summaryrefslogtreecommitdiffstats
path: root/chrome/renderer
diff options
context:
space:
mode:
authorcira@chromium.org <cira@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-28 19:38:49 +0000
committercira@chromium.org <cira@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-28 19:38:49 +0000
commit75e126b937df6fcf5590f607adb460099211fb5a (patch)
treedea2e8c33b6777b36df3435179fd9e6840b77710 /chrome/renderer
parent99a19b7411d408c7471b3ee2c452f06f4d09259d (diff)
downloadchromium_src-75e126b937df6fcf5590f607adb460099211fb5a.zip
chromium_src-75e126b937df6fcf5590f607adb460099211fb5a.tar.gz
chromium_src-75e126b937df6fcf5590f607adb460099211fb5a.tar.bz2
Implementing chrome.i18n.getMessage call, that loads message from the extension catalog, and if necessary replaces placeholders (up to 9).
I have 3 forms of getMessage call: getMessage("name") for simple messages without placeholders. getMessage("name", "one param") for messages with only one placeholder. getMessage("name", ["one", "two"]) for messages with only one or more placeholders. getMessage returns string. BUG=12131 TEST=Load samples/i18n extension (switch Chrome to sr locale) and observe ext. name, description and toolstrip texts should be in Serbian. Review URL: http://codereview.chromium.org/225009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27393 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer')
-rw-r--r--chrome/renderer/extensions/extension_api_client_unittest.cc18
-rw-r--r--chrome/renderer/extensions/extension_process_bindings.cc87
-rw-r--r--chrome/renderer/extensions/extension_process_bindings.h5
-rw-r--r--chrome/renderer/render_thread.cc9
-rw-r--r--chrome/renderer/render_thread.h13
-rw-r--r--chrome/renderer/resources/extension_process_bindings.js6
6 files changed, 132 insertions, 6 deletions
diff --git a/chrome/renderer/extensions/extension_api_client_unittest.cc b/chrome/renderer/extensions/extension_api_client_unittest.cc
index 14ab617..1a06889 100644
--- a/chrome/renderer/extensions/extension_api_client_unittest.cc
+++ b/chrome/renderer/extensions/extension_api_client_unittest.cc
@@ -605,3 +605,21 @@ TEST_F(ExtensionAPIClientTest, GetAcceptLanguages) {
ExpectJsPass("chrome.i18n.getAcceptLanguages(function(){})",
"i18n.getAcceptLanguages", "null");
}
+
+TEST_F(ExtensionAPIClientTest, GetL10nMessage) {
+ ExpectJsFail("chrome.i18n.getMessage()",
+ "Uncaught Error: Parameter 0 is required.");
+
+ ExpectJsFail("chrome.i18n.getMessage(1)",
+ "Uncaught Error: Invalid value for argument 0. "
+ "Expected 'string' but got 'integer'.");
+
+ ExpectJsFail("chrome.i18n.getMessage('name', [])",
+ "Uncaught Error: Invalid value for argument 1. Value does not "
+ "match any valid type choices.");
+
+ ExpectJsFail("chrome.i18n.getMessage('name', ['p1', 'p2', 'p3', 'p4', 'p5', "
+ "'p6', 'p7', 'p8', 'p9', 'p10'])",
+ "Uncaught Error: Invalid value for argument 1. Value does not "
+ "match any valid type choices.");
+}
diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc
index 0fc9438..1a461a8 100644
--- a/chrome/renderer/extensions/extension_process_bindings.cc
+++ b/chrome/renderer/extensions/extension_process_bindings.cc
@@ -2,10 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
#include "chrome/renderer/extensions/extension_process_bindings.h"
#include "base/singleton.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"
@@ -41,6 +47,13 @@ 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,
@@ -54,6 +67,7 @@ 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() {
@@ -68,6 +82,20 @@ 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;
+ }
+}
+
class ExtensionImpl : public ExtensionBase {
public:
ExtensionImpl() : ExtensionBase(
@@ -109,6 +137,8 @@ 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);
}
return ExtensionBase::GetNativeFunction(name);
@@ -131,7 +161,7 @@ class ExtensionImpl : public ExtensionBase {
// TODO(erikkay) for now, special case mole as a type of toolstrip.
// Perhaps this isn't the right long-term thing to do.
- if (match == ViewType::EXTENSION_TOOLSTRIP &&
+ if (match == ViewType::EXTENSION_TOOLSTRIP &&
type == ViewType::EXTENSION_MOLE) {
return true;
}
@@ -255,6 +285,50 @@ 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();
+ }
+
+ L10nMessagesMap* l10n_messages =
+ GetL10nMessagesMap(ExtensionIdForCurrentContext());
+ 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<string16> 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(UTF8ToUTF16(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(UTF8ToUTF16(substitute));
+ }
+ } else {
+ NOTREACHED() << "Couldn't parse second parameter.";
+ return v8::Undefined();
+ }
+
+ return v8::String::New(UTF16ToUTF8(ReplaceStringPlaceholders(
+ UTF8ToUTF16(message), substitutions, NULL)).c_str());
+ }
+
// Starts an API request to the browser, with an optional callback. The
// callback will be dispatched to EventBindings::HandleResponse.
static v8::Handle<v8::Value> StartRequest(const v8::Arguments& args) {
@@ -331,7 +405,7 @@ void ExtensionProcessBindings::HandleResponse(int request_id, bool success,
argv[4] = v8::String::New(error.c_str());
v8::Handle<v8::Value> retval = bindings_utils::CallFunctionInContext(
request->second->context, "handleResponse", arraysize(argv), argv);
- // In debug, the js will validate the callback parameters and return a
+ // In debug, the js will validate the callback parameters and return a
// string if a validation error has occured.
#ifdef _DEBUG
if (!retval.IsEmpty() && !retval->IsUndefined()) {
@@ -357,6 +431,15 @@ 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 1777658..77e5854 100644
--- a/chrome/renderer/extensions/extension_process_bindings.h
+++ b/chrome/renderer/extensions/extension_process_bindings.h
@@ -40,6 +40,11 @@ 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/render_thread.cc b/chrome/renderer/render_thread.cc
index 788b852..d753556 100644
--- a/chrome/renderer/render_thread.cc
+++ b/chrome/renderer/render_thread.cc
@@ -5,6 +5,7 @@
#include "chrome/renderer/render_thread.h"
#include <algorithm>
+#include <map>
#include <vector>
#include "base/command_line.h"
@@ -238,6 +239,12 @@ void RenderThread::OnExtensionSetHostPermissions(
ExtensionProcessBindings::SetHostPermissions(extension_url, permissions);
}
+void RenderThread::OnExtensionSetL10nMessages(
+ const std::string& extension_id,
+ const std::map<std::string, std::string>& l10n_messages) {
+ ExtensionProcessBindings::SetL10nMessages(extension_id, l10n_messages);
+}
+
void RenderThread::OnControlMessageReceived(const IPC::Message& msg) {
// App cache messages are handled by a delegate.
if (appcache_dispatcher_->OnMessageReceived(msg))
@@ -273,6 +280,8 @@ void RenderThread::OnControlMessageReceived(const IPC::Message& msg) {
OnExtensionSetAPIPermissions)
IPC_MESSAGE_HANDLER(ViewMsg_Extension_SetHostPermissions,
OnExtensionSetHostPermissions)
+ IPC_MESSAGE_HANDLER(ViewMsg_Extension_SetL10nMessages,
+ OnExtensionSetL10nMessages)
IPC_END_MESSAGE_MAP()
}
diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h
index ab9a0b2..9fa7203 100644
--- a/chrome/renderer/render_thread.h
+++ b/chrome/renderer/render_thread.h
@@ -140,10 +140,15 @@ class RenderThread : public RenderThreadBase,
void OnSetExtensionFunctionNames(const std::vector<std::string>& names);
void OnPageActionsUpdated(const std::string& extension_id,
const std::vector<std::string>& page_actions);
- void OnExtensionSetAPIPermissions(const std::string& extension_id,
- const std::vector<std::string>& permissions);
- void OnExtensionSetHostPermissions(const GURL& extension_url,
- const std::vector<URLPattern>& permissions);
+ void OnExtensionSetAPIPermissions(
+ const std::string& extension_id,
+ const std::vector<std::string>& permissions);
+ void OnExtensionSetHostPermissions(
+ const GURL& extension_url,
+ const std::vector<URLPattern>& permissions);
+ void OnExtensionSetL10nMessages(
+ const std::string& extension_id,
+ const std::map<std::string, std::string>& l10n_messages);
void OnSetNextPageID(int32 next_page_id);
void OnSetCSSColors(const std::vector<CSSColors::CSSColorMapping>& colors);
void OnCreateNewView(gfx::NativeViewId parent_hwnd,
diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js
index ff2fddd..710dad8 100644
--- a/chrome/renderer/resources/extension_process_bindings.js
+++ b/chrome/renderer/resources/extension_process_bindings.js
@@ -20,6 +20,7 @@ var chrome = chrome || {};
native function GetNextRequestId();
native function OpenChannelToTab();
native function GetRenderViewId();
+ native function GetL10nMessage();
if (!chrome)
chrome = {};
@@ -323,6 +324,11 @@ var chrome = chrome || {};
return tabIdProxy;
}
+ apiFunctions["i18n.getMessage"].handleRequest =
+ function(message_name, placeholders) {
+ return GetL10nMessage(message_name, placeholders);
+ }
+
setupPageActionEvents(extensionId);
setupBrowserActionEvent(extensionId);
setupToolstripEvents(GetRenderViewId());