summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/extensions/extension_file_util.cc1
-rw-r--r--chrome/browser/extensions/extension_l10n_util.cc109
-rw-r--r--chrome/browser/extensions/extension_l10n_util.h19
-rw-r--r--chrome/browser/extensions/extension_l10n_util_unittest.cc51
-rw-r--r--chrome/common/extensions/extension_message_bundle.cc54
-rw-r--r--chrome/common/extensions/extension_message_bundle.h21
-rw-r--r--chrome/common/extensions/extension_message_bundle_unittest.cc91
-rw-r--r--chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/_locales/en/messages.json14
-rw-r--r--chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/_locales/en_US/messages.json3
9 files changed, 227 insertions, 136 deletions
diff --git a/chrome/browser/extensions/extension_file_util.cc b/chrome/browser/extensions/extension_file_util.cc
index 0bd9507..23bd085 100644
--- a/chrome/browser/extensions/extension_file_util.cc
+++ b/chrome/browser/extensions/extension_file_util.cc
@@ -362,6 +362,7 @@ ExtensionMessageBundle* LoadLocaleInfo(const FilePath& extension_path,
extension_l10n_util::LoadMessageCatalogs(locale_path,
default_locale,
app_locale,
+ locales,
error);
return message_bundle;
}
diff --git a/chrome/browser/extensions/extension_l10n_util.cc b/chrome/browser/extensions/extension_l10n_util.cc
index 411de59..4c8b116 100644
--- a/chrome/browser/extensions/extension_l10n_util.cc
+++ b/chrome/browser/extensions/extension_l10n_util.cc
@@ -10,6 +10,7 @@
#include "app/l10n_util.h"
#include "base/file_util.h"
+#include "base/linked_ptr.h"
#include "base/string_util.h"
#include "base/values.h"
#include "chrome/common/extensions/extension.h"
@@ -29,49 +30,85 @@ std::string GetDefaultLocaleFromManifest(const DictionaryValue& manifest,
*error = errors::kInvalidDefaultLocale;
return "";
}
- // Normalize underscores to hyphens.
- std::replace(default_locale.begin(), default_locale.end(), '_', '-');
+
return default_locale;
}
bool AddLocale(const std::set<std::string>& chrome_locales,
const FilePath& locale_folder,
+ const std::string& locale_name,
std::set<std::string>* valid_locales,
- std::string* locale_name,
std::string* error) {
- // Normalize underscores to hyphens because that's what our locale files use.
- std::replace(locale_name->begin(), locale_name->end(), '_', '-');
// Accept name that starts with a . but don't add it to the list of supported
// locales.
- if (locale_name->find(".") == 0)
+ if (locale_name.find(".") == 0)
return true;
- if (chrome_locales.find(*locale_name) == chrome_locales.end()) {
+ if (chrome_locales.find(locale_name) == chrome_locales.end()) {
// Fail if there is an extension locale that's not in the Chrome list.
*error = StringPrintf("Supplied locale %s is not supported.",
- locale_name->c_str());
+ locale_name.c_str());
return false;
}
// Check if messages file is actually present (but don't check content).
if (file_util::PathExists(
locale_folder.AppendASCII(Extension::kMessagesFilename))) {
- valid_locales->insert(*locale_name);
+ valid_locales->insert(locale_name);
} else {
*error = StringPrintf("Catalog file is missing for locale %s.",
- locale_name->c_str());
+ locale_name.c_str());
return false;
}
return true;
}
+// Converts all - into _, to be consistent with ICU and file system names.
+static std::string NormalizeLocale(const std::string& locale) {
+ std::string normalized_locale(locale);
+ std::replace(normalized_locale.begin(), normalized_locale.end(), '-', '_');
+
+ return normalized_locale;
+}
+
+// Produce a vector of parent locales for given locale.
+// It includes the current locale in the result.
+// sr_Cyrl_RS generates sr_Cyrl_RS, sr_Cyrl and sr.
+static void GetParentLocales(const std::string& current_locale,
+ std::vector<std::string>* parent_locales) {
+ std::string locale(NormalizeLocale(current_locale));
+
+ const int kNameCapacity = 256;
+ char parent[kNameCapacity];
+ strncpy(parent, locale.c_str(), kNameCapacity);
+ parent_locales->push_back(parent);
+ UErrorCode err = U_ZERO_ERROR;
+ while (uloc_getParent(parent, parent, kNameCapacity, &err) > 0) {
+ if (err != U_ZERO_ERROR)
+ break;
+ parent_locales->push_back(parent);
+ }
+}
+
+// Extends list of Chrome locales to them and their parents, so we can do
+// proper fallback.
+static void GetAllLocales(std::set<std::string>* all_locales) {
+ const std::vector<std::string>& available_locales =
+ l10n_util::GetAvailableLocales();
+ // Add all parents of the current locale to the available locales set.
+ // I.e. for sr_Cyrl_RS we add sr_Cyrl_RS, sr_Cyrl and sr.
+ for (size_t i = 0; i < available_locales.size(); ++i) {
+ std::vector<std::string> result;
+ GetParentLocales(available_locales[i], &result);
+ all_locales->insert(result.begin(), result.end());
+ }
+}
+
bool GetValidLocales(const FilePath& locale_path,
std::set<std::string>* valid_locales,
std::string* error) {
- // Get available chrome locales as a set.
- const std::vector<std::string>& available_locales =
- l10n_util::GetAvailableLocales();
- static std::set<std::string> chrome_locales(available_locales.begin(),
- available_locales.end());
+ static std::set<std::string> chrome_locales;
+ GetAllLocales(&chrome_locales);
+
// Enumerate all supplied locales in the extension.
file_util::FileEnumerator locales(locale_path,
false,
@@ -82,8 +119,8 @@ bool GetValidLocales(const FilePath& locale_path,
WideToASCII(locale_folder.BaseName().ToWStringHack());
if (!AddLocale(chrome_locales,
locale_folder,
+ locale_name,
valid_locales,
- &locale_name,
error)) {
return false;
}
@@ -103,9 +140,8 @@ bool GetValidLocales(const FilePath& locale_path,
static DictionaryValue* LoadMessageFile(const FilePath& locale_path,
const std::string& locale,
std::string* error) {
+
std::string extension_locale = locale;
- // Normalize hyphens to underscores because that's what our locale files use.
- std::replace(extension_locale.begin(), extension_locale.end(), '-', '_');
FilePath file = locale_path.AppendASCII(extension_locale)
.AppendASCII(Extension::kMessagesFilename);
JSONFileValueSerializer messages_serializer(file);
@@ -124,24 +160,31 @@ ExtensionMessageBundle* LoadMessageCatalogs(
const FilePath& locale_path,
const std::string& default_locale,
const std::string& application_locale,
+ const std::set<std::string>& valid_locales,
std::string* error) {
- scoped_ptr<DictionaryValue> default_catalog(
- LoadMessageFile(locale_path, default_locale, error));
- if (!default_catalog.get()) {
- return false;
- }
-
- scoped_ptr<DictionaryValue> app_catalog(
- LoadMessageFile(locale_path, application_locale, error));
- if (!app_catalog.get()) {
- // Only default catalog has to be present. This is not an error.
- app_catalog.reset(new DictionaryValue);
- error->clear();
+ // Order locales to load as current_locale, first_parent, ..., default_locale.
+ std::vector<std::string> all_fallback_locales;
+ if (!application_locale.empty() && application_locale != default_locale)
+ GetParentLocales(application_locale, &all_fallback_locales);
+ all_fallback_locales.push_back(default_locale);
+
+ std::vector<linked_ptr<DictionaryValue> > catalogs;
+ for (size_t i = 0; i < all_fallback_locales.size(); ++i) {
+ // Skip all parent locales that are not supplied.
+ if (valid_locales.find(all_fallback_locales[i]) == valid_locales.end())
+ continue;
+ linked_ptr<DictionaryValue> catalog(
+ LoadMessageFile(locale_path, all_fallback_locales[i], error));
+ if (!catalog.get()) {
+ // If locale is valid, but messages.json is corrupted or missing, return
+ // an error.
+ return false;
+ } else {
+ catalogs.push_back(catalog);
+ }
}
- return ExtensionMessageBundle::Create(*default_catalog,
- *app_catalog,
- error);
+ return ExtensionMessageBundle::Create(catalogs, error);
}
FilePath GetL10nRelativePath(const FilePath& relative_resource_path) {
diff --git a/chrome/browser/extensions/extension_l10n_util.h b/chrome/browser/extensions/extension_l10n_util.h
index b3be601..57c2033 100644
--- a/chrome/browser/extensions/extension_l10n_util.h
+++ b/chrome/browser/extensions/extension_l10n_util.h
@@ -29,8 +29,8 @@ std::string GetDefaultLocaleFromManifest(const DictionaryValue& manifest,
// If file name starts with . return true (helps testing extensions under svn).
bool AddLocale(const std::set<std::string>& chrome_locales,
const FilePath& locale_folder,
+ const std::string& locale_name,
std::set<std::string>* valid_locales,
- std::string* locale_name,
std::string* error);
// Adds valid locales to the extension.
@@ -44,16 +44,17 @@ bool GetValidLocales(const FilePath& locale_path,
std::set<std::string>* locales,
std::string* error);
-// Loads messages file for default locale, and application locale (application
-// locale doesn't have to exist).
-// It creates simplified in-memory representation of name-value pairs, where
-// value part is actual message with placeholders resolved.
+// Loads messages file for default locale, and application locales (application
+// locales doesn't have to exist). Application locale is current locale and its
+// parents.
// Returns message bundle if it can load default locale messages file, and all
// messages are valid, else returns NULL and sets error.
-ExtensionMessageBundle* LoadMessageCatalogs(const FilePath& locale_path,
- const std::string& default_locale,
- const std::string& app_locale,
- std::string* error);
+ExtensionMessageBundle* LoadMessageCatalogs(
+ const FilePath& locale_path,
+ const std::string& default_locale,
+ const std::string& app_locale,
+ const std::set<std::string>& valid_locales,
+ std::string* error);
// Returns relative l10n path to the resource.
FilePath GetL10nRelativePath(const FilePath& relative_resource_path);
diff --git a/chrome/browser/extensions/extension_l10n_util_unittest.cc b/chrome/browser/extensions/extension_l10n_util_unittest.cc
index 5c0df39..acf946c 100644
--- a/chrome/browser/extensions/extension_l10n_util_unittest.cc
+++ b/chrome/browser/extensions/extension_l10n_util_unittest.cc
@@ -66,8 +66,35 @@ TEST(ExtensionL10nUtil, GetValidLocalesWithValidLocalesAndMessagesFile) {
EXPECT_TRUE(extension_l10n_util::GetValidLocales(install_dir,
&locales,
&error));
- EXPECT_EQ(2U, locales.size());
+ EXPECT_EQ(3U, locales.size());
EXPECT_TRUE(locales.find("sr") != locales.end());
+ EXPECT_TRUE(locales.find("en") != locales.end());
+ EXPECT_TRUE(locales.find("en_US") != locales.end());
+}
+
+TEST(ExtensionL10nUtil, LoadMessageCatalogsValidFallback) {
+ FilePath install_dir;
+ ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &install_dir));
+ install_dir = install_dir.AppendASCII("extensions")
+ .AppendASCII("good")
+ .AppendASCII("Extensions")
+ .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
+ .AppendASCII("1.0.0.0")
+ .AppendASCII(Extension::kLocaleFolder);
+
+ std::string error;
+ std::set<std::string> locales;
+ EXPECT_TRUE(extension_l10n_util::GetValidLocales(install_dir,
+ &locales,
+ &error));
+
+ scoped_ptr<ExtensionMessageBundle> bundle(
+ extension_l10n_util::LoadMessageCatalogs(
+ install_dir, "sr", "en_US", locales, &error));
+ ASSERT_FALSE(NULL == bundle.get());
+ EXPECT_TRUE(error.empty());
+ EXPECT_EQ("Color", bundle->GetL10nMessage("color"));
+ EXPECT_EQ("Not in the US or GB.", bundle->GetL10nMessage("not_in_US_or_GB"));
}
TEST(ExtensionL10nUtil, LoadMessageCatalogsMissingFiles) {
@@ -77,10 +104,14 @@ TEST(ExtensionL10nUtil, LoadMessageCatalogsMissingFiles) {
FilePath src_path = temp.path().AppendASCII(Extension::kLocaleFolder);
ASSERT_TRUE(file_util::CreateDirectory(src_path));
+ std::set<std::string> valid_locales;
+ valid_locales.insert("sr");
+ valid_locales.insert("en");
std::string error;
EXPECT_TRUE(NULL == extension_l10n_util::LoadMessageCatalogs(src_path,
- "en-US",
+ "en",
"sr",
+ valid_locales,
&error));
EXPECT_FALSE(error.empty());
}
@@ -92,7 +123,7 @@ TEST(ExtensionL10nUtil, LoadMessageCatalogsBadJSONFormat) {
FilePath src_path = temp.path().AppendASCII(Extension::kLocaleFolder);
ASSERT_TRUE(file_util::CreateDirectory(src_path));
- FilePath locale = src_path.AppendASCII("en_US");
+ FilePath locale = src_path.AppendASCII("sr");
ASSERT_TRUE(file_util::CreateDirectory(locale));
std::string data = "{ \"name\":";
@@ -100,10 +131,14 @@ TEST(ExtensionL10nUtil, LoadMessageCatalogsBadJSONFormat) {
file_util::WriteFile(locale.AppendASCII(Extension::kMessagesFilename),
data.c_str(), data.length()));
+ std::set<std::string> valid_locales;
+ valid_locales.insert("sr");
+ valid_locales.insert("en_US");
std::string error;
EXPECT_TRUE(NULL == extension_l10n_util::LoadMessageCatalogs(src_path,
- "en-US",
+ "en_US",
"sr",
+ valid_locales,
&error));
EXPECT_EQ("Line: 1, column: 10, Syntax error.", error);
}
@@ -115,7 +150,7 @@ TEST(ExtensionL10nUtil, LoadMessageCatalogsDuplicateKeys) {
FilePath src_path = temp.path().AppendASCII(Extension::kLocaleFolder);
ASSERT_TRUE(file_util::CreateDirectory(src_path));
- FilePath locale_1 = src_path.AppendASCII("en_US");
+ FilePath locale_1 = src_path.AppendASCII("en");
ASSERT_TRUE(file_util::CreateDirectory(locale_1));
std::string data =
@@ -132,13 +167,17 @@ TEST(ExtensionL10nUtil, LoadMessageCatalogsDuplicateKeys) {
file_util::WriteFile(locale_2.AppendASCII(Extension::kMessagesFilename),
data.c_str(), data.length()));
+ std::set<std::string> valid_locales;
+ valid_locales.insert("sr");
+ valid_locales.insert("en");
std::string error;
// JSON parser hides duplicates. We are going to get only one key/value
// pair at the end.
scoped_ptr<ExtensionMessageBundle> message_bundle(
extension_l10n_util::LoadMessageCatalogs(src_path,
- "en-US",
+ "en",
"sr",
+ valid_locales,
&error));
EXPECT_TRUE(NULL != message_bundle.get());
EXPECT_TRUE(error.empty());
diff --git a/chrome/common/extensions/extension_message_bundle.cc b/chrome/common/extensions/extension_message_bundle.cc
index 980dd08..9e3a7df 100644
--- a/chrome/common/extensions/extension_message_bundle.cc
+++ b/chrome/common/extensions/extension_message_bundle.cc
@@ -5,8 +5,10 @@
#include "chrome/common/extensions/extension_message_bundle.h"
#include <string>
+#include <vector>
#include "base/hash_tables.h"
+#include "base/linked_ptr.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "base/values.h"
@@ -34,52 +36,34 @@ static bool BadKeyMessage(const std::string& name, std::string* error) {
// static
ExtensionMessageBundle* ExtensionMessageBundle::Create(
- const DictionaryValue& default_locale_catalog,
- const DictionaryValue& current_locale_catalog,
+ const CatalogVector& locale_catalogs,
std::string* error) {
scoped_ptr<ExtensionMessageBundle> message_bundle(
new ExtensionMessageBundle);
- if (!message_bundle->Init(default_locale_catalog,
- current_locale_catalog,
- error))
+ if (!message_bundle->Init(locale_catalogs, error))
return NULL;
return message_bundle.release();
}
-bool ExtensionMessageBundle::Init(const DictionaryValue& default_locale_catalog,
- const DictionaryValue& current_locale_catalog,
+bool ExtensionMessageBundle::Init(const CatalogVector& locale_catalogs,
std::string* error) {
dictionary_.clear();
- // Create a single dictionary out of default and current_locale catalogs.
- // If message is missing from current_locale catalog, we take one from default
- // catalog.
- DictionaryValue::key_iterator key_it = current_locale_catalog.begin_keys();
- for (; key_it != current_locale_catalog.end_keys(); ++key_it) {
- std::string key(StringToLowerASCII(WideToUTF8(*key_it)));
- if (!IsValidName(*key_it))
- return BadKeyMessage(key, error);
- std::string value;
- if (!GetMessageValue(*key_it, current_locale_catalog, &value, error))
- return false;
- // Keys are not case-sensitive.
- dictionary_[key] = value;
- }
-
- key_it = default_locale_catalog.begin_keys();
- for (; key_it != default_locale_catalog.end_keys(); ++key_it) {
- std::string key(StringToLowerASCII(WideToUTF8(*key_it)));
- if (!IsValidName(*key_it))
- 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, default_locale_catalog, &value, error))
- return false;
- // Keys are not case-sensitive.
- dictionary_[key] = value;
+ CatalogVector::const_reverse_iterator it = locale_catalogs.rbegin();
+ for (; it != locale_catalogs.rend(); ++it) {
+ DictionaryValue* catalog = (*it).get();
+ DictionaryValue::key_iterator key_it = catalog->begin_keys();
+ for (; key_it != catalog->end_keys(); ++key_it) {
+ std::string key(StringToLowerASCII(WideToUTF8(*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;
+ }
}
return true;
diff --git a/chrome/common/extensions/extension_message_bundle.h b/chrome/common/extensions/extension_message_bundle.h
index 4c57117..3c57df7 100644
--- a/chrome/common/extensions/extension_message_bundle.h
+++ b/chrome/common/extensions/extension_message_bundle.h
@@ -7,7 +7,9 @@
#include <map>
#include <string>
+#include <vector>
+#include "base/linked_ptr.h"
#include "base/values.h"
// Contains localized extension messages for one locale. Any messages that the
@@ -15,6 +17,7 @@
class ExtensionMessageBundle {
public:
typedef std::map<std::string, std::string> SubstitutionMap;
+ typedef std::vector<linked_ptr<DictionaryValue> > CatalogVector;
// JSON keys of interest for messages file.
static const wchar_t* kContentKey;
@@ -32,10 +35,10 @@ class ExtensionMessageBundle {
static const char* kExtensionDescription;
// Creates ExtensionMessageBundle or returns NULL if there was an error.
- static ExtensionMessageBundle* Create(
- const DictionaryValue& default_locale_catalog,
- const DictionaryValue& current_locale_catalog,
- std::string* error);
+ // Expects locale_catalogs to be sorted from more specific to less specific,
+ // with default catalog at the end.
+ static ExtensionMessageBundle* Create(const CatalogVector& locale_catalogs,
+ std::string* error);
// Get message from the catalog with given key.
// Returned message has all of the internal placeholders resolved to their
@@ -82,13 +85,11 @@ class ExtensionMessageBundle {
// Use Create to create ExtensionMessageBundle instance.
ExtensionMessageBundle();
- // Initializes the instance from the contents of two catalogs. If a key is not
- // present in current_locale_catalog, the value from default_local_catalog is
- // used instead.
+ // Initializes the instance from the contents of vector of catalogs.
+ // If the key is not present in more specific catalog we fall back to next one
+ // (less specific).
// Returns false on error.
- bool Init(const DictionaryValue& default_locale_catalog,
- const DictionaryValue& current_locale_catalog,
- std::string* error);
+ bool Init(const CatalogVector& locale_catalogs, std::string* error);
// Helper methods that navigate JSON tree and return simplified message.
// They replace all $PLACEHOLDERS$ with their value, and return just key/value
diff --git a/chrome/common/extensions/extension_message_bundle_unittest.cc b/chrome/common/extensions/extension_message_bundle_unittest.cc
index df2b7c7..9c27055 100644
--- a/chrome/common/extensions/extension_message_bundle_unittest.cc
+++ b/chrome/common/extensions/extension_message_bundle_unittest.cc
@@ -5,7 +5,9 @@
#include "chrome/common/extensions/extension_message_bundle.h"
#include <string>
+#include <vector>
+#include "base/linked_ptr.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "base/values.h"
@@ -49,11 +51,13 @@ void CreateMessageTree(const std::wstring& name,
SetDictionary(name, dict, message_tree);
}
-void CreateGoodDictionary(DictionaryValue* dict) {
- dict->Clear();
+// Caller owns the memory.
+DictionaryValue* CreateGoodDictionary() {
+ DictionaryValue* dict = new DictionaryValue;
CreateMessageTree(L"n1", "message1 $a$ $b$", true, dict);
CreateMessageTree(L"n2", "message2 $c$", true, dict);
CreateMessageTree(L"n3", "message3", false, dict);
+ return dict;
}
enum BadDictionary {
@@ -67,9 +71,9 @@ enum BadDictionary {
MESSAGE_PLACEHOLDER_DOESNT_MATCH,
};
-void CreateBadDictionary(DictionaryValue* dict,
- enum BadDictionary what_is_bad) {
- CreateGoodDictionary(dict);
+// Caller owns the memory.
+DictionaryValue* CreateBadDictionary(enum BadDictionary what_is_bad) {
+ DictionaryValue* dict = CreateGoodDictionary();
// Now remove/break things.
switch (what_is_bad) {
case INVALID_NAME:
@@ -104,27 +108,27 @@ void CreateBadDictionary(DictionaryValue* dict,
CreateContentTree(L"x", "X", value);
break;
}
+
+ return dict;
}
TEST(ExtensionMessageBundle, InitEmptyDictionaries) {
- DictionaryValue default_dict;
- DictionaryValue app_dict;
+ std::vector<linked_ptr<DictionaryValue> > catalogs;
std::string error;
scoped_ptr<ExtensionMessageBundle> handler(
- ExtensionMessageBundle::Create(default_dict, app_dict, &error));
+ ExtensionMessageBundle::Create(catalogs, &error));
EXPECT_TRUE(handler.get() != NULL);
EXPECT_EQ(0U, handler->size());
}
-TEST(ExtensionMessageBundle, InitGoodDefaultDictEmptyAppDict) {
- DictionaryValue default_dict;
- DictionaryValue app_dict;
- std::string error;
+TEST(ExtensionMessageBundle, InitGoodDefaultDict) {
+ std::vector<linked_ptr<DictionaryValue> > catalogs;
+ catalogs.push_back(linked_ptr<DictionaryValue>(CreateGoodDictionary()));
- CreateGoodDictionary(&default_dict);
+ std::string error;
scoped_ptr<ExtensionMessageBundle> handler(
- ExtensionMessageBundle::Create(default_dict, app_dict, &error));
+ ExtensionMessageBundle::Create(catalogs, &error));
EXPECT_TRUE(handler.get() != NULL);
EXPECT_EQ(3U, handler->size());
@@ -135,22 +139,22 @@ TEST(ExtensionMessageBundle, InitGoodDefaultDictEmptyAppDict) {
}
TEST(ExtensionMessageBundle, InitAppDictConsultedFirst) {
- DictionaryValue default_dict;
- DictionaryValue app_dict;
- std::string error;
+ std::vector<linked_ptr<DictionaryValue> > catalogs;
+ catalogs.push_back(linked_ptr<DictionaryValue>(CreateGoodDictionary()));
+ catalogs.push_back(linked_ptr<DictionaryValue>(CreateGoodDictionary()));
- CreateGoodDictionary(&default_dict);
- CreateGoodDictionary(&app_dict);
+ DictionaryValue* app_dict = catalogs[0].get();
// Flip placeholders in message of n1 tree.
- app_dict.SetString(L"n1.message", "message1 $b$ $a$");
+ app_dict->SetString(L"n1.message", "message1 $b$ $a$");
// Remove one message from app dict.
- app_dict.Remove(L"n2", NULL);
+ app_dict->Remove(L"n2", NULL);
// Replace n3 with N3.
- app_dict.Remove(L"n3", NULL);
- CreateMessageTree(L"N3", "message3_app_dict", false, &app_dict);
+ app_dict->Remove(L"n3", NULL);
+ CreateMessageTree(L"N3", "message3_app_dict", false, app_dict);
+ std::string error;
scoped_ptr<ExtensionMessageBundle> handler(
- ExtensionMessageBundle::Create(default_dict, app_dict, &error));
+ ExtensionMessageBundle::Create(catalogs, &error));
EXPECT_TRUE(handler.get() != NULL);
EXPECT_EQ(3U, handler->size());
@@ -161,50 +165,51 @@ TEST(ExtensionMessageBundle, InitAppDictConsultedFirst) {
}
TEST(ExtensionMessageBundle, InitBadAppDict) {
- DictionaryValue default_dict;
- DictionaryValue app_dict;
- std::string error;
+ std::vector<linked_ptr<DictionaryValue> > catalogs;
+ catalogs.push_back(
+ linked_ptr<DictionaryValue>(CreateBadDictionary(INVALID_NAME)));
+ catalogs.push_back(linked_ptr<DictionaryValue>(CreateGoodDictionary()));
- CreateBadDictionary(&app_dict, INVALID_NAME);
+ std::string error;
scoped_ptr<ExtensionMessageBundle> handler(
- ExtensionMessageBundle::Create(default_dict, app_dict, &error));
+ ExtensionMessageBundle::Create(catalogs, &error));
EXPECT_TRUE(handler.get() == NULL);
EXPECT_EQ("Name of a key \"n 5\" is invalid. Only ASCII [a-z], "
"[A-Z], [0-9] and \"_\" are allowed.", error);
- CreateBadDictionary(&app_dict, NAME_NOT_A_TREE);
- handler.reset(ExtensionMessageBundle::Create(default_dict, app_dict, &error));
+ catalogs[0].reset(CreateBadDictionary(NAME_NOT_A_TREE));
+ handler.reset(ExtensionMessageBundle::Create(catalogs, &error));
EXPECT_TRUE(handler.get() == NULL);
EXPECT_EQ("Not a valid tree for key n4.", error);
- CreateBadDictionary(&app_dict, EMPTY_NAME_TREE);
- handler.reset(ExtensionMessageBundle::Create(default_dict, app_dict, &error));
+ catalogs[0].reset(CreateBadDictionary(EMPTY_NAME_TREE));
+ handler.reset(ExtensionMessageBundle::Create(catalogs, &error));
EXPECT_TRUE(handler.get() == NULL);
EXPECT_EQ("There is no \"message\" element for key n4.", error);
- CreateBadDictionary(&app_dict, MISSING_MESSAGE);
- handler.reset(ExtensionMessageBundle::Create(default_dict, app_dict, &error));
+ catalogs[0].reset(CreateBadDictionary(MISSING_MESSAGE));
+ handler.reset(ExtensionMessageBundle::Create(catalogs, &error));
EXPECT_TRUE(handler.get() == NULL);
EXPECT_EQ("There is no \"message\" element for key n1.", error);
- CreateBadDictionary(&app_dict, PLACEHOLDER_NOT_A_TREE);
- handler.reset(ExtensionMessageBundle::Create(default_dict, app_dict, &error));
+ catalogs[0].reset(CreateBadDictionary(PLACEHOLDER_NOT_A_TREE));
+ handler.reset(ExtensionMessageBundle::Create(catalogs, &error));
EXPECT_TRUE(handler.get() == NULL);
EXPECT_EQ("Not a valid \"placeholders\" element for key n1.", error);
- CreateBadDictionary(&app_dict, EMPTY_PLACEHOLDER_TREE);
- handler.reset(ExtensionMessageBundle::Create(default_dict, app_dict, &error));
+ catalogs[0].reset(CreateBadDictionary(EMPTY_PLACEHOLDER_TREE));
+ handler.reset(ExtensionMessageBundle::Create(catalogs, &error));
EXPECT_TRUE(handler.get() == NULL);
EXPECT_EQ("Variable $a$ used but not defined.", error);
- CreateBadDictionary(&app_dict, CONTENT_MISSING);
- handler.reset(ExtensionMessageBundle::Create(default_dict, app_dict, &error));
+ catalogs[0].reset(CreateBadDictionary(CONTENT_MISSING));
+ handler.reset(ExtensionMessageBundle::Create(catalogs, &error));
EXPECT_TRUE(handler.get() == NULL);
EXPECT_EQ("Invalid \"content\" element for key n1.", error);
- CreateBadDictionary(&app_dict, MESSAGE_PLACEHOLDER_DOESNT_MATCH);
- handler.reset(ExtensionMessageBundle::Create(default_dict, app_dict, &error));
+ catalogs[0].reset(CreateBadDictionary(MESSAGE_PLACEHOLDER_DOESNT_MATCH));
+ handler.reset(ExtensionMessageBundle::Create(catalogs, &error));
EXPECT_TRUE(handler.get() == NULL);
EXPECT_EQ("Variable $a$ used but not defined.", error);
}
diff --git a/chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/_locales/en/messages.json b/chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/_locales/en/messages.json
new file mode 100644
index 0000000..d6c7577
--- /dev/null
+++ b/chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/_locales/en/messages.json
@@ -0,0 +1,14 @@
+{
+ "chrome_extension_name": {
+ "message": "My extension 1"
+ },
+ "chrome_extension_description": {
+ "message": "The first extension that I made."
+ },
+ "color": {
+ "message": "Colour"
+ },
+ "not_in_US_or_GB": {
+ "message": "Not in the US or GB."
+ }
+}
diff --git a/chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/_locales/en_US/messages.json b/chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/_locales/en_US/messages.json
index c600b46..3630ecb 100644
--- a/chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/_locales/en_US/messages.json
+++ b/chrome/test/data/extensions/good/Extensions/behllobkkfkfnphdnhnkndlbkcpglgmj/1.0.0.0/_locales/en_US/messages.json
@@ -4,5 +4,8 @@
},
"chrome_extension_description": {
"message": "The first extension that I made."
+ },
+ "color": {
+ "message": "Color"
}
}