diff options
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" } } |