Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2704)

Unified Diff: chrome/browser/extensions/extension_message_handler.cc

Issue 173487: Implemented the rest of loading/parsing logic for extension i18n:... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/extension_message_handler.cc
===================================================================
--- chrome/browser/extensions/extension_message_handler.cc (revision 0)
+++ chrome/browser/extensions/extension_message_handler.cc (revision 0)
@@ -0,0 +1,228 @@
+// 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/browser/extensions/extension_message_handler.h"
+
+#include <string>
+
+#include "base/hash_tables.h"
+#include "base/scoped_ptr.h"
+#include "base/string_util.h"
+#include "base/values.h"
+
+const wchar_t* ExtensionMessageHandler::kContentKey = L"content";
+const wchar_t* ExtensionMessageHandler::kMessageKey = L"message";
+const wchar_t* ExtensionMessageHandler::kPlaceholdersKey = L"placeholders";
+
+const char* ExtensionMessageHandler::kPlaceholderBegin = "$";
+const char* ExtensionMessageHandler::kPlaceholderEnd = "$";
+const char* ExtensionMessageHandler::kMessageBegin = "__MSG_";
+const char* ExtensionMessageHandler::kMessageEnd = "__";
+
+// Formats message in case we encounter a bad formed key in the JSON object.
+// Returns false and sets |error| to actual error message.
Aaron Boodman 2009/08/31 21:42:55 How about just returning the string since the retu
+static bool BadKeyMessage(const std::string& name, std::string* error) {
+ *error = StringPrintf("Name of a key \"%s\" is invalid. Only ASCII [a-z], "
+ "[A-Z], [0-9] and \"_\" are allowed.", name.c_str());
+ return false;
+}
+
+ExtensionMessageHandler::ExtensionMessageHandler() {
Aaron Boodman 2009/08/31 21:42:55 Nit: Since the constructor and destructors are not
+}
+
+ExtensionMessageHandler::~ExtensionMessageHandler() {
+}
+
+bool ExtensionMessageHandler::Init(const DictionaryValue* default_catalog,
Aaron Boodman 2009/08/31 21:42:55 The naming of these parameters is a bit confusing
+ const DictionaryValue* app_catalog,
+ std::string* error) {
+ dictionary_.clear();
+
+ for (DictionaryValue::key_iterator key_it = app_catalog->begin_keys();
+ key_it != app_catalog->end_keys();
+ ++key_it) {
+ std::string key(WideToUTF8(*key_it));
+ if (!IsValidName(key))
+ return BadKeyMessage(key, error);
+ std::string value;
+ if (!GetMessageValue(*key_it, key, app_catalog, &value, error)) {
Aaron Boodman 2009/08/31 21:42:55 Nit: braces unnecessary here.
+ return false;
+ }
+ dictionary_.insert(make_pair(key, value));
Aaron Boodman 2009/08/31 21:42:55 Nit: I think the syntax dictionary[key] = value is
+ }
+
+ for (DictionaryValue::key_iterator key_it = default_catalog->begin_keys();
+ key_it != default_catalog->end_keys();
+ ++key_it) {
+ std::string key(WideToUTF8(*key_it));
+ if (!IsValidName(key))
+ return BadKeyMessage(key, error);
+ // Add only messages that are not provided by app_catalog.
+ if (dictionary_.find(key) != dictionary_.end())
+ continue;
+ std::string value;
+ if (!GetMessageValue(*key_it, key, default_catalog, &value, error)) {
+ return false;
+ }
+ dictionary_.insert(make_pair(key, value));
+ }
+
+ return true;
+}
+
+bool ExtensionMessageHandler::GetMessageValue(
+ const std::wstring& wkey,
+ const std::string& key,
+ const DictionaryValue* main_catalog,
Aaron Boodman 2009/08/31 21:42:55 Nit: the "main_catalog" parameter seems misnamed.
+ std::string* value,
+ std::string* error) const {
Aaron Boodman 2009/08/31 21:42:55 Add a DCHECK that the two keys are the same?
+ // Get the top level tree for given key (name part).
+ DictionaryValue* name_tree;
+ if (!main_catalog->GetDictionary(wkey, &name_tree)) {
+ *error = StringPrintf("Not a valid tree for key %s.", key.c_str());
+ return false;
+ }
+ // Extract message from it.
+ if (!name_tree->GetString(kMessageKey, value)) {
+ *error = StringPrintf("There is no \"%s\" element for key %s.",
+ WideToUTF8(kMessageKey).c_str(),
+ key.c_str());
+ return false;
+ }
+
+ SSMap placeholders;
+ if (!GetPlaceholders(name_tree, key, &placeholders, error)) {
+ return false;
+ }
+ if (!ReplacePlaceholdersInMessage(placeholders, value)) {
+ *error = StringPrintf("Placeholder \"%s\" is missing but used in a "
+ "message %s.", value->c_str(), key.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+bool ExtensionMessageHandler::GetPlaceholders(const DictionaryValue* name_tree,
+ const std::string name_key,
+ SSMap* placeholders,
+ std::string* error) const {
+ if (!name_tree->HasKey(kPlaceholdersKey))
+ return true;
+
+ DictionaryValue* placeholders_tree;
+ if (!name_tree->GetDictionary(kPlaceholdersKey, &placeholders_tree)) {
+ *error = StringPrintf("Not a valid \"%s\" element for key %s.",
+ WideToUTF8(kPlaceholdersKey).c_str(),
+ name_key.c_str());
+ return false;
+ }
+
+ for (DictionaryValue::key_iterator key_itr = placeholders_tree->begin_keys();
+ key_itr != placeholders_tree->end_keys();
+ ++key_itr) {
+ DictionaryValue* placeholder;
+ std::string content_key = WideToUTF8(*key_itr);
+ if (!IsValidName(content_key))
+ return BadKeyMessage(content_key, error);
+ if (!placeholders_tree->GetDictionary(*key_itr, &placeholder)) {
+ *error = StringPrintf("Invalid placeholder %s for key %s",
+ content_key.c_str(),
+ name_key.c_str());
+ return false;
+ }
+ std::string content;
+ if (!placeholder->GetString(kContentKey, &content)) {
+ *error = StringPrintf("Invalid \"%s\" element for key %s.",
+ WideToUTF8(kContentKey).c_str(),
+ name_key.c_str());
+ return false;
+ }
+ placeholders->insert(std::make_pair(content_key, content));
+ }
+
+ return true;
+}
+
+bool ExtensionMessageHandler::ReplacePlaceholdersInMessage(
+ const SSMap& placeholders,
+ std::string* message) const {
+ return ReplaceVariablesInString(
+ placeholders, kPlaceholderBegin, kPlaceholderEnd, message);
+}
+
+bool ExtensionMessageHandler::ReplaceMessagesInString(std::string* text) const {
+ return ReplaceVariablesInString(
+ dictionary_, kMessageBegin, kMessageEnd, text);
+}
+
+bool ExtensionMessageHandler::ReplaceVariablesInString(
+ const SSMap& variables,
+ const std::string& var_begin,
+ const std::string& var_end,
+ std::string* message) const {
+ std::string::size_type beg_index = 0;
+ const std::string::size_type var_begin_size = var_begin.size();
+ while (true) {
+ beg_index = message->find(var_begin, beg_index);
+ if (beg_index == message->npos) {
Aaron Boodman 2009/08/31 21:42:55 All these one line early exits can be braceless.
+ return true;
+ }
+ // Advance it immediately to the begining of possible variable name.
+ beg_index += var_begin_size;
+ if (beg_index >= message->size()) {
+ return true;
+ }
+ std::string::size_type end_index = message->find(var_end, beg_index);
+ if (end_index == message->npos) {
+ return true;
+ }
+ // Looking for 1 in substring of ...$1$....
+ const std::string& var_name =
+ message->substr(beg_index, end_index - beg_index);
+ if (!IsValidName(var_name)) {
+ continue;
+ }
+ SSMap::const_iterator it = variables.find(var_name);
+ if (it == variables.end()) {
+ message->assign(var_name);
Aaron Boodman 2009/08/31 21:42:55 Did you mean to replace the entire input string wi
+ return false;
+ }
+ std::string value = it->second;
+ // Replace variable with its value.
+ message->replace(beg_index - var_begin_size,
+ end_index - beg_index + var_begin_size + var_end.size(),
+ value);
+ // And position pointer to after the replacement.
+ beg_index += value.size() - var_begin_size;
+ }
+
+ return true;
+}
+
+bool ExtensionMessageHandler::IsValidName(const std::string& name) const {
+ if (name.empty())
+ return false;
+
+ for (std::string::const_iterator it = name.begin(); it != name.end(); ++it) {
+ // Allow only ascii 0-9, a-z, A-Z, and _ in the name.
+ if (!IsAsciiAlpha(*it) && !IsAsciiDigit(*it) && *it != '_')
+ return false;
+ }
+
+ return true;
+}
+
+// Dictionary interface.
+
+bool ExtensionMessageHandler::GetMessage(const std::string& name,
+ std::string* message) const {
+ SSMap::const_iterator it = dictionary_.find(name);
+ if (it != dictionary_.end()) {
+ message->assign(it->second);
+ return true;
+ }
+
+ return false;
+}
Property changes on: chrome\browser\extensions\extension_message_handler.cc
___________________________________________________________________
Added: svn:eol-style
+ LF

Powered by Google App Engine
This is Rietveld 408576698