| Index: chrome/common/extensions/extension_message_bundle.cc
|
| diff --git a/chrome/common/extensions/extension_message_bundle.cc b/chrome/common/extensions/extension_message_bundle.cc
|
| deleted file mode 100644
|
| index cafbd91b81075bacbe97ba058e16f28e44f5f297..0000000000000000000000000000000000000000
|
| --- a/chrome/common/extensions/extension_message_bundle.cc
|
| +++ /dev/null
|
| @@ -1,346 +0,0 @@
|
| -// Copyright (c) 2012 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_message_bundle.h"
|
| -
|
| -#include <string>
|
| -#include <vector>
|
| -
|
| -#include "base/hash_tables.h"
|
| -#include "base/i18n/rtl.h"
|
| -#include "base/lazy_instance.h"
|
| -#include "base/memory/linked_ptr.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/stl_util.h"
|
| -#include "base/stringprintf.h"
|
| -#include "base/utf_string_conversions.h"
|
| -#include "base/values.h"
|
| -#include "chrome/common/extensions/extension_manifest_constants.h"
|
| -#include "chrome/common/extensions/extension_error_utils.h"
|
| -#include "chrome/common/extensions/extension_l10n_util.h"
|
| -#include "ui/base/l10n/l10n_util.h"
|
| -
|
| -namespace errors = extension_manifest_errors;
|
| -
|
| -const char* ExtensionMessageBundle::kContentKey = "content";
|
| -const char* ExtensionMessageBundle::kMessageKey = "message";
|
| -const char* ExtensionMessageBundle::kPlaceholdersKey = "placeholders";
|
| -
|
| -const char* ExtensionMessageBundle::kPlaceholderBegin = "$";
|
| -const char* ExtensionMessageBundle::kPlaceholderEnd = "$";
|
| -const char* ExtensionMessageBundle::kMessageBegin = "__MSG_";
|
| -const char* ExtensionMessageBundle::kMessageEnd = "__";
|
| -
|
| -// Reserved messages names.
|
| -const char* ExtensionMessageBundle::kUILocaleKey = "@@ui_locale";
|
| -const char* ExtensionMessageBundle::kBidiDirectionKey = "@@bidi_dir";
|
| -const char* ExtensionMessageBundle::kBidiReversedDirectionKey =
|
| - "@@bidi_reversed_dir";
|
| -const char* ExtensionMessageBundle::kBidiStartEdgeKey = "@@bidi_start_edge";
|
| -const char* ExtensionMessageBundle::kBidiEndEdgeKey = "@@bidi_end_edge";
|
| -const char* ExtensionMessageBundle::kExtensionIdKey = "@@extension_id";
|
| -
|
| -// Reserved messages values.
|
| -const char* ExtensionMessageBundle::kBidiLeftEdgeValue = "left";
|
| -const char* ExtensionMessageBundle::kBidiRightEdgeValue = "right";
|
| -
|
| -// Formats message in case we encounter a bad formed key in the JSON object.
|
| -// Returns false and sets |error| to actual error message.
|
| -static bool BadKeyMessage(const std::string& name, std::string* error) {
|
| - *error = base::StringPrintf(
|
| - "Name of a key \"%s\" is invalid. Only ASCII [a-z], "
|
| - "[A-Z], [0-9] and \"_\" are allowed.",
|
| - name.c_str());
|
| - return false;
|
| -}
|
| -
|
| -// static
|
| -ExtensionMessageBundle* ExtensionMessageBundle::Create(
|
| - const CatalogVector& locale_catalogs,
|
| - std::string* error) {
|
| - scoped_ptr<ExtensionMessageBundle> message_bundle(
|
| - new ExtensionMessageBundle);
|
| - if (!message_bundle->Init(locale_catalogs, error))
|
| - return NULL;
|
| -
|
| - return message_bundle.release();
|
| -}
|
| -
|
| -bool ExtensionMessageBundle::Init(const CatalogVector& locale_catalogs,
|
| - std::string* error) {
|
| - dictionary_.clear();
|
| -
|
| - for (CatalogVector::const_reverse_iterator it = locale_catalogs.rbegin();
|
| - it != locale_catalogs.rend(); ++it) {
|
| - DictionaryValue* catalog = (*it).get();
|
| - for (DictionaryValue::key_iterator key_it = catalog->begin_keys();
|
| - key_it != catalog->end_keys(); ++key_it) {
|
| - std::string key(StringToLowerASCII(*key_it));
|
| - if (!IsValidName(*key_it))
|
| - return BadKeyMessage(key, error);
|
| - std::string value;
|
| - if (!GetMessageValue(*key_it, *catalog, &value, error))
|
| - return false;
|
| - // Keys are not case-sensitive.
|
| - dictionary_[key] = value;
|
| - }
|
| - }
|
| -
|
| - if (!AppendReservedMessagesForLocale(
|
| - extension_l10n_util::CurrentLocaleOrDefault(), error))
|
| - return false;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool ExtensionMessageBundle::AppendReservedMessagesForLocale(
|
| - const std::string& app_locale, std::string* error) {
|
| - SubstitutionMap append_messages;
|
| - append_messages[kUILocaleKey] = app_locale;
|
| -
|
| - // Calling base::i18n::GetTextDirection on non-UI threads doesn't seems safe,
|
| - // so we use GetTextDirectionForLocale instead.
|
| - if (base::i18n::GetTextDirectionForLocale(app_locale.c_str()) ==
|
| - base::i18n::RIGHT_TO_LEFT) {
|
| - append_messages[kBidiDirectionKey] = "rtl";
|
| - append_messages[kBidiReversedDirectionKey] = "ltr";
|
| - append_messages[kBidiStartEdgeKey] = kBidiRightEdgeValue;
|
| - append_messages[kBidiEndEdgeKey] = kBidiLeftEdgeValue;
|
| - } else {
|
| - append_messages[kBidiDirectionKey] = "ltr";
|
| - append_messages[kBidiReversedDirectionKey] = "rtl";
|
| - append_messages[kBidiStartEdgeKey] = kBidiLeftEdgeValue;
|
| - append_messages[kBidiEndEdgeKey] = kBidiRightEdgeValue;
|
| - }
|
| -
|
| - // Add all reserved messages to the dictionary, but check for collisions.
|
| - SubstitutionMap::iterator it = append_messages.begin();
|
| - for (; it != append_messages.end(); ++it) {
|
| - if (ContainsKey(dictionary_, it->first)) {
|
| - *error = ExtensionErrorUtils::FormatErrorMessage(
|
| - errors::kReservedMessageFound, it->first);
|
| - return false;
|
| - } else {
|
| - dictionary_[it->first] = it->second;
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool ExtensionMessageBundle::GetMessageValue(const std::string& key,
|
| - const DictionaryValue& catalog,
|
| - std::string* value,
|
| - std::string* error) const {
|
| - // Get the top level tree for given key (name part).
|
| - DictionaryValue* name_tree;
|
| - if (!catalog.GetDictionaryWithoutPathExpansion(key, &name_tree)) {
|
| - *error = base::StringPrintf("Not a valid tree for key %s.", key.c_str());
|
| - return false;
|
| - }
|
| - // Extract message from it.
|
| - if (!name_tree->GetString(kMessageKey, value)) {
|
| - *error = base::StringPrintf(
|
| - "There is no \"%s\" element for key %s.", kMessageKey, key.c_str());
|
| - return false;
|
| - }
|
| -
|
| - SubstitutionMap placeholders;
|
| - if (!GetPlaceholders(*name_tree, key, &placeholders, error))
|
| - return false;
|
| -
|
| - if (!ReplacePlaceholders(placeholders, value, error))
|
| - return false;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -ExtensionMessageBundle::ExtensionMessageBundle() {
|
| -}
|
| -
|
| -bool ExtensionMessageBundle::GetPlaceholders(const DictionaryValue& name_tree,
|
| - const std::string& name_key,
|
| - SubstitutionMap* placeholders,
|
| - std::string* error) const {
|
| - if (!name_tree.HasKey(kPlaceholdersKey))
|
| - return true;
|
| -
|
| - DictionaryValue* placeholders_tree;
|
| - if (!name_tree.GetDictionary(kPlaceholdersKey, &placeholders_tree)) {
|
| - *error = base::StringPrintf("Not a valid \"%s\" element for key %s.",
|
| - kPlaceholdersKey, name_key.c_str());
|
| - return false;
|
| - }
|
| -
|
| - for (DictionaryValue::key_iterator key_it = placeholders_tree->begin_keys();
|
| - key_it != placeholders_tree->end_keys(); ++key_it) {
|
| - DictionaryValue* placeholder;
|
| - const std::string& content_key(*key_it);
|
| - if (!IsValidName(content_key))
|
| - return BadKeyMessage(content_key, error);
|
| - if (!placeholders_tree->GetDictionaryWithoutPathExpansion(content_key,
|
| - &placeholder)) {
|
| - *error = base::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 = base::StringPrintf("Invalid \"%s\" element for key %s.",
|
| - kContentKey, name_key.c_str());
|
| - return false;
|
| - }
|
| - (*placeholders)[StringToLowerASCII(content_key)] = content;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool ExtensionMessageBundle::ReplacePlaceholders(
|
| - const SubstitutionMap& placeholders,
|
| - std::string* message,
|
| - std::string* error) const {
|
| - return ReplaceVariables(placeholders,
|
| - kPlaceholderBegin,
|
| - kPlaceholderEnd,
|
| - message,
|
| - error);
|
| -}
|
| -
|
| -bool ExtensionMessageBundle::ReplaceMessages(std::string* text,
|
| - std::string* error) const {
|
| - return ReplaceMessagesWithExternalDictionary(dictionary_, text, error);
|
| -}
|
| -
|
| -ExtensionMessageBundle::~ExtensionMessageBundle() {
|
| -}
|
| -
|
| -// static
|
| -bool ExtensionMessageBundle::ReplaceMessagesWithExternalDictionary(
|
| - const SubstitutionMap& dictionary, std::string* text, std::string* error) {
|
| - return ReplaceVariables(dictionary, kMessageBegin, kMessageEnd, text, error);
|
| -}
|
| -
|
| -// static
|
| -bool ExtensionMessageBundle::ReplaceVariables(
|
| - const SubstitutionMap& variables,
|
| - const std::string& var_begin_delimiter,
|
| - const std::string& var_end_delimiter,
|
| - std::string* message,
|
| - std::string* error) {
|
| - std::string::size_type beg_index = 0;
|
| - const std::string::size_type var_begin_delimiter_size =
|
| - var_begin_delimiter.size();
|
| - while (true) {
|
| - beg_index = message->find(var_begin_delimiter, beg_index);
|
| - if (beg_index == message->npos)
|
| - return true;
|
| -
|
| - // Advance it immediately to the begining of possible variable name.
|
| - beg_index += var_begin_delimiter_size;
|
| - if (beg_index >= message->size())
|
| - return true;
|
| - std::string::size_type end_index =
|
| - message->find(var_end_delimiter, 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;
|
| - SubstitutionMap::const_iterator it =
|
| - variables.find(StringToLowerASCII(var_name));
|
| - if (it == variables.end()) {
|
| - *error = base::StringPrintf("Variable %s%s%s used but not defined.",
|
| - var_begin_delimiter.c_str(),
|
| - var_name.c_str(),
|
| - var_end_delimiter.c_str());
|
| - return false;
|
| - }
|
| -
|
| - // Replace variable with its value.
|
| - std::string value = it->second;
|
| - message->replace(beg_index - var_begin_delimiter_size,
|
| - end_index - beg_index + var_begin_delimiter_size +
|
| - var_end_delimiter.size(),
|
| - value);
|
| -
|
| - // And position pointer to after the replacement.
|
| - beg_index += value.size() - var_begin_delimiter_size;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// static
|
| -bool ExtensionMessageBundle::IsValidName(const std::string& name) {
|
| - if (name.empty())
|
| - return false;
|
| -
|
| - std::string::const_iterator it = name.begin();
|
| - for (; it != name.end(); ++it) {
|
| - // Allow only ascii 0-9, a-z, A-Z, and _ in the name.
|
| - if (!IsAsciiAlpha(*it) && !IsAsciiDigit(*it) && *it != '_' && *it != '@')
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// Dictionary interface.
|
| -
|
| -std::string ExtensionMessageBundle::GetL10nMessage(
|
| - const std::string& name) const {
|
| - return GetL10nMessage(name, dictionary_);
|
| -}
|
| -
|
| -// static
|
| -std::string ExtensionMessageBundle::GetL10nMessage(
|
| - const std::string& name, const SubstitutionMap& dictionary) {
|
| - SubstitutionMap::const_iterator it =
|
| - dictionary.find(StringToLowerASCII(name));
|
| - if (it != dictionary.end()) {
|
| - return it->second;
|
| - }
|
| -
|
| - return "";
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -//
|
| -// Renderer helper functions.
|
| -//
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -
|
| -// Unique class for Singleton.
|
| -struct ExtensionToMessagesMap {
|
| - ExtensionToMessagesMap();
|
| - ~ExtensionToMessagesMap();
|
| -
|
| - // Maps extension ID to message map.
|
| - ExtensionToL10nMessagesMap messages_map;
|
| -};
|
| -
|
| -static base::LazyInstance<ExtensionToMessagesMap> g_extension_to_messages_map =
|
| - LAZY_INSTANCE_INITIALIZER;
|
| -
|
| -ExtensionToMessagesMap::ExtensionToMessagesMap() {}
|
| -
|
| -ExtensionToMessagesMap::~ExtensionToMessagesMap() {}
|
| -
|
| -ExtensionToL10nMessagesMap* GetExtensionToL10nMessagesMap() {
|
| - return &g_extension_to_messages_map.Get().messages_map;
|
| -}
|
| -
|
| -L10nMessagesMap* GetL10nMessagesMap(const std::string& extension_id) {
|
| - ExtensionToL10nMessagesMap::iterator it =
|
| - g_extension_to_messages_map.Get().messages_map.find(extension_id);
|
| - if (it != g_extension_to_messages_map.Get().messages_map.end())
|
| - return &(it->second);
|
| -
|
| - return NULL;
|
| -}
|
|
|