summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorcira@chromium.org <cira@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-07 22:49:10 +0000
committercira@chromium.org <cira@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-07 22:49:10 +0000
commitecabe6eed156a36238888bfd2fdb96ec4906f0a4 (patch)
tree9419d9a349fc940d45fa450b3a75169fdf48b39f /chrome
parent7050861ff094fd74d155264b6da3ca3795543870 (diff)
downloadchromium_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')
-rw-r--r--chrome/browser/extensions/crx_installer.cc5
-rwxr-xr-xchrome/browser/extensions/execute_code_in_tab_function.cc12
-rwxr-xr-xchrome/browser/extensions/execute_code_in_tab_function.h6
-rw-r--r--chrome/browser/extensions/extension_disabled_infobar_delegate.cc9
-rw-r--r--chrome/browser/extensions/extension_file_util.cc16
-rw-r--r--chrome/browser/extensions/extension_l10n_util.cc12
-rw-r--r--chrome/browser/extensions/extension_l10n_util.h3
-rw-r--r--chrome/browser/extensions/extension_l10n_util_unittest.cc31
-rw-r--r--chrome/browser/extensions/extension_protocols.cc14
-rw-r--r--chrome/browser/extensions/extensions_service_unittest.cc18
-rw-r--r--chrome/browser/extensions/extensions_ui.cc18
-rw-r--r--chrome/browser/extensions/file_reader.cc (renamed from chrome/browser/net/file_reader.cc)9
-rw-r--r--chrome/browser/extensions/file_reader.h (renamed from chrome/browser/net/file_reader.h)19
-rw-r--r--chrome/browser/extensions/file_reader_unittest.cc (renamed from chrome/browser/net/file_reader_unittest.cc)11
-rw-r--r--chrome/browser/extensions/image_loading_tracker.cc (renamed from chrome/browser/image_loading_tracker.cc)19
-rw-r--r--chrome/browser/extensions/image_loading_tracker.h (renamed from chrome/browser/image_loading_tracker.h)14
-rw-r--r--chrome/browser/extensions/user_script_master.cc13
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.cc2
-rw-r--r--chrome/browser/gtk/location_bar_view_gtk.h2
-rw-r--r--chrome/browser/views/browser_actions_container.cc9
-rw-r--r--chrome/browser/views/location_bar_view.cc3
-rw-r--r--chrome/browser/views/location_bar_view.h2
-rwxr-xr-xchrome/chrome.gyp13
-rw-r--r--chrome/common/extensions/extension.cc52
-rw-r--r--chrome/common/extensions/extension.h18
-rw-r--r--chrome/common/extensions/extension_resource.cc100
-rw-r--r--chrome/common/extensions/extension_resource.h49
-rw-r--r--chrome/common/extensions/extension_resource_unittest.cc74
-rw-r--r--chrome/common/extensions/extension_unittest.cc9
-rw-r--r--chrome/common/extensions/user_script.h17
-rw-r--r--chrome/common/extensions/user_script_unittest.cc9
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);