Index: chrome/common/extensions/message_bundle.cc |
diff --git a/chrome/common/extensions/message_bundle.cc b/chrome/common/extensions/message_bundle.cc |
deleted file mode 100644 |
index 9a5f4b035265f3640257b938c60a1b2d9e6d982c..0000000000000000000000000000000000000000 |
--- a/chrome/common/extensions/message_bundle.cc |
+++ /dev/null |
@@ -1,348 +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/message_bundle.h" |
- |
-#include <string> |
-#include <vector> |
- |
-#include "base/containers/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/strings/stringprintf.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "base/values.h" |
-#include "chrome/common/extensions/extension_l10n_util.h" |
-#include "extensions/common/error_utils.h" |
-#include "extensions/common/manifest_constants.h" |
-#include "ui/base/l10n/l10n_util.h" |
- |
-namespace extensions { |
- |
-namespace errors = manifest_errors; |
- |
-const char* MessageBundle::kContentKey = "content"; |
-const char* MessageBundle::kMessageKey = "message"; |
-const char* MessageBundle::kPlaceholdersKey = "placeholders"; |
- |
-const char* MessageBundle::kPlaceholderBegin = "$"; |
-const char* MessageBundle::kPlaceholderEnd = "$"; |
-const char* MessageBundle::kMessageBegin = "__MSG_"; |
-const char* MessageBundle::kMessageEnd = "__"; |
- |
-// Reserved messages names. |
-const char* MessageBundle::kUILocaleKey = "@@ui_locale"; |
-const char* MessageBundle::kBidiDirectionKey = "@@bidi_dir"; |
-const char* MessageBundle::kBidiReversedDirectionKey = |
- "@@bidi_reversed_dir"; |
-const char* MessageBundle::kBidiStartEdgeKey = "@@bidi_start_edge"; |
-const char* MessageBundle::kBidiEndEdgeKey = "@@bidi_end_edge"; |
-const char* MessageBundle::kExtensionIdKey = "@@extension_id"; |
- |
-// Reserved messages values. |
-const char* MessageBundle::kBidiLeftEdgeValue = "left"; |
-const char* MessageBundle::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 |
-MessageBundle* MessageBundle::Create(const CatalogVector& locale_catalogs, |
- std::string* error) { |
- scoped_ptr<MessageBundle> message_bundle(new MessageBundle); |
- if (!message_bundle->Init(locale_catalogs, error)) |
- return NULL; |
- |
- return message_bundle.release(); |
-} |
- |
-bool MessageBundle::Init(const CatalogVector& locale_catalogs, |
- std::string* error) { |
- dictionary_.clear(); |
- |
- for (CatalogVector::const_reverse_iterator it = locale_catalogs.rbegin(); |
- it != locale_catalogs.rend(); ++it) { |
- base::DictionaryValue* catalog = (*it).get(); |
- for (base::DictionaryValue::Iterator message_it(*catalog); |
- !message_it.IsAtEnd(); message_it.Advance()) { |
- std::string key(StringToLowerASCII(message_it.key())); |
- if (!IsValidName(message_it.key())) |
- return BadKeyMessage(key, error); |
- std::string value; |
- if (!GetMessageValue(message_it.key(), message_it.value(), &value, error)) |
- return false; |
- // Keys are not case-sensitive. |
- dictionary_[key] = value; |
- } |
- } |
- |
- if (!AppendReservedMessagesForLocale( |
- extension_l10n_util::CurrentLocaleOrDefault(), error)) |
- return false; |
- |
- return true; |
-} |
- |
-bool MessageBundle::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 = ErrorUtils::FormatErrorMessage( |
- errors::kReservedMessageFound, it->first); |
- return false; |
- } else { |
- dictionary_[it->first] = it->second; |
- } |
- } |
- |
- return true; |
-} |
- |
-bool MessageBundle::GetMessageValue(const std::string& key, |
- const base::Value& name_value, |
- std::string* value, |
- std::string* error) const { |
- // Get the top level tree for given key (name part). |
- const base::DictionaryValue* name_tree; |
- if (!name_value.GetAsDictionary(&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; |
-} |
- |
-MessageBundle::MessageBundle() { |
-} |
- |
-bool MessageBundle::GetPlaceholders(const base::DictionaryValue& name_tree, |
- const std::string& name_key, |
- SubstitutionMap* placeholders, |
- std::string* error) const { |
- if (!name_tree.HasKey(kPlaceholdersKey)) |
- return true; |
- |
- const base::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 (base::DictionaryValue::Iterator it(*placeholders_tree); !it.IsAtEnd(); |
- it.Advance()) { |
- const base::DictionaryValue* placeholder; |
- const std::string& content_key(it.key()); |
- if (!IsValidName(content_key)) |
- return BadKeyMessage(content_key, error); |
- if (!it.value().GetAsDictionary(&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 MessageBundle::ReplacePlaceholders(const SubstitutionMap& placeholders, |
- std::string* message, |
- std::string* error) const { |
- return ReplaceVariables(placeholders, |
- kPlaceholderBegin, |
- kPlaceholderEnd, |
- message, |
- error); |
-} |
- |
-bool MessageBundle::ReplaceMessages(std::string* text, |
- std::string* error) const { |
- return ReplaceMessagesWithExternalDictionary(dictionary_, text, error); |
-} |
- |
-MessageBundle::~MessageBundle() { |
-} |
- |
-// static |
-bool MessageBundle::ReplaceMessagesWithExternalDictionary( |
- const SubstitutionMap& dictionary, std::string* text, std::string* error) { |
- return ReplaceVariables(dictionary, kMessageBegin, kMessageEnd, text, error); |
-} |
- |
-// static |
-bool MessageBundle::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 MessageBundle::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 MessageBundle::GetL10nMessage(const std::string& name) const { |
- return GetL10nMessage(name, dictionary_); |
-} |
- |
-// static |
-std::string MessageBundle::GetL10nMessage(const std::string& name, |
- const SubstitutionMap& dictionary) { |
- SubstitutionMap::const_iterator it = |
- dictionary.find(StringToLowerASCII(name)); |
- if (it != dictionary.end()) { |
- return it->second; |
- } |
- |
- return std::string(); |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// |
-// 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; |
-} |
- |
-void EraseL10nMessagesMap(const std::string& extension_id) { |
- g_extension_to_messages_map.Get().messages_map.erase(extension_id); |
-} |
- |
-} // namespace extensions |