diff options
author | cira@chromium.org <cira@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-07 22:49:10 +0000 |
---|---|---|
committer | cira@chromium.org <cira@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-07 22:49:10 +0000 |
commit | ecabe6eed156a36238888bfd2fdb96ec4906f0a4 (patch) | |
tree | 9419d9a349fc940d45fa450b3a75169fdf48b39f /chrome | |
parent | 7050861ff094fd74d155264b6da3ca3795543870 (diff) | |
download | chromium_src-ecabe6eed156a36238888bfd2fdb96ec4906f0a4.zip chromium_src-ecabe6eed156a36238888bfd2fdb96ec4906f0a4.tar.gz chromium_src-ecabe6eed156a36238888bfd2fdb96ec4906f0a4.tar.bz2 |
Loads local resources from current locale subtree if available, if not it falls back to extension subtree.
We look for ext_root/foo/bar.js under ext_root/_locales/fr/foo/bar.js if current locale is fr. If there is no fr specific resource we load ext_root/foo/bar.js instead.
Lots of small refactoring to replace FilePath with ExtensionResource.
BUG=12131
TEST=See unittest for sample tree.
Review URL: http://codereview.chromium.org/256022
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28333 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
31 files changed, 420 insertions, 168 deletions
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc index c90870f..ac7ea52 100644 --- a/chrome/browser/extensions/crx_installer.cc +++ b/chrome/browser/extensions/crx_installer.cc @@ -124,8 +124,9 @@ void CrxInstaller::OnUnpackSuccess(const FilePath& temp_dir, } if (client_.get()) { - DecodeInstallIcon(extension_->GetIconPath(Extension::EXTENSION_ICON_LARGE), - &install_icon_); + FilePath icon_path = + extension_->GetIconPath(Extension::EXTENSION_ICON_LARGE).GetFilePath(); + DecodeInstallIcon(icon_path, &install_icon_); } ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, &CrxInstaller::ConfirmInstall)); diff --git a/chrome/browser/extensions/execute_code_in_tab_function.cc b/chrome/browser/extensions/execute_code_in_tab_function.cc index bcca094..92d6fb9 100755 --- a/chrome/browser/extensions/execute_code_in_tab_function.cc +++ b/chrome/browser/extensions/execute_code_in_tab_function.cc @@ -7,7 +7,7 @@ #include "chrome/browser/browser.h" #include "chrome/browser/extensions/extension_tabs_module.h" #include "chrome/browser/extensions/extension_tabs_module_constants.h" -#include "chrome/browser/net/file_reader.h" +#include "chrome/browser/extensions/file_reader.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_error_utils.h" @@ -80,15 +80,15 @@ bool ExecuteCodeInTabFunction::RunImpl() { if (script_info->HasKey(kFileKey)) { if (!script_info->GetString(kFileKey, &relative_path)) return false; - file_path_ = GetExtension()->GetResourcePath(relative_path); + resource_ = GetExtension()->GetResource(relative_path); } - if (file_path_.empty()) { + if (resource_.extension_root().empty() || resource_.relative_path().empty()) { error_ = keys::kNoCodeOrFileToExecuteError; return false; } scoped_refptr<FileReader> file_reader(new FileReader( - file_path_, NewCallback(this, &ExecuteCodeInTabFunction::DidLoadFile))); + resource_, NewCallback(this, &ExecuteCodeInTabFunction::DidLoadFile))); file_reader->Start(); AddRef(); // Keep us alive until DidLoadFile is called. @@ -102,10 +102,10 @@ void ExecuteCodeInTabFunction::DidLoadFile(bool success, } else { #if defined(OS_POSIX) error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kLoadFileError, - file_path_.value()); + resource_.relative_path().value()); #elif defined(OS_WIN) error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kLoadFileError, - WideToUTF8(file_path_.value())); + WideToUTF8(resource_.relative_path().value())); #endif // OS_WIN SendResponse(false); } diff --git a/chrome/browser/extensions/execute_code_in_tab_function.h b/chrome/browser/extensions/execute_code_in_tab_function.h index e887e7c..5ea91e6 100755 --- a/chrome/browser/extensions/execute_code_in_tab_function.h +++ b/chrome/browser/extensions/execute_code_in_tab_function.h @@ -10,6 +10,7 @@ #include "base/file_path.h" #include "chrome/browser/extensions/extension_function.h" +#include "chrome/common/extensions/extension_resource.h" #include "chrome/common/notification_service.h" #include "chrome/common/notification_registrar.h" @@ -40,8 +41,9 @@ class ExecuteCodeInTabFunction : public AsyncExtensionFunction, // Id of tab which executes code. int execute_tab_id_; - // Contain path of file which is specified in JSON arguments. - FilePath file_path_; + // Contains extension resource built from path of file which is + // specified in JSON arguments. + ExtensionResource resource_; }; #endif // CHROME_BROWSER_EXTENSIONS_EXECUTE_CODE_IN_TAB_FUNCTION_H__ diff --git a/chrome/browser/extensions/extension_disabled_infobar_delegate.cc b/chrome/browser/extensions/extension_disabled_infobar_delegate.cc index e3b0ca8..14cc3e7 100644 --- a/chrome/browser/extensions/extension_disabled_infobar_delegate.cc +++ b/chrome/browser/extensions/extension_disabled_infobar_delegate.cc @@ -7,11 +7,13 @@ #include "app/l10n_util.h" #include "chrome/browser/chrome_thread.h" #include "chrome/browser/extensions/crx_installer.h" +#include "chrome/browser/extensions/extension_file_util.h" #include "chrome/browser/extensions/extension_install_ui.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/browser_list.h" +#include "chrome/common/extensions/extension_resource.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/notification_service.h" #include "grit/generated_resources.h" @@ -28,7 +30,7 @@ class ExtensionDisabledDialogDelegate AddRef(); // balanced in ContinueInstall or AbortInstall. // Do this now because we can't touch extension on the file loop. - install_icon_path_ = + install_icon_resource_ = extension_->GetIconPath(Extension::EXTENSION_ICON_LARGE); ChromeThread::GetMessageLoop(ChromeThread::FILE)->PostTask(FROM_HERE, @@ -48,7 +50,8 @@ class ExtensionDisabledDialogDelegate private: void Start() { // We start on the file thread so we can decode the install icon. - CrxInstaller::DecodeInstallIcon(install_icon_path_, &install_icon_); + FilePath install_icon_path = install_icon_resource_.GetFilePath(); + CrxInstaller::DecodeInstallIcon(install_icon_path, &install_icon_); // Then we display the UI on the UI thread. ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, @@ -64,7 +67,7 @@ class ExtensionDisabledDialogDelegate Profile* profile_; ExtensionsService* service_; Extension* extension_; - FilePath install_icon_path_; + ExtensionResource install_icon_resource_; scoped_ptr<SkBitmap> install_icon_; MessageLoop* ui_loop_; }; diff --git a/chrome/browser/extensions/extension_file_util.cc b/chrome/browser/extensions/extension_file_util.cc index 28a7482..32c4819 100644 --- a/chrome/browser/extensions/extension_file_util.cc +++ b/chrome/browser/extensions/extension_file_util.cc @@ -137,7 +137,7 @@ bool ValidateExtension(Extension* extension, std::string* error) { // Validate icons exist. for (std::map<int, std::string>::const_iterator iter = extension->icons().begin(); iter != extension->icons().end(); ++iter) { - if (!file_util::PathExists(extension->GetResourcePath(iter->second))) { + if (extension->GetResource(iter->second).GetFilePath().empty()) { *error = StringPrintf("Could not load extension icon '%s'.", iter->second.c_str()); return false; @@ -172,8 +172,9 @@ bool ValidateExtension(Extension* extension, std::string* error) { const UserScript& script = extension->content_scripts()[i]; for (size_t j = 0; j < script.js_scripts().size(); j++) { - const FilePath& path = script.js_scripts()[j].path(); - if (!file_util::PathExists(path)) { + const FilePath& path = + script.js_scripts()[j].resource().GetFilePath(); + if (path.empty()) { *error = StringPrintf("Could not load '%s' for content script.", WideToUTF8(path.ToWStringHack()).c_str()); return false; @@ -181,8 +182,9 @@ bool ValidateExtension(Extension* extension, std::string* error) { } for (size_t j = 0; j < script.css_scripts().size(); j++) { - const FilePath& path = script.css_scripts()[j].path(); - if (!file_util::PathExists(path)) { + const FilePath& path = + script.css_scripts()[j].resource().GetFilePath(); + if (path.empty()) { *error = StringPrintf("Could not load '%s' for content script.", WideToUTF8(path.ToWStringHack()).c_str()); return false; @@ -219,7 +221,7 @@ bool ValidateExtension(Extension* extension, std::string* error) { const std::vector<std::string>& icon_paths = page_action->icon_paths(); for (std::vector<std::string>::const_iterator iter = icon_paths.begin(); iter != icon_paths.end(); ++iter) { - if (!file_util::PathExists(extension->GetResourcePath(*iter))) { + if (extension->GetResource(*iter).GetFilePath().empty()) { *error = StringPrintf("Could not load icon '%s' for page action.", iter->c_str()); return false; @@ -233,7 +235,7 @@ bool ValidateExtension(Extension* extension, std::string* error) { const std::vector<std::string>& icon_paths = browser_action->icon_paths(); for (std::vector<std::string>::const_iterator iter = icon_paths.begin(); iter != icon_paths.end(); ++iter) { - if (!file_util::PathExists(extension->GetResourcePath(*iter))) { + if (extension->GetResource(*iter).GetFilePath().empty()) { *error = StringPrintf("Could not load icon '%s' for browser action.", iter->c_str()); return false; diff --git a/chrome/browser/extensions/extension_l10n_util.cc b/chrome/browser/extensions/extension_l10n_util.cc index 2c66ff9..411de59 100644 --- a/chrome/browser/extensions/extension_l10n_util.cc +++ b/chrome/browser/extensions/extension_l10n_util.cc @@ -144,4 +144,16 @@ ExtensionMessageBundle* LoadMessageCatalogs( error); } +FilePath GetL10nRelativePath(const FilePath& relative_resource_path) { + // Get locale relative path. + static std::string current_locale = l10n_util::GetApplicationLocale(L""); + std::replace(current_locale.begin(), current_locale.end(), '-', '_'); + + FilePath locale_relative_path; + return locale_relative_path + .AppendASCII(Extension::kLocaleFolder) + .AppendASCII(current_locale) + .Append(relative_resource_path); +} + } // namespace extension_l10n_util diff --git a/chrome/browser/extensions/extension_l10n_util.h b/chrome/browser/extensions/extension_l10n_util.h index 98759ab..b3be601 100644 --- a/chrome/browser/extensions/extension_l10n_util.h +++ b/chrome/browser/extensions/extension_l10n_util.h @@ -55,6 +55,9 @@ ExtensionMessageBundle* LoadMessageCatalogs(const FilePath& locale_path, const std::string& app_locale, std::string* error); +// Returns relative l10n path to the resource. +FilePath GetL10nRelativePath(const FilePath& relative_resource_path); + } // namespace extension_l10n_util #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_L10N_UTIL_H_ diff --git a/chrome/browser/extensions/extension_l10n_util_unittest.cc b/chrome/browser/extensions/extension_l10n_util_unittest.cc index f674f69..5c0df39 100644 --- a/chrome/browser/extensions/extension_l10n_util_unittest.cc +++ b/chrome/browser/extensions/extension_l10n_util_unittest.cc @@ -4,6 +4,7 @@ #include "chrome/browser/extensions/extension_l10n_util.h" +#include "app/l10n_util.h" #include "base/file_path.h" #include "base/file_util.h" #include "base/path_service.h" @@ -143,4 +144,34 @@ TEST(ExtensionL10nUtil, LoadMessageCatalogsDuplicateKeys) { EXPECT_TRUE(error.empty()); } +bool PathsAreEqual(const FilePath& path1, const FilePath& path2) { + FilePath::StringType path1_str = path1.value(); + std::replace(path1_str.begin(), path1_str.end(), '\\', '/'); + + FilePath::StringType path2_str = path2.value(); + std::replace(path2_str.begin(), path2_str.end(), '\\', '/'); + + if (path1_str == path2_str) { + return true; + } else { + return false; + } +} + +TEST(ExtensionL10nUtil, GetL10nRelativePath) { + static std::string current_locale = l10n_util::GetApplicationLocale(L""); + std::replace(current_locale.begin(), current_locale.end(), '-', '_'); + + FilePath locale_path; + locale_path = locale_path + .AppendASCII(Extension::kLocaleFolder) + .AppendASCII(current_locale) + .AppendASCII("foo") + .AppendASCII("bar.js"); + + FilePath result = extension_l10n_util::GetL10nRelativePath( + FilePath(FILE_PATH_LITERAL("foo/bar.js"))); + EXPECT_TRUE(PathsAreEqual(locale_path, result)); +} + } // namespace diff --git a/chrome/browser/extensions/extension_protocols.cc b/chrome/browser/extensions/extension_protocols.cc index 3ff9c51..3be8337 100644 --- a/chrome/browser/extensions/extension_protocols.cc +++ b/chrome/browser/extensions/extension_protocols.cc @@ -7,6 +7,7 @@ #include "base/string_util.h" #include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_resource.h" #include "chrome/common/url_constants.h" #include "googleurl/src/url_util.h" #include "net/base/net_util.h" @@ -26,10 +27,10 @@ static URLRequestJob* CreateExtensionURLRequestJob(URLRequest* request, return NULL; } - std::string resource = request->url().path(); - FilePath path = Extension::GetResourcePath(directory_path, resource); + ExtensionResource resource = + Extension::GetResource(directory_path, request->url().path()); - return new URLRequestFileJob(request, path); + return new URLRequestFileJob(request, resource.GetFilePath()); } // Factory registered with URLRequest to create URLRequestJobs for @@ -41,10 +42,11 @@ static URLRequestJob* CreateUserScriptURLRequestJob(URLRequest* request, // chrome-user-script:/user-script-name.user.js FilePath directory_path = context->user_script_dir_path(); - std::string resource = request->url().path(); - FilePath path = Extension::GetResourcePath(directory_path, resource); - return new URLRequestFileJob(request, path); + ExtensionResource resource = + Extension::GetResource(directory_path, request->url().path()); + + return new URLRequestFileJob(request, resource.GetFilePath()); } void RegisterExtensionProtocols() { diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc index fa257e0..578bde2 100644 --- a/chrome/browser/extensions/extensions_service_unittest.cc +++ b/chrome/browser/extensions/extensions_service_unittest.cc @@ -540,21 +540,15 @@ TEST_F(ExtensionsServiceTest, LoadAllExtensionsFromDirectorySuccess) { EXPECT_EQ("https://*.google.com/*", scripts[0].url_patterns()[2].GetAsString()); EXPECT_EQ(2u, scripts[0].js_scripts().size()); - EXPECT_EQ( - NormalizeSeperators(extension->path().AppendASCII("script1.js").value()), - NormalizeSeperators(scripts[0].js_scripts()[0].path().value())); - EXPECT_EQ( - NormalizeSeperators(extension->path().AppendASCII("script2.js").value()), - NormalizeSeperators(scripts[0].js_scripts()[1].path().value())); + EXPECT_TRUE(scripts[0].js_scripts()[0].resource().ComparePathWithDefault( + extension->path().AppendASCII("script1.js"))); + EXPECT_TRUE(scripts[0].js_scripts()[1].resource().ComparePathWithDefault( + extension->path().AppendASCII("script2.js"))); EXPECT_TRUE(extension->plugins().empty()); EXPECT_EQ(1u, scripts[1].url_patterns().size()); EXPECT_EQ("http://*.news.com/*", scripts[1].url_patterns()[0].GetAsString()); - EXPECT_EQ( - NormalizeSeperators(extension->path() - .AppendASCII("js_files") - .AppendASCII("script3.js") - .value()), - NormalizeSeperators(scripts[1].js_scripts()[0].path().value())); + EXPECT_TRUE(scripts[1].js_scripts()[0].resource().ComparePathWithDefault( + extension->path().AppendASCII("js_files").AppendASCII("script3.js"))); const std::vector<URLPattern> permissions = extension->host_permissions(); ASSERT_EQ(2u, permissions.size()); EXPECT_EQ("http://*.google.com/*", permissions[0].GetAsString()); diff --git a/chrome/browser/extensions/extensions_ui.cc b/chrome/browser/extensions/extensions_ui.cc index db10a9a..7313f50 100644 --- a/chrome/browser/extensions/extensions_ui.cc +++ b/chrome/browser/extensions/extensions_ui.cc @@ -239,15 +239,11 @@ static void CreateScriptFileDetailValue( ListValue *list = new ListValue(); for (size_t i = 0; i < scripts.size(); ++i) { - const UserScript::File &file = scripts[i]; - // We are passing through GURLs to canonicalize the output to a valid - // URL path fragment. - GURL script_url = net::FilePathToFileURL(file.path()); - GURL extension_url = net::FilePathToFileURL(extension_path); - std::string relative_path = - script_url.spec().substr(extension_url.spec().length() + 1); - - list->Append(new StringValue(relative_path)); + const UserScript::File& file = scripts[i]; + // TODO(cira): this information is not used on extension page yet. We + // may want to display actual resource that got loaded, not default. + list->Append( + new StringValue(file.resource().relative_path().value())); } script_data->Set(key, list); } @@ -292,8 +288,8 @@ DictionaryValue* ExtensionsDOMHandler::CreateExtensionDetailValue( UserScriptList content_scripts = extension->content_scripts(); for (UserScriptList::const_iterator script = content_scripts.begin(); script != content_scripts.end(); ++script) { - content_script_list->Append(CreateContentScriptDetailValue(*script, - extension->path())); + content_script_list->Append( + CreateContentScriptDetailValue(*script, extension->path())); } extension_data->Set(L"content_scripts", content_script_list); diff --git a/chrome/browser/net/file_reader.cc b/chrome/browser/extensions/file_reader.cc index 9e3041e..955e664 100644 --- a/chrome/browser/net/file_reader.cc +++ b/chrome/browser/extensions/file_reader.cc @@ -2,13 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/net/file_reader.h" +#include "chrome/browser/extensions/file_reader.h" #include "base/file_util.h" #include "chrome/browser/chrome_thread.h" +#include "chrome/common/extensions/extension_resource.h" -FileReader::FileReader(const FilePath& path, Callback* callback) - : path_(path), +FileReader::FileReader(const ExtensionResource& resource, Callback* callback) + : resource_(resource), callback_(callback), origin_loop_(MessageLoop::current()) { DCHECK(callback_); @@ -21,7 +22,7 @@ void FileReader::Start() { void FileReader::ReadFileOnBackgroundThread() { std::string data; - bool success = file_util::ReadFileToString(path_, &data); + bool success = file_util::ReadFileToString(resource_.GetFilePath(), &data); origin_loop_->PostTask(FROM_HERE, NewRunnableMethod( this, &FileReader::RunCallback, success, data)); } diff --git a/chrome/browser/net/file_reader.h b/chrome/browser/extensions/file_reader.h index 7aa52f1..008450e 100644 --- a/chrome/browser/net/file_reader.h +++ b/chrome/browser/extensions/file_reader.h @@ -1,27 +1,28 @@ // Copyright (c) 2009 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. -// -// This file defines an interface for reading a file asynchronously on a -// background thread. -#ifndef CHROME_BROWSER_NET_FILE_READER_H_ -#define CHROME_BROWSER_NET_FILE_READER_H_ +#ifndef CHROME_BROWSER_EXTENSIONS_FILE_READER_H_ +#define CHROME_BROWSER_EXTENSIONS_FILE_READER_H_ #include <string> -#include "base/file_path.h" #include "base/ref_counted.h" #include "base/task.h" +#include "chrome/common/extensions/extension_resource.h" class MessageLoop; +// This file defines an interface for reading a file asynchronously on a +// background thread. +// Consider abstracting out a FilePathProvider (ExtensionResource) and moving +// back to chrome/browser/net if other subsystems want to use it. class FileReader : public base::RefCountedThreadSafe<FileReader> { public: // Reports success or failure and the data of the file upon success. typedef Callback2<bool, const std::string&>::Type Callback; - FileReader(const FilePath& path, Callback* callback); + FileReader(const ExtensionResource& resource, Callback* callback); // Called to start reading the file on a background thread. Upon completion, // the callback will be notified of the results. @@ -31,9 +32,9 @@ class FileReader : public base::RefCountedThreadSafe<FileReader> { void ReadFileOnBackgroundThread(); void RunCallback(bool success, const std::string& data); - FilePath path_; + ExtensionResource resource_; Callback* callback_; MessageLoop* origin_loop_; }; -#endif // CHROME_BROWSER_NET_FILE_READER_H_ +#endif // CHROME_BROWSER_EXTENSIONS_FILE_READER_H_ diff --git a/chrome/browser/net/file_reader_unittest.cc b/chrome/browser/extensions/file_reader_unittest.cc index 72c3f42..bf16b71 100644 --- a/chrome/browser/net/file_reader_unittest.cc +++ b/chrome/browser/extensions/file_reader_unittest.cc @@ -2,12 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/file_path.h" #include "base/file_util.h" #include "base/message_loop.h" #include "base/path_service.h" #include "chrome/browser/chrome_thread.h" -#include "chrome/browser/net/file_reader.h" +#include "chrome/browser/extensions/file_reader.h" #include "chrome/common/chrome_paths.h" +#include "chrome/common/extensions/extension_resource.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -48,6 +50,7 @@ class Receiver { void RunBasicTest(const char* filename) { FilePath path; PathService::Get(chrome::DIR_TEST_DATA, &path); + ExtensionResource resource(path, FilePath().AppendASCII(filename)); path = path.AppendASCII(filename); std::string file_contents; @@ -56,7 +59,7 @@ void RunBasicTest(const char* filename) { Receiver receiver; scoped_refptr<FileReader> file_reader( - new FileReader(path, receiver.NewCallback())); + new FileReader(resource, receiver.NewCallback())); file_reader->Start(); MessageLoop::current()->Run(); @@ -76,12 +79,14 @@ TEST_F(FileReaderTest, BiggerFile) { TEST_F(FileReaderTest, NonExistantFile) { FilePath path; PathService::Get(chrome::DIR_TEST_DATA, &path); + ExtensionResource resource(path, FilePath( + FILE_PATH_LITERAL("file_that_does_not_exist"))); path = path.AppendASCII("file_that_does_not_exist"); Receiver receiver; scoped_refptr<FileReader> file_reader( - new FileReader(path, receiver.NewCallback())); + new FileReader(resource, receiver.NewCallback())); file_reader->Start(); MessageLoop::current()->Run(); diff --git a/chrome/browser/image_loading_tracker.cc b/chrome/browser/extensions/image_loading_tracker.cc index 423e5fd..e141391 100644 --- a/chrome/browser/image_loading_tracker.cc +++ b/chrome/browser/extensions/image_loading_tracker.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/image_loading_tracker.h" +#include "chrome/browser/extensions/image_loading_tracker.h" #include "app/gfx/favicon_size.h" #include "base/file_util.h" @@ -12,6 +12,7 @@ #include "base/task.h" #include "base/thread.h" #include "chrome/browser/browser_process.h" +#include "chrome/common/extensions/extension_resource.h" #include "skia/ext/image_operations.h" #include "third_party/skia/include/core/SkBitmap.h" #include "webkit/glue/image_decoder.h" @@ -29,11 +30,11 @@ class ImageLoadingTracker::LoadImageTask : public Task { // decode it. |path| is the path to load the image from. |index| is an // identifier for the image that we pass back to the caller. LoadImageTask(ImageLoadingTracker* tracker, - const FilePath& path, + const ExtensionResource& resource, size_t index) : callback_loop_(MessageLoop::current()), tracker_(tracker), - path_(path), + resource_(resource), index_(index) {} void ReportBack(SkBitmap* image) { @@ -47,8 +48,8 @@ class ImageLoadingTracker::LoadImageTask : public Task { virtual void Run() { // Read the file from disk. std::string file_contents; - if (!file_util::PathExists(path_) || - !file_util::ReadFileToString(path_, &file_contents)) { + FilePath path = resource_.GetFilePath(); + if (path.empty() || !file_util::ReadFileToString(path, &file_contents)) { ReportBack(NULL); return; } @@ -85,8 +86,8 @@ class ImageLoadingTracker::LoadImageTask : public Task { // The object that is waiting for us to respond back. ImageLoadingTracker* tracker_; - // The path to the image to load asynchronously. - FilePath path_; + // The image resource to load asynchronously. + ExtensionResource resource_; // The index of the icon being loaded. size_t index_; @@ -95,9 +96,9 @@ class ImageLoadingTracker::LoadImageTask : public Task { //////////////////////////////////////////////////////////////////////////////// // ImageLoadingTracker -void ImageLoadingTracker::PostLoadImageTask(FilePath path) { +void ImageLoadingTracker::PostLoadImageTask(const ExtensionResource& resource) { MessageLoop* file_loop = g_browser_process->file_thread()->message_loop(); - file_loop->PostTask(FROM_HERE, new LoadImageTask(this, path, + file_loop->PostTask(FROM_HERE, new LoadImageTask(this, resource, posted_count_++)); } diff --git a/chrome/browser/image_loading_tracker.h b/chrome/browser/extensions/image_loading_tracker.h index 7265b63..9732a00 100644 --- a/chrome/browser/image_loading_tracker.h +++ b/chrome/browser/extensions/image_loading_tracker.h @@ -2,18 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_IMAGE_LOADING_TRACKER_H_ -#define CHROME_BROWSER_IMAGE_LOADING_TRACKER_H_ +#ifndef CHROME_BROWSER_EXTENSIONS_IMAGE_LOADING_TRACKER_H_ +#define CHROME_BROWSER_EXTENSIONS_IMAGE_LOADING_TRACKER_H_ #include "base/ref_counted.h" -class FilePath; +class ExtensionResource; class SkBitmap; // The views need to load their icons asynchronously but might be deleted before // the images have loaded. This class stays alive while the request is in // progress (manages its own lifetime) and keeps track of whether the view still // cares about the icon loading. +// Consider abstracting out a FilePathProvider (ExtensionResource) and moving +// back to chrome/browser/ if other subsystems want to use it. class ImageLoadingTracker : public base::RefCountedThreadSafe<ImageLoadingTracker> { public: @@ -40,10 +42,10 @@ class ImageLoadingTracker observer_ = NULL; } - // Specify path of image to load. This method must be called a number of + // Specify image resource to load. This method must be called a number of // times equal to the |image_count| arugment to the constructor. Calling it // any more or less than that is an error. - void PostLoadImageTask(FilePath path); + void PostLoadImageTask(const ExtensionResource& resource); private: class LoadImageTask; @@ -69,4 +71,4 @@ class ImageLoadingTracker DISALLOW_COPY_AND_ASSIGN(ImageLoadingTracker); }; -#endif // CHROME_BROWSER_IMAGE_LOADING_TRACKER_H_ +#endif // CHROME_BROWSER_EXTENSIONS_IMAGE_LOADING_TRACKER_H_ diff --git a/chrome/browser/extensions/user_script_master.cc b/chrome/browser/extensions/user_script_master.cc index b4130c8..f58a9e6 100644 --- a/chrome/browser/extensions/user_script_master.cc +++ b/chrome/browser/extensions/user_script_master.cc @@ -136,20 +136,20 @@ void UserScriptMaster::ScriptReloader::NotifyMaster( static bool LoadScriptContent(UserScript::File* script_file) { std::string content; - if (!file_util::ReadFileToString(script_file->path(), &content)) { - LOG(WARNING) << "Failed to load user script file: " - << script_file->path().value(); + FilePath path = script_file->resource().GetFilePath(); + if (path.empty() || !file_util::ReadFileToString(path, &content)) { + LOG(WARNING) << "Failed to load user script file: " << path.value(); return false; } script_file->set_content(content); - LOG(INFO) << "Loaded user script file: " << script_file->path().value(); + LOG(INFO) << "Loaded user script file: " << path.value(); return true; } void UserScriptMaster::ScriptReloader::LoadScriptsFromDirectory( const FilePath& script_dir, UserScriptList* result) { - // Clear the list. We will populate it with the scrips found in script_dir. + // Clear the list. We will populate it with the scripts found in script_dir. result->clear(); // Find all the scripts in |script_dir|. @@ -168,7 +168,8 @@ void UserScriptMaster::ScriptReloader::LoadScriptsFromDirectory( // Push single js file in this UserScript. GURL url(std::string(chrome::kUserScriptScheme) + ":/" + net::FilePathToFileURL(file).ExtractFileName()); - user_script.js_scripts().push_back(UserScript::File(file, url)); + ExtensionResource resource(script_dir, file.BaseName()); + user_script.js_scripts().push_back(UserScript::File(resource, url)); UserScript::File& script_file = user_script.js_scripts().back(); if (!LoadScriptContent(&script_file)) result->pop_back(); diff --git a/chrome/browser/gtk/location_bar_view_gtk.cc b/chrome/browser/gtk/location_bar_view_gtk.cc index a728022..ee6424c 100644 --- a/chrome/browser/gtk/location_bar_view_gtk.cc +++ b/chrome/browser/gtk/location_bar_view_gtk.cc @@ -695,7 +695,7 @@ LocationBarViewGtk::PageActionViewGtk::PageActionViewGtk( tracker_ = new ImageLoadingTracker(this, icon_paths.size()); for (std::vector<std::string>::const_iterator iter = icon_paths.begin(); iter != icon_paths.end(); ++iter) { - tracker_->PostLoadImageTask(extension->GetResourcePath(*iter)); + tracker_->PostLoadImageTask(extension->GetResource(*iter)); } } diff --git a/chrome/browser/gtk/location_bar_view_gtk.h b/chrome/browser/gtk/location_bar_view_gtk.h index bb86a69..3fe531a 100644 --- a/chrome/browser/gtk/location_bar_view_gtk.h +++ b/chrome/browser/gtk/location_bar_view_gtk.h @@ -15,7 +15,7 @@ #include "base/scoped_vector.h" #include "chrome/browser/autocomplete/autocomplete_edit.h" #include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" -#include "chrome/browser/image_loading_tracker.h" +#include "chrome/browser/extensions/image_loading_tracker.h" #include "chrome/browser/location_bar.h" #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" diff --git a/chrome/browser/views/browser_actions_container.cc b/chrome/browser/views/browser_actions_container.cc index 9fdd2fd..4a246f2 100644 --- a/chrome/browser/views/browser_actions_container.cc +++ b/chrome/browser/views/browser_actions_container.cc @@ -10,7 +10,7 @@ #include "chrome/browser/extensions/extension_browser_event_router.h" #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/extensions/extension_tabs_module.h" -#include "chrome/browser/image_loading_tracker.h" +#include "chrome/browser/extensions/image_loading_tracker.h" #include "chrome/browser/profile.h" #include "chrome/browser/views/extensions/extension_popup.h" #include "chrome/browser/views/toolbar_view.h" @@ -129,8 +129,7 @@ BrowserActionButton::BrowserActionButton( tracker_ = new ImageLoadingTracker(this, icon_paths.size()); for (std::vector<std::string>::const_iterator iter = icon_paths.begin(); iter != icon_paths.end(); ++iter) { - FilePath path = extension->GetResourcePath(*iter); - tracker_->PostLoadImageTask(path); + tracker_->PostLoadImageTask(extension->GetResource(*iter)); } registrar_.Add(this, NotificationType::EXTENSION_BROWSER_ACTION_UPDATED, @@ -251,7 +250,7 @@ class BrowserActionView : public views::View { private: virtual void Layout(); - + // Override PaintChildren so that we can paint the badge on top of children. virtual void PaintChildren(gfx::Canvas* canvas); @@ -270,7 +269,7 @@ void BrowserActionView::Layout() { button_->SetBounds(0, kControlVertOffset, width(), height() - 2 * kControlVertOffset); } - + void BrowserActionView::PaintChildren(gfx::Canvas* canvas) { View::PaintChildren(canvas); diff --git a/chrome/browser/views/location_bar_view.cc b/chrome/browser/views/location_bar_view.cc index ee8eb90..b7a97a7 100644 --- a/chrome/browser/views/location_bar_view.cc +++ b/chrome/browser/views/location_bar_view.cc @@ -1204,8 +1204,7 @@ LocationBarView::PageActionImageView::PageActionImageView( tracker_ = new ImageLoadingTracker(this, icon_paths.size()); for (std::vector<std::string>::const_iterator iter = icon_paths.begin(); iter != icon_paths.end(); ++iter) { - FilePath path = extension->GetResourcePath(*iter); - tracker_->PostLoadImageTask(path); + tracker_->PostLoadImageTask(extension->GetResource(*iter)); } } diff --git a/chrome/browser/views/location_bar_view.h b/chrome/browser/views/location_bar_view.h index b315e75..fb8b249 100644 --- a/chrome/browser/views/location_bar_view.h +++ b/chrome/browser/views/location_bar_view.h @@ -11,7 +11,7 @@ #include "app/gfx/font.h" #include "base/gfx/rect.h" #include "chrome/browser/autocomplete/autocomplete_edit.h" -#include "chrome/browser/image_loading_tracker.h" +#include "chrome/browser/extensions/image_loading_tracker.h" #include "chrome/browser/location_bar.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/toolbar_model.h" diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index fb39caf..07b32bd 100755 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -499,6 +499,8 @@ 'common/extensions/extension_action.h', 'common/extensions/extension_message_bundle.cc', 'common/extensions/extension_message_bundle.h', + 'common/extensions/extension_resource.cc', + 'common/extensions/extension_resource.h', 'common/extensions/extension_unpacker.cc', 'common/extensions/extension_unpacker.h', 'common/extensions/update_manifest.cc', @@ -1281,8 +1283,12 @@ 'browser/extensions/external_registry_extension_provider_win.h', 'browser/extensions/external_pref_extension_provider.cc', 'browser/extensions/external_pref_extension_provider.h', + 'browser/extensions/file_reader.cc', + 'browser/extensions/file_reader.h', 'browser/extensions/gtk_theme_preview_infobar_delegate.cc', 'browser/extensions/gtk_theme_preview_infobar_delegate.h', + 'browser/extensions/image_loading_tracker.cc', + 'browser/extensions/image_loading_tracker.h', 'browser/extensions/pack_extension_job.cc', 'browser/extensions/pack_extension_job.h', 'browser/extensions/sandboxed_extension_unpacker.cc', @@ -1553,8 +1559,6 @@ 'browser/icon_manager_linux.cc', 'browser/icon_manager_mac.mm', 'browser/icon_manager_win.cc', - 'browser/image_loading_tracker.cc', - 'browser/image_loading_tracker.h', 'browser/ime_input.cc', 'browser/ime_input.h', 'browser/importer/firefox2_importer.cc', @@ -1660,8 +1664,6 @@ 'browser/net/dns_host_info.h', 'browser/net/dns_master.cc', 'browser/net/dns_master.h', - 'browser/net/file_reader.cc', - 'browser/net/file_reader.h', 'browser/net/metadata_url_request.cc', 'browser/net/metadata_url_request.h', 'browser/net/referrer.cc', @@ -4251,6 +4253,7 @@ 'browser/extensions/extension_ui_unittest.cc', 'browser/extensions/extension_updater_unittest.cc', 'browser/extensions/extensions_service_unittest.cc', + 'browser/extensions/file_reader_unittest.cc', 'browser/extensions/user_script_listener_unittest.cc', 'browser/extensions/user_script_master_unittest.cc', 'browser/find_backend_unittest.cc', @@ -4303,7 +4306,6 @@ 'browser/net/chrome_url_request_context_unittest.cc', 'browser/net/dns_host_info_unittest.cc', 'browser/net/dns_master_unittest.cc', - 'browser/net/file_reader_unittest.cc', 'browser/net/resolve_proxy_msg_helper_unittest.cc', 'browser/net/test_url_fetcher_factory.cc', 'browser/net/test_url_fetcher_factory.h', @@ -4368,6 +4370,7 @@ 'common/child_process_logging_mac_unittest.mm', 'common/chrome_plugin_unittest.cc', 'common/common_param_traits_unittest.cc', + 'common/extensions/extension_resource_unittest.cc', 'common/extensions/extension_unittest.cc', 'common/extensions/extension_message_bundle_unittest.cc', 'common/extensions/update_manifest_unittest.cc', diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc index f00db65..ccfe787 100644 --- a/chrome/common/extensions/extension.cc +++ b/chrome/common/extensions/extension.cc @@ -13,6 +13,7 @@ #include "base/stl_util-inl.h" #include "base/third_party/nss/blapi.h" #include "base/third_party/nss/sha256.h" +#include "chrome/browser/extensions/extension_l10n_util.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/extensions/extension_constants.h" #include "chrome/common/extensions/extension_error_reporter.h" @@ -21,7 +22,6 @@ #include "chrome/common/notification_service.h" #include "chrome/common/url_constants.h" #include "net/base/base64.h" -#include "net/base/net_util.h" #if defined(OS_WIN) #include "base/registry.h" @@ -282,8 +282,8 @@ bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script, } // TODO(georged): Make GetResourceURL accept wstring too GURL url = GetResourceURL(WideToUTF8(relative)); - FilePath path = GetResourcePath(WideToUTF8(relative)); - result->js_scripts().push_back(UserScript::File(path, url)); + ExtensionResource resource = GetResource(WideToUTF8(relative)); + result->js_scripts().push_back(UserScript::File(resource, url)); } } @@ -299,8 +299,8 @@ bool Extension::LoadUserScriptHelper(const DictionaryValue* content_script, } // TODO(georged): Make GetResourceURL accept wstring too GURL url = GetResourceURL(WideToUTF8(relative)); - FilePath path = GetResourcePath(WideToUTF8(relative)); - result->css_scripts().push_back(UserScript::File(path, url)); + ExtensionResource resource = GetResource(WideToUTF8(relative)); + result->css_scripts().push_back(UserScript::File(resource, url)); } } @@ -427,37 +427,11 @@ bool Extension::ContainsNonThemeKeys(const DictionaryValue& source) { } // static -FilePath Extension::GetResourcePath(const FilePath& extension_path, - const std::string& relative_path) { - // Build up a file:// URL and convert that back to a FilePath. This avoids - // URL encoding and path separator issues. - - // Convert the extension's root to a file:// URL. - GURL extension_url = net::FilePathToFileURL(extension_path); - if (!extension_url.is_valid()) - return FilePath(); - - // Append the requested path. - GURL::Replacements replacements; - std::string new_path(extension_url.path()); - new_path += "/"; - new_path += relative_path; - replacements.SetPathStr(new_path); - GURL file_url = extension_url.ReplaceComponents(replacements); - if (!file_url.is_valid()) - return FilePath(); - - // Convert the result back to a FilePath. - FilePath ret_val; - if (!net::FileURLToFilePath(file_url, &ret_val)) - return FilePath(); - - // Double-check that the path we ended up with is actually inside the - // extension root. - if (!extension_path.IsParent(ret_val)) - return FilePath(); - - return ret_val; +ExtensionResource Extension::GetResource(const FilePath& extension_path, + const std::string& relative_path) { + FilePath relative_resource_path; + return ExtensionResource(extension_path, + relative_resource_path.AppendASCII(relative_path)); } Extension::Extension(const FilePath& path) @@ -1119,12 +1093,12 @@ void Extension::SetBackgroundPageReady() { NotificationService::NoDetails()); } -FilePath Extension::GetIconPath(Icons icon) { +ExtensionResource Extension::GetIconPath(Icons icon) { std::map<int, std::string>::const_iterator iter = icons_.find(Extension::EXTENSION_ICON_LARGE); if (iter == icons_.end()) - return FilePath(); - return GetResourcePath(iter->second); + return ExtensionResource(); + return GetResource(iter->second); } bool Extension::CanAccessHost(const GURL& url) const { diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h index c01d948..57337de 100644 --- a/chrome/common/extensions/extension.h +++ b/chrome/common/extensions/extension.h @@ -17,6 +17,7 @@ #include "chrome/browser/extensions/user_script_master.h" #include "chrome/common/extensions/extension_action.h" #include "chrome/common/extensions/extension_message_bundle.h" +#include "chrome/common/extensions/extension_resource.h" #include "chrome/common/extensions/user_script.h" #include "chrome/common/extensions/url_pattern.h" #include "googleurl/src/gurl.h" @@ -132,15 +133,14 @@ class Extension { return GetResourceURL(url(), relative_path); } - // Returns an absolute path to a resource inside of an extension. The - // |extension_path| argument should be the path() from an Extension object. - // The |relative_path| can be untrusted user input. The returned path will - // either be empty or a child of extension_path. + // Returns an extension resource object. The |extension_path| argument should + // be the path() from an Extension object. + // The |relative_path| can be untrusted user input. // NOTE: Static so that it can be used from multiple threads. - static FilePath GetResourcePath(const FilePath& extension_path, - const std::string& relative_path); - FilePath GetResourcePath(const std::string& relative_path) { - return GetResourcePath(path(), relative_path); + static ExtensionResource GetResource(const FilePath& extension_path, + const std::string& relative_path); + ExtensionResource GetResource(const std::string& relative_path) { + return GetResource(path(), relative_path); } // |input| is expected to be the text of an rsa public or private key. It @@ -243,7 +243,7 @@ class Extension { // Returns an absolute path to the given icon inside of the extension. Returns // an empty FilePath if the extension does not have that icon. - FilePath GetIconPath(Icons icon); + ExtensionResource GetIconPath(Icons icon); const DictionaryValue* manifest_value() const { return manifest_value_.get(); diff --git a/chrome/common/extensions/extension_resource.cc b/chrome/common/extensions/extension_resource.cc new file mode 100644 index 0000000..f64354f --- /dev/null +++ b/chrome/common/extensions/extension_resource.cc @@ -0,0 +1,100 @@ +// Copyright (c) 2009 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/common/extensions/extension_resource.h" + +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/string_util.h" +#include "chrome/browser/extensions/extension_l10n_util.h" +#include "googleurl/src/gurl.h" +#include "net/base/net_util.h" + +ExtensionResource::ExtensionResource() { +} + +ExtensionResource::ExtensionResource(const FilePath& extension_root, + const FilePath& relative_path) + : extension_root_(extension_root), + relative_path_(relative_path) { +} + +const FilePath& ExtensionResource::GetFilePath() const { + if (extension_root_.empty() || relative_path_.empty()) + return full_resource_path_; + + // We've already checked, just return last value. + if (!full_resource_path_.empty()) + return full_resource_path_; + + // Stat l10n file, and return new path if it exists. + FilePath l10n_relative_path = + extension_l10n_util::GetL10nRelativePath(relative_path_); + full_resource_path_ = CombinePathsSafely(extension_root_, l10n_relative_path); + if (file_util::PathExists(full_resource_path_)) { + return full_resource_path_; + } + + // Fall back to root resource. + full_resource_path_ = CombinePathsSafely(extension_root_, relative_path_); + return full_resource_path_; +} + +FilePath ExtensionResource::CombinePathsSafely( + const FilePath& extension_path, + const FilePath& relative_resource_path) const { + // Build up a file:// URL and convert that back to a FilePath. This avoids + // URL encoding and path separator issues. + + // Convert the extension's root to a file:// URL. + GURL extension_url = net::FilePathToFileURL(extension_path); + if (!extension_url.is_valid()) + return FilePath(); + + // Append the requested path. + std::string relative_path = + WideToUTF8(relative_resource_path.ToWStringHack()); + GURL::Replacements replacements; + std::string new_path(extension_url.path()); + new_path += "/"; + new_path += relative_path; + replacements.SetPathStr(new_path); + GURL file_url = extension_url.ReplaceComponents(replacements); + if (!file_url.is_valid()) + return FilePath(); + + // Convert the result back to a FilePath. + FilePath ret_val; + if (!net::FileURLToFilePath(file_url, &ret_val)) + return FilePath(); + + // Double-check that the path we ended up with is actually inside the + // extension root. + if (!extension_path.IsParent(ret_val)) + return FilePath(); + + return ret_val; +} + +// Unittesting helpers. +FilePath::StringType ExtensionResource::NormalizeSeperators( + FilePath::StringType path) const { +#if defined(FILE_PATH_USES_WIN_SEPARATORS) + FilePath::StringType ret_val; + for (size_t i = 0; i < path.length(); i++) { + if (FilePath::IsSeparator(path[i])) + path[i] = FilePath::kSeparators[0]; + } +#endif // FILE_PATH_USES_WIN_SEPARATORS + return path; +} + +bool ExtensionResource::ComparePathWithDefault(const FilePath& path) const { + if (NormalizeSeperators(path.value()) == + NormalizeSeperators(full_resource_path_.value())) { + return true; + } else { + return false; + } +} diff --git a/chrome/common/extensions/extension_resource.h b/chrome/common/extensions/extension_resource.h new file mode 100644 index 0000000..7d6e70c6 --- /dev/null +++ b/chrome/common/extensions/extension_resource.h @@ -0,0 +1,49 @@ +// Copyright (c) 2009 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. + +#ifndef CHROME_COMMON_EXTENSIONS_EXTENSION_RESOURCE_H_ +#define CHROME_COMMON_EXTENSIONS_EXTENSION_RESOURCE_H_ + +#include "base/file_path.h" + +// Represents a resource inside an extension. For example, an image, or a +// JavaScript file. This is more complicated than just a simple FilePath +// because extension resources can come from multiple physical file locations +// depending on locale. +class ExtensionResource { + public: + ExtensionResource(); + + ExtensionResource(const FilePath& extension_root, + const FilePath& relative_path); + + // Returns actual path to the resource (default or locale specific). + // *** MIGHT HIT FILESYSTEM. Do not call on UI thread! *** + const FilePath& GetFilePath() const; + + // Getters + const FilePath& extension_root() const { return extension_root_; } + const FilePath& relative_path() const { return relative_path_; } + + // Unittest helpers. + FilePath::StringType NormalizeSeperators(FilePath::StringType path) const; + bool ComparePathWithDefault(const FilePath& path) const; + + private: + // Returns normalized full path to the resource. + // Resource doesn't have to exist. + FilePath CombinePathsSafely(const FilePath& extension_root, + const FilePath& relative_path) const; + + // Extension root. + FilePath extension_root_; + + // Relative path to resource. + FilePath relative_path_; + + // Full path to extension resource. Starts empty. + mutable FilePath full_resource_path_; +}; + +#endif // CHROME_COMMON_EXTENSIONS_EXTENSION_RESOURCE_H_ diff --git a/chrome/common/extensions/extension_resource_unittest.cc b/chrome/common/extensions/extension_resource_unittest.cc new file mode 100644 index 0000000..bd92bd9 --- /dev/null +++ b/chrome/common/extensions/extension_resource_unittest.cc @@ -0,0 +1,74 @@ +// Copyright (c) 2009 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 <algorithm> + +#include "app/l10n_util.h" +#include "base/file_util.h" +#include "base/path_service.h" +#include "base/scoped_temp_dir.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_resource.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(ExtensionResourceTest, CreateEmptyResource) { + ExtensionResource resource; + + EXPECT_TRUE(resource.extension_root().empty()); + EXPECT_TRUE(resource.relative_path().empty()); + EXPECT_TRUE(resource.GetFilePath().empty()); +} + +const FilePath::StringType ToLower(const FilePath::StringType& in_str) { + FilePath::StringType str(in_str); + std::transform(str.begin(), str.end(), str.begin(), tolower); + return str; +} + +TEST(ExtensionResourceTest, CreateWithMissingResourceOnDisk) { + FilePath root_path; + ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &root_path)); + FilePath relative_path; + relative_path = relative_path.AppendASCII("cira.js"); + ExtensionResource resource(root_path, relative_path); + + EXPECT_EQ(root_path.value(), resource.extension_root().value()); + EXPECT_EQ(relative_path.value(), resource.relative_path().value()); + EXPECT_EQ(root_path.Append(relative_path).value(), + ToLower(resource.GetFilePath().value())); + + EXPECT_FALSE(resource.GetFilePath().empty()); +} + +TEST(ExtensionResourceTest, CreateWithBothResourcesOnDisk) { + ScopedTempDir temp; + ASSERT_TRUE(temp.CreateUniqueTempDir()); + + const char* filename = "res.ico"; + FilePath root_resource = temp.path().AppendASCII(filename); + std::string data = "some foo"; + ASSERT_TRUE(file_util::WriteFile(root_resource.AppendASCII(filename), + data.c_str(), data.length())); + + FilePath l10n_path = temp.path().AppendASCII(Extension::kLocaleFolder); + ASSERT_TRUE(file_util::CreateDirectory(l10n_path)); + + static std::string current_locale = l10n_util::GetApplicationLocale(L""); + std::replace(current_locale.begin(), current_locale.end(), '-', '_'); + l10n_path = l10n_path.AppendASCII(current_locale); + ASSERT_TRUE(file_util::CreateDirectory(l10n_path)); + + ASSERT_TRUE(file_util::WriteFile(l10n_path.AppendASCII(filename), + data.c_str(), data.length())); + + FilePath path; + ExtensionResource resource(temp.path(), FilePath().AppendASCII(filename)); + FilePath resolved_path = resource.GetFilePath(); + + EXPECT_EQ(l10n_path.AppendASCII(filename).value(), resolved_path.value()); + EXPECT_EQ(temp.path().value(), resource.extension_root().value()); + EXPECT_EQ(FilePath().AppendASCII(filename).value(), + resource.relative_path().value()); +} diff --git a/chrome/common/extensions/extension_unittest.cc b/chrome/common/extensions/extension_unittest.cc index 466f27a..26cf648 100644 --- a/chrome/common/extensions/extension_unittest.cc +++ b/chrome/common/extensions/extension_unittest.cc @@ -262,15 +262,6 @@ TEST(ExtensionTest, GetResourceURLAndPath) { Extension::GetResourceURL(extension.url(), "bar/../baz.js").spec()); EXPECT_EQ(extension.url().spec() + "baz.js", Extension::GetResourceURL(extension.url(), "../baz.js").spec()); - - EXPECT_EQ(path.Append(FILE_PATH_LITERAL("bar")) - .Append(FILE_PATH_LITERAL("baz.js")).value(), - Extension::GetResourcePath(extension.path(), "bar/baz.js").value()); - EXPECT_EQ(path.Append(FILE_PATH_LITERAL("baz.js")).value(), - Extension::GetResourcePath(extension.path(), "bar/../baz.js") - .value()); - EXPECT_EQ(FilePath().value(), - Extension::GetResourcePath(extension.path(), "../baz.js").value()); } TEST(ExtensionTest, LoadPageActionHelper) { diff --git a/chrome/common/extensions/user_script.h b/chrome/common/extensions/user_script.h index 4b571799..30807e8 100644 --- a/chrome/common/extensions/user_script.h +++ b/chrome/common/extensions/user_script.h @@ -10,6 +10,7 @@ #include "base/file_path.h" #include "base/string_piece.h" +#include "chrome/common/extensions/extension_resource.h" #include "chrome/common/extensions/url_pattern.h" #include "googleurl/src/gurl.h" @@ -34,14 +35,16 @@ class UserScript { // Holds actual script file info. class File { public: - File(const FilePath& path, const GURL& url): - path_(path), + File(const ExtensionResource& resource, const GURL& url): + resource_(resource), url_(url) { } File() {} - const FilePath& path() const { return path_; } - void set_path(const FilePath& path) { path_ = path; } + const ExtensionResource& resource() const { return resource_; } + void set_resource(const ExtensionResource& resource) { + resource_ = resource; + } const GURL& url() const { return url_; } void set_url(const GURL& url) { url_ = url; } @@ -61,14 +64,14 @@ class UserScript { content_.assign(content.begin(), content.end()); } - // Serialization support. The content and path_ member will not be + // Serialization support. The content and resource_ member will not be // serialized! void Pickle(::Pickle* pickle) const; void Unpickle(const ::Pickle& pickle, void** iter); private: - // Where is the script file lives on the disk. - FilePath path_; + // Where the script file lives on the disk. + ExtensionResource resource_; // The url to this scipt file. GURL url_; diff --git a/chrome/common/extensions/user_script_unittest.cc b/chrome/common/extensions/user_script_unittest.cc index 62fa0a3..0c0bac9 100644 --- a/chrome/common/extensions/user_script_unittest.cc +++ b/chrome/common/extensions/user_script_unittest.cc @@ -78,13 +78,16 @@ TEST(UserScriptTest, Pickle) { UserScript script1; script1.js_scripts().push_back(UserScript::File( - FilePath(FILE_PATH_LITERAL("c:\\foo\\foo.user.js")), + ExtensionResource(FilePath(FILE_PATH_LITERAL("c:\\foo\\")), + FilePath(FILE_PATH_LITERAL("foo.user.js"))), GURL("chrome-user-script:/foo.user.js"))); script1.css_scripts().push_back(UserScript::File( - FilePath(FILE_PATH_LITERAL("c:\\foo\\foo.user.css")), + ExtensionResource(FilePath(FILE_PATH_LITERAL("c:\\foo\\")), + FilePath(FILE_PATH_LITERAL("foo.user.css"))), GURL("chrome-user-script:/foo.user.css"))); script1.css_scripts().push_back(UserScript::File( - FilePath(FILE_PATH_LITERAL("c:\\foo\\foo2.user.css")), + ExtensionResource(FilePath(FILE_PATH_LITERAL("c:\\foo\\")), + FilePath(FILE_PATH_LITERAL("foo2.user.css"))), GURL("chrome-user-script:/foo2.user.css"))); script1.set_run_location(UserScript::DOCUMENT_START); |