1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/common/extensions/api/i18n/default_locale_handler.h" 6 7 #include "base/files/file_enumerator.h" 8 #include "base/files/file_util.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/strings/string_util.h" 11 #include "base/strings/stringprintf.h" 12 #include "base/strings/utf_string_conversions.h" 13 #include "base/values.h" 14 #include "extensions/common/constants.h" 15 #include "extensions/common/extension_l10n_util.h" 16 #include "extensions/common/manifest.h" 17 #include "extensions/common/manifest_constants.h" 18 #include "grit/extensions_strings.h" 19 #include "ui/base/l10n/l10n_util.h" 20 21 namespace extensions { 22 23 namespace keys = manifest_keys; 24 namespace errors = manifest_errors; 25 26 // static 27 const std::string& LocaleInfo::GetDefaultLocale(const Extension* extension) { 28 LocaleInfo* info = static_cast<LocaleInfo*>( 29 extension->GetManifestData(keys::kDefaultLocale)); 30 return info ? info->default_locale : base::EmptyString(); 31 } 32 33 DefaultLocaleHandler::DefaultLocaleHandler() { 34 } 35 36 DefaultLocaleHandler::~DefaultLocaleHandler() { 37 } 38 39 bool DefaultLocaleHandler::Parse(Extension* extension, base::string16* error) { 40 scoped_ptr<LocaleInfo> info(new LocaleInfo); 41 if (!extension->manifest()->GetString(keys::kDefaultLocale, 42 &info->default_locale) || 43 !l10n_util::IsValidLocaleSyntax(info->default_locale)) { 44 *error = base::ASCIIToUTF16(manifest_errors::kInvalidDefaultLocale); 45 return false; 46 } 47 extension->SetManifestData(keys::kDefaultLocale, info.release()); 48 return true; 49 } 50 51 bool DefaultLocaleHandler::Validate( 52 const Extension* extension, 53 std::string* error, 54 std::vector<InstallWarning>* warnings) const { 55 // default_locale and _locales have to be both present or both missing. 56 const base::FilePath path = extension->path().Append(kLocaleFolder); 57 bool path_exists = base::PathExists(path); 58 std::string default_locale = 59 extensions::LocaleInfo::GetDefaultLocale(extension); 60 61 // If both default locale and _locales folder are empty, skip verification. 62 if (default_locale.empty() && !path_exists) 63 return true; 64 65 if (default_locale.empty() && path_exists) { 66 *error = l10n_util::GetStringUTF8( 67 IDS_EXTENSION_LOCALES_NO_DEFAULT_LOCALE_SPECIFIED); 68 return false; 69 } else if (!default_locale.empty() && !path_exists) { 70 *error = errors::kLocalesTreeMissing; 71 return false; 72 } 73 74 // Treat all folders under _locales as valid locales. 75 base::FileEnumerator locales(path, false, base::FileEnumerator::DIRECTORIES); 76 77 std::set<std::string> all_locales; 78 extension_l10n_util::GetAllLocales(&all_locales); 79 const base::FilePath default_locale_path = path.AppendASCII(default_locale); 80 bool has_default_locale_message_file = false; 81 82 base::FilePath locale_path; 83 while (!(locale_path = locales.Next()).empty()) { 84 if (extension_l10n_util::ShouldSkipValidation(path, locale_path, 85 all_locales)) 86 continue; 87 88 base::FilePath messages_path = locale_path.Append(kMessagesFilename); 89 90 if (!base::PathExists(messages_path)) { 91 *error = base::StringPrintf( 92 "%s %s", errors::kLocalesMessagesFileMissing, 93 base::UTF16ToUTF8(messages_path.LossyDisplayName()).c_str()); 94 return false; 95 } 96 97 if (locale_path == default_locale_path) 98 has_default_locale_message_file = true; 99 } 100 101 // Only message file for default locale has to exist. 102 if (!has_default_locale_message_file) { 103 *error = errors::kLocalesNoDefaultMessages; 104 return false; 105 } 106 107 return true; 108 } 109 110 bool DefaultLocaleHandler::AlwaysValidateForType(Manifest::Type type) const { 111 // Required to validate _locales directory; see Validate. 112 return true; 113 } 114 115 const std::vector<std::string> DefaultLocaleHandler::Keys() const { 116 return SingleKey(keys::kDefaultLocale); 117 } 118 119 } // namespace extensions 120