summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/extensions/content_script_apitest.cc5
-rw-r--r--chrome/browser/extensions/execute_code_in_tab_function.cc53
-rw-r--r--chrome/browser/extensions/execute_code_in_tab_function.h11
-rw-r--r--chrome/browser/extensions/user_script_master.cc43
-rw-r--r--chrome/browser/extensions/user_script_master.h16
-rw-r--r--chrome/browser/extensions/user_script_master_unittest.cc12
-rw-r--r--chrome/browser/renderer_host/chrome_render_message_filter.cc23
7 files changed, 135 insertions, 28 deletions
diff --git a/chrome/browser/extensions/content_script_apitest.cc b/chrome/browser/extensions/content_script_apitest.cc
index c640eec..acd1a75 100644
--- a/chrome/browser/extensions/content_script_apitest.cc
+++ b/chrome/browser/extensions/content_script_apitest.cc
@@ -92,3 +92,8 @@ IN_PROC_BROWSER_TEST_F(
&styles_injected));
ASSERT_TRUE(styles_injected);
}
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContentScriptCSSLocalization) {
+ ASSERT_TRUE(StartTestServer());
+ ASSERT_TRUE(RunExtensionTest("content_scripts/css_l10n")) << message_;
+}
diff --git a/chrome/browser/extensions/execute_code_in_tab_function.cc b/chrome/browser/extensions/execute_code_in_tab_function.cc
index b5eb0d5..5c96195 100644
--- a/chrome/browser/extensions/execute_code_in_tab_function.cc
+++ b/chrome/browser/extensions/execute_code_in_tab_function.cc
@@ -4,7 +4,6 @@
#include "chrome/browser/extensions/execute_code_in_tab_function.h"
-#include "base/callback.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/extensions/extension_service.h"
@@ -17,7 +16,10 @@
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/extension_error_utils.h"
+#include "chrome/common/extensions/extension_file_util.h"
+#include "chrome/common/extensions/extension_l10n_util.h"
#include "chrome/common/extensions/extension_messages.h"
+#include "chrome/common/extensions/extension_message_bundle.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/browser/renderer_host/render_view_host.h"
@@ -117,13 +119,60 @@ bool ExecuteCodeInTabFunction::RunImpl() {
scoped_refptr<FileReader> file_reader(new FileReader(
resource_, NewCallback(this, &ExecuteCodeInTabFunction::DidLoadFile)));
file_reader->Start();
- AddRef(); // Keep us alive until DidLoadFile is called.
+ AddRef(); // Keep us alive until DidLoadAndLocalizeFile is called.
return true;
}
void ExecuteCodeInTabFunction::DidLoadFile(bool success,
const std::string& data) {
+ std::string function_name = name();
+ const Extension* extension = GetExtension();
+
+ // Check if the file is CSS and needs localization.
+ if (success &&
+ function_name == TabsInsertCSSFunction::function_name() &&
+ extension != NULL &&
+ data.find(ExtensionMessageBundle::kMessageBegin) != std::string::npos) {
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ NewRunnableMethod(this, &ExecuteCodeInTabFunction::LocalizeCSS,
+ data,
+ extension->id(),
+ extension->path(),
+ extension->default_locale()));
+ } else {
+ DidLoadAndLocalizeFile(success, data);
+ }
+}
+
+void ExecuteCodeInTabFunction::LocalizeCSS(
+ const std::string& data,
+ const std::string& extension_id,
+ const FilePath& extension_path,
+ const std::string& extension_default_locale) {
+ scoped_ptr<SubstitutionMap> localization_messages(
+ extension_file_util::LoadExtensionMessageBundleSubstitutionMap(
+ extension_path, extension_id, extension_default_locale));
+
+ // We need to do message replacement on the data, so it has to be mutable.
+ std::string css_data = data;
+ std::string error;
+ ExtensionMessageBundle::ReplaceMessagesWithExternalDictionary(
+ *localization_messages, &css_data, &error);
+
+ // Call back DidLoadAndLocalizeFile on the UI thread. The success parameter
+ // is always true, because if loading had failed, we wouldn't have had
+ // anything to localize.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this,
+ &ExecuteCodeInTabFunction::DidLoadAndLocalizeFile,
+ true, css_data));
+}
+
+void ExecuteCodeInTabFunction::DidLoadAndLocalizeFile(bool success,
+ const std::string& data) {
if (success) {
Execute(data);
} else {
diff --git a/chrome/browser/extensions/execute_code_in_tab_function.h b/chrome/browser/extensions/execute_code_in_tab_function.h
index 2dbc115..b57ad49 100644
--- a/chrome/browser/extensions/execute_code_in_tab_function.h
+++ b/chrome/browser/extensions/execute_code_in_tab_function.h
@@ -33,6 +33,17 @@ class ExecuteCodeInTabFunction : public AsyncExtensionFunction,
// arguments has been loaded.
void DidLoadFile(bool success, const std::string& data);
+ // Runs on FILE thread. Loads message bundles for the extension and
+ // localizes the CSS data. Calls back DidLoadAndLocalizeFile on the UI thread.
+ void LocalizeCSS(
+ const std::string& data,
+ const std::string& extension_id,
+ const FilePath& extension_path,
+ const std::string& extension_default_locale);
+
+ // Called when contents from the loaded file have been localized.
+ void DidLoadAndLocalizeFile(bool success, const std::string& data);
+
// Run in UI thread. Code string contains the code to be executed. Returns
// true on success. If true is returned, this does an AddRef.
bool Execute(const std::string& code_string);
diff --git a/chrome/browser/extensions/user_script_master.cc b/chrome/browser/extensions/user_script_master.cc
index 5e68098..af2abe2 100644
--- a/chrome/browser/extensions/user_script_master.cc
+++ b/chrome/browser/extensions/user_script_master.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/extensions/user_script_master.h"
+#include <map>
#include <string>
#include <vector>
@@ -18,8 +19,10 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/extension_messages.h"
+#include "chrome/common/extensions/extension_file_util.h"
+#include "chrome/common/extensions/extension_message_bundle.h"
#include "chrome/common/extensions/extension_resource.h"
+#include "chrome/common/extensions/extension_set.h"
#include "content/browser/renderer_host/render_process_host.h"
#include "content/common/notification_service.h"
@@ -44,6 +47,12 @@ static bool GetDeclarationValue(const base::StringPiece& line,
UserScriptMaster::ScriptReloader::ScriptReloader(UserScriptMaster* master)
: master_(master) {
CHECK(BrowserThread::GetCurrentThreadIdentifier(&master_thread_id_));
+
+ // Gather extensions information needed for localization.
+ if (master && master->profile_ && master->profile_->GetExtensionInfoMap()) {
+ const ExtensionInfoMap* info_map = master->profile_->GetExtensionInfoMap();
+ info_map->extensions().GetExtensionsPathAndDefaultLocale(extensions_info_);
+ }
}
// static
@@ -160,7 +169,8 @@ void UserScriptMaster::ScriptReloader::NotifyMaster(
Release();
}
-static bool LoadScriptContent(UserScript::File* script_file) {
+static bool LoadScriptContent(UserScript::File* script_file,
+ const SubstitutionMap* localization_messages) {
std::string content;
const FilePath& path = ExtensionResource::GetFilePath(
script_file->extension_root(), script_file->relative_path());
@@ -175,6 +185,16 @@ static bool LoadScriptContent(UserScript::File* script_file) {
return false;
}
+ // Localize the content.
+ if (localization_messages) {
+ std::string error;
+ ExtensionMessageBundle::ReplaceMessagesWithExternalDictionary(
+ *localization_messages, &content, &error);
+ if (!error.empty()) {
+ LOG(WARNING) << "Failed to replace messages in script: " << error;
+ }
+ }
+
// Remove BOM from the content.
std::string::size_type index = content.find(kUtf8ByteOrderMark);
if (index == 0) {
@@ -186,24 +206,37 @@ static bool LoadScriptContent(UserScript::File* script_file) {
return true;
}
-// static
void UserScriptMaster::ScriptReloader::LoadUserScripts(
UserScriptList* user_scripts) {
for (size_t i = 0; i < user_scripts->size(); ++i) {
UserScript& script = user_scripts->at(i);
+ scoped_ptr<SubstitutionMap> localization_messages(
+ GetLocalizationMessages(script.extension_id()));
for (size_t k = 0; k < script.js_scripts().size(); ++k) {
UserScript::File& script_file = script.js_scripts()[k];
if (script_file.GetContent().empty())
- LoadScriptContent(&script_file);
+ LoadScriptContent(&script_file, NULL);
}
for (size_t k = 0; k < script.css_scripts().size(); ++k) {
UserScript::File& script_file = script.css_scripts()[k];
if (script_file.GetContent().empty())
- LoadScriptContent(&script_file);
+ LoadScriptContent(&script_file, localization_messages.get());
}
}
}
+SubstitutionMap* UserScriptMaster::ScriptReloader::GetLocalizationMessages(
+ std::string extension_id) {
+ if (extensions_info_.find(extension_id) == extensions_info_.end()) {
+ return NULL;
+ }
+
+ return extension_file_util::LoadExtensionMessageBundleSubstitutionMap(
+ extensions_info_[extension_id].first,
+ extension_id,
+ extensions_info_[extension_id].second);
+}
+
// Pickle user scripts and return pointer to the shared memory.
static base::SharedMemory* Serialize(const UserScriptList& scripts) {
Pickle pickle;
diff --git a/chrome/browser/extensions/user_script_master.h b/chrome/browser/extensions/user_script_master.h
index 2df53d8..1ef6453 100644
--- a/chrome/browser/extensions/user_script_master.h
+++ b/chrome/browser/extensions/user_script_master.h
@@ -6,10 +6,15 @@
#define CHROME_BROWSER_EXTENSIONS_USER_SCRIPT_MASTER_H_
#pragma once
+#include <map>
+#include <string>
+
#include "base/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/shared_memory.h"
+#include "chrome/common/extensions/extension_messages.h"
+#include "chrome/common/extensions/extension_set.h"
#include "chrome/common/extensions/user_script.h"
#include "content/browser/browser_thread.h"
#include "content/common/notification_observer.h"
@@ -75,7 +80,6 @@ class UserScriptMaster : public base::RefCountedThreadSafe<UserScriptMaster>,
}
private:
- private:
FRIEND_TEST_ALL_PREFIXES(UserScriptMasterTest, SkipBOMAtTheBeginning);
FRIEND_TEST_ALL_PREFIXES(UserScriptMasterTest, LeaveBOMNotAtTheBeginning);
friend class base::RefCountedThreadSafe<UserScriptMaster::ScriptReloader>;
@@ -98,12 +102,20 @@ class UserScriptMaster : public base::RefCountedThreadSafe<UserScriptMaster>,
// tied to the caller.
void RunLoad(const UserScriptList& user_scripts);
- static void LoadUserScripts(UserScriptList* user_scripts);
+ void LoadUserScripts(UserScriptList* user_scripts);
+
+ // Uses extensions_info_ to build a map of localization messages.
+ // Returns NULL if |extension_id| is invalid.
+ SubstitutionMap* GetLocalizationMessages(std::string extension_id);
// A pointer back to our master.
// May be NULL if DisownMaster() is called.
UserScriptMaster* master_;
+ // Maps extension info needed for localization to an extension ID.
+ std::map<std::string, ExtensionSet::ExtensionPathAndDefaultLocale>
+ extensions_info_;
+
// The message loop to call our master back on.
// Expected to always outlive us.
BrowserThread::ID master_thread_id_;
diff --git a/chrome/browser/extensions/user_script_master_unittest.cc b/chrome/browser/extensions/user_script_master_unittest.cc
index d1ea7ac..2637c28 100644
--- a/chrome/browser/extensions/user_script_master_unittest.cc
+++ b/chrome/browser/extensions/user_script_master_unittest.cc
@@ -220,7 +220,11 @@ TEST_F(UserScriptMasterTest, SkipBOMAtTheBeginning) {
UserScriptList user_scripts;
user_scripts.push_back(user_script);
- UserScriptMaster::ScriptReloader::LoadUserScripts(&user_scripts);
+ UserScriptMaster::ScriptReloader* script_reloader =
+ new UserScriptMaster::ScriptReloader(NULL);
+ script_reloader->AddRef();
+ script_reloader->LoadUserScripts(&user_scripts);
+ script_reloader->Release();
EXPECT_EQ(content.substr(3),
user_scripts[0].js_scripts()[0].GetContent().as_string());
@@ -239,7 +243,11 @@ TEST_F(UserScriptMasterTest, LeaveBOMNotAtTheBeginning) {
UserScriptList user_scripts;
user_scripts.push_back(user_script);
- UserScriptMaster::ScriptReloader::LoadUserScripts(&user_scripts);
+ UserScriptMaster::ScriptReloader* script_reloader =
+ new UserScriptMaster::ScriptReloader(NULL);
+ script_reloader->AddRef();
+ script_reloader->LoadUserScripts(&user_scripts);
+ script_reloader->Release();
EXPECT_EQ(content, user_scripts[0].js_scripts()[0].GetContent().as_string());
}
diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.cc b/chrome/browser/renderer_host/chrome_render_message_filter.cc
index 5cc1293..7486ebd 100644
--- a/chrome/browser/renderer_host/chrome_render_message_filter.cc
+++ b/chrome/browser/renderer_host/chrome_render_message_filter.cc
@@ -323,25 +323,14 @@ void ChromeRenderMessageFilter::OnGetExtensionMessageBundleOnFileThread(
IPC::Message* reply_msg) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- std::map<std::string, std::string> dictionary_map;
- if (!default_locale.empty()) {
- // Touch disk only if extension is localized.
- std::string error;
- scoped_ptr<ExtensionMessageBundle> bundle(
- extension_file_util::LoadExtensionMessageBundle(
- extension_path, default_locale, &error));
-
- if (bundle.get())
- dictionary_map = *bundle->dictionary();
- }
-
- // Add @@extension_id reserved message here, so it's available to
- // non-localized extensions too.
- dictionary_map.insert(
- std::make_pair(ExtensionMessageBundle::kExtensionIdKey, extension_id));
+ scoped_ptr<ExtensionMessageBundle::SubstitutionMap> dictionary_map(
+ extension_file_util::LoadExtensionMessageBundleSubstitutionMap(
+ extension_path,
+ extension_id,
+ default_locale));
ExtensionHostMsg_GetMessageBundle::WriteReplyParams(
- reply_msg, dictionary_map);
+ reply_msg, *dictionary_map);
Send(reply_msg);
}