diff options
author | cira@chromium.org <cira@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-29 00:28:43 +0000 |
---|---|---|
committer | cira@chromium.org <cira@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-29 00:28:43 +0000 |
commit | a672cb9dce10306f3b149802653dbb554b326a44 (patch) | |
tree | f726e3b92f3b3ddebd48c0143d42617af89165d7 /chrome/renderer/extensions | |
parent | a36d06b727f8ebc8f60e515d0c6f855513c88272 (diff) | |
download | chromium_src-a672cb9dce10306f3b149802653dbb554b326a44.zip chromium_src-a672cb9dce10306f3b149802653dbb554b326a44.tar.gz chromium_src-a672cb9dce10306f3b149802653dbb554b326a44.tar.bz2 |
Adding support for i18n to content scripts.
Auto-updated extension docs.
Review URL: http://codereview.chromium.org/522017
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35320 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer/extensions')
4 files changed, 115 insertions, 109 deletions
diff --git a/chrome/renderer/extensions/extension_api_client_unittest.cc b/chrome/renderer/extensions/extension_api_client_unittest.cc index abe3f5c..05c2ddf 100644 --- a/chrome/renderer/extensions/extension_api_client_unittest.cc +++ b/chrome/renderer/extensions/extension_api_client_unittest.cc @@ -620,7 +620,9 @@ TEST_F(ExtensionAPIClientTest, GetAcceptLanguages) { "i18n.getAcceptLanguages", "null"); } -TEST_F(ExtensionAPIClientTest, GetL10nMessage) { +// TODO(cira): re-enable when we get validation going for +// renderer_process_bindings.js +TEST_F(ExtensionAPIClientTest, DISABLED_GetL10nMessage) { ExpectJsFail("chrome.i18n.getMessage()", "Uncaught Error: Parameter 0 is required."); diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc index c1009c3e..f065dd9 100644 --- a/chrome/renderer/extensions/extension_process_bindings.cc +++ b/chrome/renderer/extensions/extension_process_bindings.cc @@ -14,7 +14,6 @@ #include "base/singleton.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension.h" -#include "chrome/common/extensions/extension_message_bundle.h" #include "chrome/common/extensions/url_pattern.h" #include "chrome/common/render_messages.h" #include "chrome/common/url_constants.h" @@ -56,13 +55,6 @@ typedef std::map<std::string, bool> PermissionsMap; // A map of extension ID to permissions map. typedef std::map<std::string, PermissionsMap> ExtensionPermissionsMap; -// A map of message name to message. -typedef std::map<std::string, std::string> L10nMessagesMap; - -// A map of extension ID to l10n message map. -typedef std::map<std::string, L10nMessagesMap > - ExtensionToL10nMessagesMap; - const char kExtensionName[] = "chrome/ExtensionProcessBindings"; const char* kExtensionDeps[] = { BaseJsV8Extension::kName, @@ -76,7 +68,6 @@ struct SingletonData { std::set<std::string> function_names_; PageActionIdMap page_action_ids_; ExtensionPermissionsMap permissions_; - ExtensionToL10nMessagesMap extension_l10n_messages_map_; }; static std::set<std::string>* GetFunctionNameSet() { @@ -91,20 +82,6 @@ static PermissionsMap* GetPermissionsMap(const std::string& extension_id) { return &Singleton<SingletonData>()->permissions_[extension_id]; } -static ExtensionToL10nMessagesMap* GetExtensionToL10nMessagesMap() { - return &Singleton<SingletonData>()->extension_l10n_messages_map_; -} - -static L10nMessagesMap* GetL10nMessagesMap(const std::string extension_id) { - ExtensionToL10nMessagesMap::iterator it = - Singleton<SingletonData>()->extension_l10n_messages_map_.find(extension_id); - if (it != Singleton<SingletonData>()->extension_l10n_messages_map_.end()) { - return &(it->second); - } else { - return NULL; - } -} - static void GetActiveExtensionIDs(std::set<std::string>* extension_ids) { ExtensionPermissionsMap& permissions = Singleton<SingletonData>()->permissions_; @@ -254,8 +231,6 @@ class ExtensionImpl : public ExtensionBase { return v8::FunctionTemplate::New(StartRequest); } else if (name->Equals(v8::String::New("GetRenderViewId"))) { return v8::FunctionTemplate::New(GetRenderViewId); - } else if (name->Equals(v8::String::New("GetL10nMessage"))) { - return v8::FunctionTemplate::New(GetL10nMessage); } else if (name->Equals(v8::String::New("GetPopupView"))) { return v8::FunctionTemplate::New(GetPopupView); } else if (name->Equals(v8::String::New("GetPopupParentWindow"))) { @@ -412,71 +387,6 @@ class ExtensionImpl : public ExtensionBase { return page_action_vector; } - static v8::Handle<v8::Value> GetL10nMessage(const v8::Arguments& args) { - if (args.Length() != 2 || !args[0]->IsString()) { - NOTREACHED() << "Bad arguments"; - return v8::Undefined(); - } - - std::string extension_id = ExtensionIdForCurrentContext(); - if (extension_id.empty()) - return v8::Undefined(); - - L10nMessagesMap* l10n_messages = GetL10nMessagesMap(extension_id); - if (!l10n_messages) { - // Get the current RenderView so that we can send a routed IPC message - // from the correct source. - RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext(); - if (!renderview) - return v8::Undefined(); - - L10nMessagesMap messages; - // A sync call to load message catalogs for current extension. - renderview->Send(new ViewHostMsg_GetExtensionMessageBundle( - extension_id, &messages)); - - if (messages.empty()) - return v8::Undefined(); - - ExtensionProcessBindings::SetL10nMessages(extension_id, messages); - l10n_messages = GetL10nMessagesMap(extension_id); - if (!l10n_messages) - return v8::Undefined(); - } - - std::string message_name = *v8::String::AsciiValue(args[0]); - std::string message = - ExtensionMessageBundle::GetL10nMessage(message_name, *l10n_messages); - - std::vector<std::string> substitutions; - if (args[1]->IsNull() || args[1]->IsUndefined()) { - // chrome.i18n.getMessage("message_name"); - // chrome.i18n.getMessage("message_name", null); - return v8::String::New(message.c_str()); - } else if (args[1]->IsString()) { - // chrome.i18n.getMessage("message_name", "one param"); - std::string substitute = *v8::String::Utf8Value(args[1]->ToString()); - substitutions.push_back(substitute); - } else if (args[1]->IsArray()) { - // chrome.i18n.getMessage("message_name", ["more", "params"]); - v8::Array* placeholders = static_cast<v8::Array*>(*args[1]); - uint32_t count = placeholders->Length(); - DCHECK(count > 0 && count <= 9); - for (uint32_t i = 0; i < count; ++i) { - std::string substitute = - *v8::String::Utf8Value( - placeholders->Get(v8::Integer::New(i))->ToString()); - substitutions.push_back(substitute); - } - } else { - NOTREACHED() << "Couldn't parse second parameter."; - return v8::Undefined(); - } - - return v8::String::New(ReplaceStringPlaceholders( - message, substitutions, NULL).c_str()); - } - // Common code for starting an API request to the browser. |value_args| // contains the request's arguments. static v8::Handle<v8::Value> StartRequestCommon( @@ -656,15 +566,6 @@ void ExtensionProcessBindings::SetPageActions( } // static -void ExtensionProcessBindings::SetL10nMessages( - const std::string& extension_id, - const std::map<std::string, std::string>& l10n_messages) { - ExtensionToL10nMessagesMap& l10n_messages_map = - *GetExtensionToL10nMessagesMap(); - l10n_messages_map[extension_id] = l10n_messages; -} - -// static void ExtensionProcessBindings::SetAPIPermissions( const std::string& extension_id, const std::vector<std::string>& permissions) { diff --git a/chrome/renderer/extensions/extension_process_bindings.h b/chrome/renderer/extensions/extension_process_bindings.h index 08f068d2..2fd7613 100644 --- a/chrome/renderer/extensions/extension_process_bindings.h +++ b/chrome/renderer/extensions/extension_process_bindings.h @@ -7,7 +7,6 @@ #ifndef CHROME_RENDERER_EXTENSIONS_EXTENSION_PROCESS_BINDINGS_H_ #define CHROME_RENDERER_EXTENSIONS_EXTENSION_PROCESS_BINDINGS_H_ -#include <map> #include <set> #include <string> #include <vector> @@ -47,11 +46,6 @@ class ExtensionProcessBindings { static void SetHostPermissions(const GURL& extension_url, const std::vector<URLPattern>& permissions); - // Set l10n messages for a particular extension. - static void SetL10nMessages( - const std::string& extension_id, - const std::map<std::string, std::string>& l10n_messages); - // Check if the extension in the currently running context has permission to // access the given extension function. Must be called with a valid V8 // context in scope. diff --git a/chrome/renderer/extensions/renderer_extension_bindings.cc b/chrome/renderer/extensions/renderer_extension_bindings.cc index 42882d07..54231b6 100644 --- a/chrome/renderer/extensions/renderer_extension_bindings.cc +++ b/chrome/renderer/extensions/renderer_extension_bindings.cc @@ -4,10 +4,16 @@ #include "chrome/renderer/extensions/renderer_extension_bindings.h" +#include <map> +#include <string> + #include "app/resource_bundle.h" #include "base/basictypes.h" +#include "base/singleton.h" #include "base/values.h" +#include "chrome/common/extensions/extension_message_bundle.h" #include "chrome/common/render_messages.h" +#include "chrome/common/url_constants.h" #include "chrome/renderer/extensions/bindings_utils.h" #include "chrome/renderer/extensions/event_bindings.h" #include "chrome/renderer/render_thread.h" @@ -29,6 +35,12 @@ using bindings_utils::ExtensionBase; namespace { +// A map of message name to message. +typedef std::map<std::string, std::string> L10nMessagesMap; + +// A map of extension ID to l10n message map. +typedef std::map<std::string, L10nMessagesMap > ExtensionToL10nMessagesMap; + struct ExtensionData { struct PortData { int ref_count; // how many contexts have a handle to this port @@ -36,18 +48,38 @@ struct ExtensionData { PortData() : ref_count(0), disconnected(false) {} }; std::map<int, PortData> ports; // port ID -> data + // Maps extension ID to message map. + ExtensionToL10nMessagesMap extension_l10n_messages_map_; }; -bool HasPortData(int port_id) { + +static bool HasPortData(int port_id) { return Singleton<ExtensionData>::get()->ports.find(port_id) != Singleton<ExtensionData>::get()->ports.end(); } -ExtensionData::PortData& GetPortData(int port_id) { + +static ExtensionData::PortData& GetPortData(int port_id) { return Singleton<ExtensionData>::get()->ports[port_id]; } -void ClearPortData(int port_id) { + +static void ClearPortData(int port_id) { Singleton<ExtensionData>::get()->ports.erase(port_id); } +static ExtensionToL10nMessagesMap* GetExtensionToL10nMessagesMap() { + return &Singleton<ExtensionData>()->extension_l10n_messages_map_; +} + +static L10nMessagesMap* GetL10nMessagesMap(const std::string extension_id) { + ExtensionToL10nMessagesMap::iterator it = + Singleton<ExtensionData>()->extension_l10n_messages_map_.find( + extension_id); + if (it != Singleton<ExtensionData>()->extension_l10n_messages_map_.end()) { + return &(it->second); + } else { + return NULL; + } +} + const char kPortClosedError[] = "Attempting to use a disconnected port object"; const char* kExtensionDeps[] = { EventBindings::kName }; @@ -72,6 +104,8 @@ class ExtensionImpl : public ExtensionBase { return v8::FunctionTemplate::New(PortAddRef); } else if (name->Equals(v8::String::New("PortRelease"))) { return v8::FunctionTemplate::New(PortRelease); + } else if (name->Equals(v8::String::New("GetL10nMessage"))) { + return v8::FunctionTemplate::New(GetL10nMessage); } return ExtensionBase::GetNativeFunction(name); } @@ -158,6 +192,81 @@ class ExtensionImpl : public ExtensionBase { } return v8::Undefined(); } + + static v8::Handle<v8::Value> GetL10nMessage(const v8::Arguments& args) { + if (args.Length() != 3 || !args[0]->IsString()) { + NOTREACHED() << "Bad arguments"; + return v8::Undefined(); + } + + std::string extension_id; + if (args[2]->IsNull() || !args[2]->IsString()) { + return v8::Undefined(); + } else { + extension_id = *v8::String::Utf8Value(args[2]->ToString()); + if (extension_id.empty()) + return v8::Undefined(); + } + + L10nMessagesMap* l10n_messages = GetL10nMessagesMap(extension_id); + if (!l10n_messages) { + // Get the current RenderView so that we can send a routed IPC message + // from the correct source. + RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext(); + if (!renderview) + return v8::Undefined(); + + L10nMessagesMap messages; + // A sync call to load message catalogs for current extension. + renderview->Send(new ViewHostMsg_GetExtensionMessageBundle( + extension_id, &messages)); + + if (messages.empty()) + return v8::Undefined(); + + // Save messages we got. + ExtensionToL10nMessagesMap& l10n_messages_map = + *GetExtensionToL10nMessagesMap(); + l10n_messages_map[extension_id] = messages; + + l10n_messages = GetL10nMessagesMap(extension_id); + if (!l10n_messages) + return v8::Undefined(); + } + + std::string message_name = *v8::String::AsciiValue(args[0]); + std::string message = + ExtensionMessageBundle::GetL10nMessage(message_name, *l10n_messages); + + std::vector<std::string> substitutions; + if (args[1]->IsNull() || args[1]->IsUndefined()) { + // chrome.i18n.getMessage("message_name"); + // chrome.i18n.getMessage("message_name", null); + return v8::String::New(message.c_str()); + } else if (args[1]->IsString()) { + // chrome.i18n.getMessage("message_name", "one param"); + std::string substitute = *v8::String::Utf8Value(args[1]->ToString()); + substitutions.push_back(substitute); + } else if (args[1]->IsArray()) { + // chrome.i18n.getMessage("message_name", ["more", "params"]); + v8::Array* placeholders = static_cast<v8::Array*>(*args[1]); + uint32_t count = placeholders->Length(); + if (count <= 0 || count > 9) + return v8::Undefined(); + for (uint32_t i = 0; i < count; ++i) { + std::string substitute = + *v8::String::Utf8Value( + placeholders->Get(v8::Integer::New(i))->ToString()); + substitutions.push_back(substitute); + } + } else { + NOTREACHED() << "Couldn't parse second parameter."; + return v8::Undefined(); + } + + return v8::String::New(ReplaceStringPlaceholders( + message, substitutions, NULL).c_str()); + } }; // Convert a ListValue to a vector of V8 values. |