| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/search/local_files_ntp_source.h" |
| |
| #include <memory> |
| |
| #if !defined(GOOGLE_CHROME_BUILD) |
| |
| #include "base/bind.h" |
| #include "base/files/file_path.h" |
| #include "base/files/file_util.h" |
| #include "base/location.h" |
| #include "base/memory/ref_counted_memory.h" |
| #include "base/path_service.h" |
| #include "base/strings/string_util.h" |
| #include "base/task_scheduler/post_task.h" |
| #include "base/threading/thread_restrictions.h" |
| #include "build/build_config.h" |
| #include "chrome/common/url_constants.h" |
| #include "content/public/browser/url_data_source.h" |
| #include "third_party/re2/src/re2/re2.h" |
| #include "third_party/re2/src/re2/stringpiece.h" |
| |
| namespace { |
| |
| const char kBasePath[] = "chrome/browser/resources/local_ntp"; |
| |
| // Matches lines of form '<include src="foo">' and captures 'foo'. |
| // TODO(treib): None of the local NTP files use this. Remove it? |
| const char kInlineResourceRegex[] = "<include.*?src\\=[\"'](.+?)[\"'].*?>"; |
| |
| // TODO(treib): local_ntp.css contains url(...) references to images, which get |
| // inlined by grit's "flattenhtml" feature during regular builds. Find some way |
| // to make that work with local files. |
| |
| void CallbackWithLoadedResource( |
| const std::string& origin, |
| const content::URLDataSource::GotDataCallback& callback, |
| const std::string& content) { |
| std::string output = content; |
| if (!origin.empty()) |
| base::ReplaceFirstSubstringAfterOffset(&output, 0, "{{ORIGIN}}", origin); |
| |
| // Strip out the integrity placeholders. CSP is disabled in local-files mode, |
| // so the integrity values aren't required. |
| base::ReplaceFirstSubstringAfterOffset(&output, 0, "{{CONFIG_INTEGRITY}}", |
| std::string()); |
| base::ReplaceFirstSubstringAfterOffset(&output, 0, "{{LOCAL_NTP_INTEGRITY}}", |
| std::string()); |
| |
| callback.Run(base::RefCountedString::TakeString(&output)); |
| } |
| |
| // Read a file to a string and return. |
| std::string ReadFileAndReturn(const base::FilePath& path) { |
| std::string data; |
| // This call can fail, but it doesn't matter for our purposes. If it fails, |
| // we simply return an empty string. |
| base::ReadFileToString(path, &data); |
| return data; |
| } |
| |
| } // namespace |
| |
| namespace local_ntp { |
| |
| void FlattenLocalInclude( |
| const content::URLDataSource::GotDataCallback& callback, |
| std::string topLevelResource, |
| scoped_refptr<base::RefCountedMemory> inlineResource); |
| |
| // Helper method invoked by both CheckLocalIncludes and FlattenLocalInclude. |
| // Checks for any <include> directives; if any are found, loads the associated |
| // file and calls FlattenLocalInclude with the result. Otherwise, processing |
| // is done, and so the original callback is invoked. |
| void CheckLocalIncludesHelper( |
| const content::URLDataSource::GotDataCallback& callback, |
| std::string& resource) { |
| std::string filename; |
| re2::StringPiece resourceWrapper(resource); |
| if (re2::RE2::FindAndConsume(&resourceWrapper, kInlineResourceRegex, |
| &filename)) { |
| content::URLDataSource::GotDataCallback wrapper = |
| base::Bind(&FlattenLocalInclude, callback, resource); |
| SendLocalFileResource(filename, wrapper); |
| } else { |
| callback.Run(base::RefCountedString::TakeString(&resource)); |
| } |
| } |
| |
| // Wrapper around the above helper function for use as a callback. Processes |
| // local files to inline any files indicated by an <include> directive. |
| void CheckLocalIncludes(const content::URLDataSource::GotDataCallback& callback, |
| scoped_refptr<base::RefCountedMemory> resource) { |
| std::string resourceAsStr(resource->front_as<char>(), resource->size()); |
| CheckLocalIncludesHelper(callback, resourceAsStr); |
| } |
| |
| // Replaces the first <include> directive found with the given file contents. |
| // Afterwards, re-invokes CheckLocalIncludesHelper to handle any subsequent |
| // <include>s, including those which may have been added by the newly-inlined |
| // resource. |
| void FlattenLocalInclude( |
| const content::URLDataSource::GotDataCallback& callback, |
| std::string topLevelResource, |
| scoped_refptr<base::RefCountedMemory> inlineResource) { |
| std::string inlineAsStr(inlineResource->front_as<char>(), |
| inlineResource->size()); |
| re2::RE2::Replace(&topLevelResource, kInlineResourceRegex, inlineAsStr); |
| CheckLocalIncludesHelper(callback, topLevelResource); |
| } |
| |
| void SendLocalFileResource( |
| const std::string& path, |
| const content::URLDataSource::GotDataCallback& callback) { |
| SendLocalFileResourceWithOrigin(path, std::string(), callback); |
| } |
| |
| void SendLocalFileResourceWithOrigin( |
| const std::string& path, |
| const std::string& origin, |
| const content::URLDataSource::GotDataCallback& callback) { |
| base::FilePath fullpath; |
| base::PathService::Get(base::DIR_SOURCE_ROOT, &fullpath); |
| fullpath = fullpath.AppendASCII(kBasePath).AppendASCII(path); |
| content::URLDataSource::GotDataCallback wrapper = |
| base::Bind(&CheckLocalIncludes, callback); |
| base::PostTaskWithTraitsAndReplyWithResult( |
| FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, |
| base::Bind(&ReadFileAndReturn, fullpath), |
| base::Bind(&CallbackWithLoadedResource, origin, wrapper)); |
| } |
| |
| } // namespace local_ntp |
| |
| #endif // !defined(GOOGLE_CHROME_BUILD) |