diff options
-rw-r--r-- | chrome/browser/extensions/extension_file_util.cc | 60 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_file_util.h | 7 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_file_util_unittest.cc | 109 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_l10n_util.cc | 90 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_l10n_util.h | 46 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_l10n_util_unittest.cc | 135 | ||||
-rw-r--r-- | chrome/chrome.gyp | 3 | ||||
-rw-r--r-- | chrome/common/extensions/extension.cc | 14 | ||||
-rw-r--r-- | chrome/common/extensions/extension.h | 26 | ||||
-rw-r--r-- | chrome/common/extensions/extension_constants.cc | 7 | ||||
-rw-r--r-- | chrome/common/extensions/extension_constants.h | 6 | ||||
-rw-r--r-- | chrome/common/extensions/extension_unittest.cc | 6 |
12 files changed, 508 insertions, 1 deletions
diff --git a/chrome/browser/extensions/extension_file_util.cc b/chrome/browser/extensions/extension_file_util.cc index 07ef77f..bf6cd9c 100644 --- a/chrome/browser/extensions/extension_file_util.cc +++ b/chrome/browser/extensions/extension_file_util.cc @@ -8,6 +8,7 @@ #include "base/logging.h" #include "base/scoped_temp_dir.h" #include "base/string_util.h" +#include "chrome/browser/extensions/extension_l10n_util.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_constants.h" #include "chrome/common/json_value_serializer.h" @@ -276,6 +277,27 @@ Extension* LoadExtension(const FilePath& extension_path, bool require_key, } } + // Load locale information if available. + FilePath locale_path = extension_path.AppendASCII(Extension::kLocaleFolder); + if (file_util::PathExists(locale_path)) { + if (!extension_l10n_util::AddValidLocales(locale_path, + extension.get(), + error)) { + return NULL; + } + + if (!extension_l10n_util::ValidateDefaultLocale(extension.get())) { + *error = extension_manifest_errors::kLocalesNoDefaultLocaleSpecified; + return NULL; + } + } + + // Check children of extension root to see if any of them start with _ and is + // not on the reserved list. + if (!CheckForIllegalFilenames(extension_path, error)) { + return NULL; + } + return extension.release(); } @@ -349,4 +371,42 @@ void GarbageCollectExtensions(const FilePath& install_directory) { } } +bool CheckForIllegalFilenames(const FilePath& extension_path, + std::string* error) { + // Reserved underscore names. + static const char* reserved_names[] = { + Extension::kLocaleFolder + }; + static std::set<std::string> reserved_underscore_names( + reserved_names, reserved_names + arraysize(reserved_names)); + + // Enumerate all files and directories in the extension root. + // There is a problem when using pattern "_*" with FileEnumerator, so we have + // to cheat with find_first_of and match all. + file_util::FileEnumerator all_files( + extension_path, + false, + static_cast<file_util::FileEnumerator::FILE_TYPE>( + file_util::FileEnumerator::DIRECTORIES | + file_util::FileEnumerator::FILES)); + + FilePath files; + while (!(files = all_files.Next()).empty()) { + std::string filename = + WideToASCII(files.BaseName().ToWStringHack()); + // Skip all that don't start with "_". + if (filename.find_first_of("_") != 0) continue; + if (reserved_underscore_names.find(filename) == + reserved_underscore_names.end()) { + *error = StringPrintf( + "Cannot load extension with file or directory name %s." + "Filenames starting with \"_\" are reserved for use by the system", + filename.c_str()); + return false; + } + } + + return true; +} + } // extensionfile_util diff --git a/chrome/browser/extensions/extension_file_util.h b/chrome/browser/extensions/extension_file_util.h index 45d0b30..c2eb5c9 100644 --- a/chrome/browser/extensions/extension_file_util.h +++ b/chrome/browser/extensions/extension_file_util.h @@ -78,6 +78,13 @@ void UninstallExtension(const std::string& id, const FilePath& extensions_dir); // removing others? void GarbageCollectExtensions(const FilePath& extensions_dir); +// We need to reserve the namespace of entries that start with "_" for future +// use by Chrome. +// If any files or directories are found using "_" prefix and are not on +// reserved list we return false, and set error message. +bool CheckForIllegalFilenames(const FilePath& extension_path, + std::string* error); + } // extension_file_util #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_FILE_UTIL_H_ diff --git a/chrome/browser/extensions/extension_file_util_unittest.cc b/chrome/browser/extensions/extension_file_util_unittest.cc index 6e9b2dc..73dfb46 100644 --- a/chrome/browser/extensions/extension_file_util_unittest.cc +++ b/chrome/browser/extensions/extension_file_util_unittest.cc @@ -8,8 +8,13 @@ #include "base/scoped_temp_dir.h" #include "base/path_service.h" #include "chrome/common/chrome_paths.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_constants.h" +#include "chrome/common/json_value_serializer.h" #include "testing/gtest/include/gtest/gtest.h" +namespace keys = extension_manifest_keys; + TEST(ExtensionFileUtil, MoveDirSafely) { // Create a test directory structure with some data in it. ScopedTempDir temp; @@ -162,6 +167,110 @@ TEST(ExtensionFileUtil, CompareToInstalledVersion) { ASSERT_EQ("", version_out); } +// Creates minimal manifest, with or without default_locale section. +bool CreateMinimalManifest(const std::string& locale, + const FilePath& manifest_path) { + DictionaryValue manifest; + + manifest.SetString(keys::kVersion, "1.0.0.0"); + manifest.SetString(keys::kName, "my extension"); + if (!locale.empty()) { + manifest.SetString(keys::kDefaultLocale, locale); + } + + JSONFileValueSerializer serializer(manifest_path); + return serializer.Serialize(manifest); +} + +TEST(ExtensionFileUtil, LoadExtensionWithValidLocales) { + ScopedTempDir temp; + ASSERT_TRUE(temp.CreateUniqueTempDir()); + ASSERT_TRUE(CreateMinimalManifest( + "en_US", temp.path().AppendASCII(Extension::kManifestFilename))); + + FilePath src_path = temp.path().AppendASCII(Extension::kLocaleFolder); + ASSERT_TRUE(file_util::CreateDirectory(src_path)); + + FilePath locale_1 = src_path.AppendASCII("sr"); + ASSERT_TRUE(file_util::CreateDirectory(locale_1)); + + std::string data = "foobar"; + ASSERT_TRUE( + file_util::WriteFile(locale_1.AppendASCII(Extension::kMessagesFilename), + data.c_str(), data.length())); + + FilePath locale_2 = src_path.AppendASCII("en_US"); + ASSERT_TRUE(file_util::CreateDirectory(locale_2)); + + ASSERT_TRUE( + file_util::WriteFile(locale_2.AppendASCII(Extension::kMessagesFilename), + data.c_str(), data.length())); + + std::string error; + scoped_ptr<Extension> extension( + extension_file_util::LoadExtension(temp.path(), false, &error)); + ASSERT_FALSE(extension == NULL); + EXPECT_EQ(static_cast<unsigned int>(2), + extension->supported_locales().size()); + EXPECT_EQ("en-US", extension->default_locale()); +} + +TEST(ExtensionFileUtil, LoadExtensionWithoutLocalesFolder) { + ScopedTempDir temp; + ASSERT_TRUE(temp.CreateUniqueTempDir()); + ASSERT_TRUE(CreateMinimalManifest( + "", temp.path().AppendASCII(Extension::kManifestFilename))); + + std::string error; + scoped_ptr<Extension> extension( + extension_file_util::LoadExtension(temp.path(), false, &error)); + ASSERT_FALSE(extension == NULL); + EXPECT_TRUE(extension->supported_locales().empty()); + EXPECT_TRUE(extension->default_locale().empty()); +} + +TEST(ExtensionFileUtil, CheckIllegalFilenamesNoUnderscores) { + ScopedTempDir temp; + ASSERT_TRUE(temp.CreateUniqueTempDir()); + + FilePath src_path = temp.path().AppendASCII("some_dir"); + ASSERT_TRUE(file_util::CreateDirectory(src_path)); + + std::string data = "foobar"; + ASSERT_TRUE(file_util::WriteFile(src_path.AppendASCII("some_file.txt"), + data.c_str(), data.length())); + std::string error; + EXPECT_TRUE(extension_file_util::CheckForIllegalFilenames(temp.path(), + &error)); +} + +TEST(ExtensionFileUtil, CheckIllegalFilenamesOnlyReserved) { + ScopedTempDir temp; + ASSERT_TRUE(temp.CreateUniqueTempDir()); + + FilePath src_path = temp.path().AppendASCII(Extension::kLocaleFolder); + ASSERT_TRUE(file_util::CreateDirectory(src_path)); + + std::string error; + EXPECT_TRUE(extension_file_util::CheckForIllegalFilenames(temp.path(), + &error)); +} + +TEST(ExtensionFileUtil, CheckIllegalFilenamesReservedAndIllegal) { + ScopedTempDir temp; + ASSERT_TRUE(temp.CreateUniqueTempDir()); + + FilePath src_path = temp.path().AppendASCII(Extension::kLocaleFolder); + ASSERT_TRUE(file_util::CreateDirectory(src_path)); + + src_path = temp.path().AppendASCII("_some_dir"); + ASSERT_TRUE(file_util::CreateDirectory(src_path)); + + std::string error; + EXPECT_FALSE(extension_file_util::CheckForIllegalFilenames(temp.path(), + &error)); +} + // TODO(aa): More tests as motivation allows. Maybe steal some from // ExtensionsService? Many of them could probably be tested here without the // MessageLoop shenanigans. diff --git a/chrome/browser/extensions/extension_l10n_util.cc b/chrome/browser/extensions/extension_l10n_util.cc new file mode 100644 index 0000000..77fddba --- /dev/null +++ b/chrome/browser/extensions/extension_l10n_util.cc @@ -0,0 +1,90 @@ +// 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_l10n_util.h" + +#include <set> +#include <string> +#include <vector> + +#include "app/l10n_util.h" +#include "base/file_util.h" +#include "base/string_util.h" +#include "base/values.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_constants.h" + +namespace keys = extension_manifest_keys; + +namespace extension_l10n_util { + +bool ValidateDefaultLocale(const Extension* extension) { + std::string default_locale = extension->default_locale(); + + if (extension->supported_locales().find(default_locale) != + extension->supported_locales().end()) { + return true; + } else { + return false; + } +} + + +bool AddLocale(const std::set<std::string>& chrome_locales, + const FilePath& locale_folder, + Extension* extension, + 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(), '_', '-'); + 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()); + return false; + } + // Check if messages file is actually present (but don't check content). + if (file_util::PathExists( + locale_folder.AppendASCII(Extension::kMessagesFilename))) { + extension->AddSupportedLocale(*locale_name); + } else { + *error = StringPrintf("Catalog file is missing for locale %s.", + locale_name->c_str()); + return false; + } + + return true; +} + +bool AddValidLocales(const FilePath& locale_path, + Extension* extension, + 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()); + // Enumerate all supplied locales in the extension. + file_util::FileEnumerator locales(locale_path, + false, + file_util::FileEnumerator::DIRECTORIES); + FilePath locale_folder; + while (!(locale_folder = locales.Next()).empty()) { + std::string locale_name = + WideToASCII(locale_folder.BaseName().ToWStringHack()); + if (!AddLocale(chrome_locales, locale_folder, + extension, &locale_name, error)) { + return false; + } + } + + if (extension->supported_locales().empty()) { + *error = extension_manifest_errors::kLocalesNoValidLocaleNamesListed; + return false; + } + + return true; +} + +} // namespace extension_l10n_util diff --git a/chrome/browser/extensions/extension_l10n_util.h b/chrome/browser/extensions/extension_l10n_util.h new file mode 100644 index 0000000..d964566 --- /dev/null +++ b/chrome/browser/extensions/extension_l10n_util.h @@ -0,0 +1,46 @@ +// 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. +// +// This file declares extension specific l10n utils. + +#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_L10N_UTIL_H_ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_L10N_UTIL_H_ + +#include <set> +#include <string> + +class DictionaryValue; +class Extension; +class FilePath; + +namespace extension_l10n_util { + +// Returns true if default_locale was set to valid locale +// (supported by the extension). +bool ValidateDefaultLocale(const Extension* extension); + +// Adds locale_name to the extension if it's in chrome_locales, and +// if messages file is present (we don't check content of messages file here). +// Returns false if locale_name was not found in chrome_locales, and sets +// error with locale_name. +bool AddLocale(const std::set<std::string>& chrome_locales, + const FilePath& locale_folder, + Extension* extension, + std::string* locale_name, + std::string* error); + +// Adds valid locales to the extension. +// 1. Do nothing if _locales directory is missing (not an error). +// 2. Get list of Chrome locales. +// 3. Enumerate all subdirectories of _locales directory. +// 4. Intersect both lists, and add intersection to the extension. +// Returns false if any of supplied locales don't match chrome list of locales. +// Fills out error with offending locale name. +bool AddValidLocales(const FilePath& locale_path, + Extension* extension, + std::string* error); + +} // namespace extension_l10n_util + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_L10N_UTIL_H_ diff --git a/chrome/browser/extensions/extension_l10n_util_unittest.cc b/chrome/browser/extensions/extension_l10n_util_unittest.cc new file mode 100644 index 0000000..04f1ac0 --- /dev/null +++ b/chrome/browser/extensions/extension_l10n_util_unittest.cc @@ -0,0 +1,135 @@ +// 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_l10n_util.h" + +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/scoped_ptr.h" +#include "base/scoped_temp_dir.h" +#include "base/values.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_constants.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace keys = extension_manifest_keys; + +namespace { + + Extension* CreateMinimalExtension(const std::string& default_locale) { +#if defined(OS_WIN) + FilePath path(FILE_PATH_LITERAL("C:\\foo")); +#elif defined(OS_POSIX) + FilePath path(FILE_PATH_LITERAL("/foo")); +#endif + Extension* extension = new Extension(path); + std::string error; + DictionaryValue input_value; + + // Test minimal extension + input_value.SetString(keys::kVersion, "1.0.0.0"); + input_value.SetString(keys::kName, "my extension"); + if (!default_locale.empty()) { + input_value.SetString(keys::kDefaultLocale, default_locale); + } + EXPECT_TRUE(extension->InitFromValue(input_value, false, &error)); + + return extension; +} + +TEST(ExtensionL10nUtil, AddValidLocalesEmptyLocaleFolder) { + ScopedTempDir temp; + ASSERT_TRUE(temp.CreateUniqueTempDir()); + + FilePath src_path = temp.path().AppendASCII(Extension::kLocaleFolder); + ASSERT_TRUE(file_util::CreateDirectory(src_path)); + + scoped_ptr<Extension> extension(CreateMinimalExtension("")); + + std::string error; + EXPECT_FALSE(extension_l10n_util::AddValidLocales(src_path, + extension.get(), + &error)); + + EXPECT_TRUE(extension->supported_locales().empty()); +} + +TEST(ExtensionL10nUtil, AddValidLocalesWithValidLocaleNoMessagesFile) { + ScopedTempDir temp; + ASSERT_TRUE(temp.CreateUniqueTempDir()); + + FilePath src_path = temp.path().AppendASCII(Extension::kLocaleFolder); + ASSERT_TRUE(file_util::CreateDirectory(src_path)); + + ASSERT_TRUE(file_util::CreateDirectory(src_path.AppendASCII("sr"))); + + scoped_ptr<Extension> extension(CreateMinimalExtension("")); + + std::string error; + EXPECT_FALSE(extension_l10n_util::AddValidLocales(src_path, + extension.get(), + &error)); + + EXPECT_TRUE(extension->supported_locales().empty()); +} + +TEST(ExtensionL10nUtil, AddValidLocalesWithValidLocalesAndMessagesFile) { + ScopedTempDir temp; + ASSERT_TRUE(temp.CreateUniqueTempDir()); + + FilePath src_path = temp.path().AppendASCII(Extension::kLocaleFolder); + ASSERT_TRUE(file_util::CreateDirectory(src_path)); + + FilePath locale_1 = src_path.AppendASCII("sr"); + ASSERT_TRUE(file_util::CreateDirectory(locale_1)); + + std::string data = "foobar"; + ASSERT_TRUE( + file_util::WriteFile(locale_1.AppendASCII(Extension::kMessagesFilename), + data.c_str(), data.length())); + + FilePath locale_2 = src_path.AppendASCII("en_US"); + ASSERT_TRUE(file_util::CreateDirectory(locale_2)); + + ASSERT_TRUE( + file_util::WriteFile(locale_2.AppendASCII(Extension::kMessagesFilename), + data.c_str(), data.length())); + + scoped_ptr<Extension> extension(CreateMinimalExtension("")); + + std::string error; + EXPECT_TRUE(extension_l10n_util::AddValidLocales(src_path, + extension.get(), + &error)); + + EXPECT_EQ(static_cast<unsigned int>(2), + extension->supported_locales().size()); +} + +TEST(ExtensionL10nUtil, SetDefaultLocaleGoodDefaultLocaleInManifest) { + scoped_ptr<Extension> extension(CreateMinimalExtension("sr")); + extension->AddSupportedLocale("sr"); + extension->AddSupportedLocale("en-US"); + + EXPECT_TRUE(extension_l10n_util::ValidateDefaultLocale(extension.get())); + EXPECT_EQ("sr", extension->default_locale()); +} + +TEST(ExtensionL10nUtil, SetDefaultLocaleNoDefaultLocaleInManifest) { + scoped_ptr<Extension> extension(CreateMinimalExtension("")); + extension->AddSupportedLocale("sr"); + extension->AddSupportedLocale("en-US"); + + EXPECT_FALSE(extension_l10n_util::ValidateDefaultLocale(extension.get())); +} + +TEST(ExtensionL10nUtil, SetDefaultLocaleWrongDefaultLocaleInManifest) { + scoped_ptr<Extension> extension(CreateMinimalExtension("ko")); + extension->AddSupportedLocale("sr"); + extension->AddSupportedLocale("en-US"); + + EXPECT_FALSE(extension_l10n_util::ValidateDefaultLocale(extension.get())); +} + +} // namespace diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index ac30fbb..d6d6e9f 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1046,6 +1046,8 @@ 'browser/extensions/extension_host.h', 'browser/extensions/extension_install_ui.cc', 'browser/extensions/extension_install_ui.h', + 'browser/extensions/extension_l10n_util.cc', + 'browser/extensions/extension_l10n_util.h', 'browser/extensions/extension_message_service.cc', 'browser/extensions/extension_message_service.h', 'browser/extensions/extension_browser_event_router.cc', @@ -3864,6 +3866,7 @@ 'browser/download/save_package_unittest.cc', 'browser/encoding_menu_controller_unittest.cc', 'browser/extensions/extension_file_util_unittest.cc', + 'browser/extensions/extension_l10n_util_unittest.cc', 'browser/extensions/extension_messages_unittest.cc', 'browser/extensions/extension_process_manager_unittest.cc', 'browser/extensions/extension_ui_unittest.cc', diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc index 08b77bb..5ceee67 100644 --- a/chrome/common/extensions/extension.cc +++ b/chrome/common/extensions/extension.cc @@ -67,6 +67,8 @@ static bool IsAPIPermission(const std::string& str) { int Extension::id_counter_ = 0; const char Extension::kManifestFilename[] = "manifest.json"; +const char Extension::kLocaleFolder[] = "_locales"; +const char Extension::kMessagesFilename[] = "messages"; // A list of all the keys allowed by themes. static const wchar_t* kValidThemeKeys[] = { @@ -935,6 +937,18 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_id, } } + // Initialize default locale (if present). + if (source.HasKey(keys::kDefaultLocale)) { + std::string default_locale; + if (!source.GetString(keys::kDefaultLocale, &default_locale)) { + *error = errors::kInvalidDefaultLocale; + return false; + } + // Normalize underscores to hyphens. + std::replace(default_locale.begin(), default_locale.end(), '_', '-'); + set_default_locale(default_locale); + } + return true; } diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h index afd62c1..f3acd1c 100644 --- a/chrome/common/extensions/extension.h +++ b/chrome/common/extensions/extension.h @@ -5,6 +5,7 @@ #ifndef CHROME_COMMON_EXTENSIONS_EXTENSION_H_ #define CHROME_COMMON_EXTENSIONS_EXTENSION_H_ +#include <map> #include <set> #include <string> #include <vector> @@ -95,6 +96,12 @@ class Extension { // The name of the manifest inside an extension. static const char kManifestFilename[]; + // The name of locale folder inside an extension. + static const char kLocaleFolder[]; + + // The name of the messages file inside an extension. + static const char kMessagesFilename[]; + #if defined(OS_WIN) static const char* kExtensionRegistryPath; #endif @@ -230,6 +237,20 @@ class Extension { // an empty FilePath if the extension does not have that icon. FilePath GetIconPath(Icons icon); + // Returns a list of all locales supported by the extension. + const std::set<std::string>& supported_locales() const { + return supported_locales_; + } + // Add locale to the list of supported locales. + void AddSupportedLocale(const std::string& supported_locale) { + supported_locales_.insert(supported_locale); + } + + // Getter/setter for a default_locale_. + const std::string& default_locale() const { return default_locale_; } + void set_default_locale(const std::string& default_locale) { + default_locale_ = default_locale; + } // Runtime data: // Put dynamic data about the state of a running extension below. @@ -342,6 +363,11 @@ class Extension { // URL for fetching an update manifest GURL update_url_; + // List of all locales extension supports. + std::set<std::string> supported_locales_; + + // Default locale, used for fallback. + std::string default_locale_; // Runtime data: diff --git a/chrome/common/extensions/extension_constants.cc b/chrome/common/extensions/extension_constants.cc index f1b8783..d887678 100644 --- a/chrome/common/extensions/extension_constants.cc +++ b/chrome/common/extensions/extension_constants.cc @@ -9,6 +9,7 @@ namespace extension_manifest_keys { const wchar_t* kBackground = L"background_page"; const wchar_t* kContentScripts = L"content_scripts"; const wchar_t* kCss = L"css"; +const wchar_t* kDefaultLocale = L"default_locale"; const wchar_t* kDescription = L"description"; const wchar_t* kIcons = L"icons"; const wchar_t* kJs = L"js"; @@ -142,6 +143,12 @@ const char* kInvalidThemeTints = "Invalid value for theme images - tints must be decimal numbers."; const char* kInvalidUpdateURL = "Invalid value for update url: '[*]'."; +const char* kInvalidDefaultLocale = + "Invalid value for default locale - locale name must be a string."; const char* kThemesCannotContainExtensions = "A theme cannot contain extensions code."; +const char* kLocalesNoDefaultLocaleSpecified = + "Localization used, but default_locale wasn't specified in the manifest."; +const char* kLocalesNoValidLocaleNamesListed = + "No valid locale name could be found in _locales directory."; } // namespace extension_manifest_errors diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h index 2785b28..b808665 100644 --- a/chrome/common/extensions/extension_constants.h +++ b/chrome/common/extensions/extension_constants.h @@ -10,6 +10,7 @@ namespace extension_manifest_keys { extern const wchar_t* kBackground; extern const wchar_t* kContentScripts; extern const wchar_t* kCss; + extern const wchar_t* kDefaultLocale; extern const wchar_t* kDescription; extern const wchar_t* kIcons; extern const wchar_t* kJs; @@ -38,7 +39,7 @@ namespace extension_manifest_keys { extern const wchar_t* kType; extern const wchar_t* kVersion; extern const wchar_t* kUpdateURL; -} // namespace extension_manifest_keys +} // namespace extension_manifest_keys // Some values expected in manifests. namespace extension_manifest_values { @@ -96,6 +97,9 @@ namespace extension_manifest_errors { extern const char* kThemesCannotContainExtensions; extern const char* kMissingFile; extern const char* kInvalidUpdateURL; + extern const char* kInvalidDefaultLocale; + extern const char* kLocalesNoDefaultLocaleSpecified; + extern const char* kLocalesNoValidLocaleNamesListed; } // namespace extension_manifest_errors #endif // CHROME_COMMON_EXTENSIONS_EXTENSION_CONSTANTS_H_ diff --git a/chrome/common/extensions/extension_unittest.cc b/chrome/common/extensions/extension_unittest.cc index fc97cc1..10edbbb 100644 --- a/chrome/common/extensions/extension_unittest.cc +++ b/chrome/common/extensions/extension_unittest.cc @@ -231,6 +231,12 @@ TEST(ExtensionTest, InitFromValueInvalid) { privacy_blacklists->Set(0, Value::CreateIntegerValue(42)); EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error)); EXPECT_TRUE(MatchPattern(error, errors::kInvalidPrivacyBlacklistsPath)); + + // Test invalid default locale. + input_value.reset(static_cast<DictionaryValue*>(valid_value->DeepCopy())); + input_value->SetInteger(keys::kDefaultLocale, 42); + EXPECT_FALSE(extension.InitFromValue(*input_value, true, &error)); + EXPECT_EQ(errors::kInvalidDefaultLocale, error); } TEST(ExtensionTest, InitFromValueValid) { |