1c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/extension_l10n_util.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_enumerator.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_file_value_serializer.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/linked_ptr.h" 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/strings/utf_string_conversions.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/constants.h" 21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "extensions/common/error_utils.h" 22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/file_util.h" 23d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "extensions/common/manifest_constants.h" 24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/message_bundle.h" 25ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "third_party/icu/source/common/unicode/uloc.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace errors = extensions::manifest_errors; 293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace keys = extensions::manifest_keys; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace { 32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 33d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Loads contents of the messages file for given locale. If file is not found, 34d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// or there was parsing error we return NULL and set |error|. 35d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Caller owns the returned object. 36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)base::DictionaryValue* LoadMessageFile(const base::FilePath& locale_path, 37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::string& locale, 38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string* error) { 39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::FilePath file = 40c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch locale_path.AppendASCII(locale).Append(extensions::kMessagesFilename); 41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) JSONFileValueSerializer messages_serializer(file); 42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Value* dictionary = messages_serializer.Deserialize(NULL, error); 43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!dictionary) { 44d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (error->empty()) { 45d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // JSONFileValueSerializer just returns NULL if file cannot be found. It 46d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // doesn't set the error, so we have to do it. 47d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) *error = base::StringPrintf("Catalog file is missing for locale %s.", 48d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) locale.c_str()); 49d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) *error = extensions::ErrorUtils::FormatErrorMessage( 51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) errors::kLocalesInvalidLocale, 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UTF16ToUTF8(file.LossyDisplayName()), 53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) *error); 54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return static_cast<base::DictionaryValue*>(dictionary); 58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Localizes manifest value of string type for a given key. 610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)bool LocalizeManifestValue(const std::string& key, 620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const extensions::MessageBundle& messages, 630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) base::DictionaryValue* manifest, 640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) std::string* error) { 650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) std::string result; 660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!manifest->GetString(key, &result)) 670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return true; 680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!messages.ReplaceMessages(&result, error)) 700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return false; 710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) manifest->SetString(key, result); 730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return true; 740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Localizes manifest value of list type for a given key. 770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)bool LocalizeManifestListValue(const std::string& key, 780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const extensions::MessageBundle& messages, 790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) base::DictionaryValue* manifest, 800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) std::string* error) { 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::ListValue* list = NULL; 820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!manifest->GetList(key, &list)) 830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return true; 84d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) bool ret = true; 860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) for (size_t i = 0; i < list->GetSize(); ++i) { 870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) std::string result; 880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (list->GetString(i, &result)) { 890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (messages.ReplaceMessages(&result, error)) 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) list->Set(i, new base::StringValue(result)); 910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) else 920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ret = false; 930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return ret; 960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)std::string& GetProcessLocale() { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CR_DEFINE_STATIC_LOCAL(std::string, locale, ()); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return locale; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} // namespace 1040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extension_l10n_util { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetProcessLocale(const std::string& locale) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetProcessLocale() = locale; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)std::string GetDefaultLocaleFromManifest(const base::DictionaryValue& manifest, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* error) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string default_locale; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (manifest.GetString(keys::kDefaultLocale, &default_locale)) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return default_locale; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *error = errors::kInvalidDefaultLocale; 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool ShouldRelocalizeManifest(const base::DictionaryValue* manifest) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!manifest) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!manifest->HasKey(keys::kDefaultLocale)) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string manifest_current_locale; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manifest->GetString(keys::kCurrentLocale, &manifest_current_locale); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return manifest_current_locale != CurrentLocaleOrDefault(); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LocalizeManifest(const extensions::MessageBundle& messages, 1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::DictionaryValue* manifest, 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* error) { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize name. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string result; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!manifest->GetString(keys::kName, &result)) { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *error = errors::kInvalidName; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!LocalizeManifestValue(keys::kName, messages, manifest, error)) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Initialize short name. 1478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!LocalizeManifestValue(keys::kShortName, messages, manifest, error)) 1488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 1498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize description. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!LocalizeManifestValue(keys::kDescription, messages, manifest, error)) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize browser_action.default_title 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string key(keys::kBrowserAction); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key.append("."); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key.append(keys::kPageActionDefaultTitle); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!LocalizeManifestValue(key, messages, manifest, error)) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize page_action.default_title 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key.assign(keys::kPageAction); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key.append("."); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key.append(keys::kPageActionDefaultTitle); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!LocalizeManifestValue(key, messages, manifest, error)) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize omnibox.keyword. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!LocalizeManifestValue(keys::kOmniboxKeyword, messages, manifest, error)) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::ListValue* file_handlers = NULL; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (manifest->GetList(keys::kFileBrowserHandlers, &file_handlers)) { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key.assign(keys::kFileBrowserHandlers); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < file_handlers->GetSize(); i++) { 1767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::DictionaryValue* handler = NULL; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!file_handlers->GetDictionary(i, &handler)) { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *error = errors::kInvalidFileBrowserHandler; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 181c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!LocalizeManifestValue( 182c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch keys::kPageActionDefaultTitle, messages, handler, error)) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Initialize all input_components 1887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::ListValue* input_components = NULL; 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (manifest->GetList(keys::kInputComponents, &input_components)) { 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < input_components->GetSize(); ++i) { 1917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::DictionaryValue* module = NULL; 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!input_components->GetDictionary(i, &module)) { 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error = errors::kInvalidInputComponents; 194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!LocalizeManifestValue(keys::kName, messages, module, error)) 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!LocalizeManifestValue(keys::kDescription, messages, module, error)) 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize app.launch.local_path. 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!LocalizeManifestValue(keys::kLaunchLocalPath, messages, manifest, error)) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize app.launch.web_url. 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!LocalizeManifestValue(keys::kLaunchWebURL, messages, manifest, error)) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Initialize description of commmands. 2123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::DictionaryValue* commands_handler = NULL; 2133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (manifest->GetDictionary(keys::kCommands, &commands_handler)) { 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (base::DictionaryValue::Iterator iter(*commands_handler); 2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !iter.IsAtEnd(); 2163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) iter.Advance()) { 217c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch key.assign( 218c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::StringPrintf("commands.%s.description", iter.key().c_str())); 2193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!LocalizeManifestValue(key, messages, manifest, error)) 2203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 2213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 2233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 2241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Initialize search_provider fields. 2251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::DictionaryValue* search_provider = NULL; 226effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (manifest->GetDictionary(keys::kOverrideSearchProvider, 227effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch &search_provider)) { 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (base::DictionaryValue::Iterator iter(*search_provider); 2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !iter.IsAtEnd(); 2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) iter.Advance()) { 231effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch key.assign(base::StringPrintf( 232effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch "%s.%s", keys::kOverrideSearchProvider, iter.key().c_str())); 233c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch bool success = 234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch (key == keys::kSettingsOverrideAlternateUrls) 235c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ? LocalizeManifestListValue(key, messages, manifest, error) 236c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch : LocalizeManifestValue(key, messages, manifest, error); 2370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!success) 2381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return false; 2391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 242effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Initialize chrome_settings_overrides.homepage. 243effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!LocalizeManifestValue( 244effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch keys::kOverrideHomepage, messages, manifest, error)) 245effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return false; 246effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 247effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Initialize chrome_settings_overrides.startup_pages. 248effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!LocalizeManifestListValue( 249effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch keys::kOverrideStartupPage, messages, manifest, error)) 250effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return false; 251effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add current locale key to the manifest, so we can overwrite prefs 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with new manifest when chrome locale changes. 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) manifest->SetString(keys::kCurrentLocale, CurrentLocaleOrDefault()); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool LocalizeExtension(const base::FilePath& extension_path, 2597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::DictionaryValue* manifest, 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* error) { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(manifest); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string default_locale = GetDefaultLocaleFromManifest(*manifest, error); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<extensions::MessageBundle> message_bundle( 266c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch extensions::file_util::LoadMessageBundle( 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_path, default_locale, error)); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!message_bundle.get() && !error->empty()) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (message_bundle.get() && 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !LocalizeManifest(*message_bundle, manifest, error)) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AddLocale(const std::set<std::string>& chrome_locales, 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& locale_folder, 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& locale_name, 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<std::string>* valid_locales, 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* error) { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Accept name that starts with a . but don't add it to the list of supported 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // locales. 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (locale_name.find(".") == 0) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chrome_locales.find(locale_name) == chrome_locales.end()) { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Warn if there is an extension locale that's not in the Chrome list, 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // but don't fail. 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << base::StringPrintf("Supplied locale %s is not supported.", 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) locale_name.c_str()); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if messages file is actually present (but don't check content). 296c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (base::PathExists(locale_folder.Append(extensions::kMessagesFilename))) { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) valid_locales->insert(locale_name); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *error = base::StringPrintf("Catalog file is missing for locale %s.", 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) locale_name.c_str()); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string CurrentLocaleOrDefault() { 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string current_locale = l10n_util::NormalizeLocale(GetProcessLocale()); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (current_locale.empty()) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_locale = "en"; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return current_locale; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetAllLocales(std::set<std::string>* all_locales) { 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<std::string>& available_locales = 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetAvailableLocales(); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add all parents of the current locale to the available locales set. 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // I.e. for sr_Cyrl_RS we add sr_Cyrl_RS, sr_Cyrl and sr. 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < available_locales.size(); ++i) { 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> result; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetParentLocales(available_locales[i], &result); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) all_locales->insert(result.begin(), result.end()); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetAllFallbackLocales(const std::string& application_locale, 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& default_locale, 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string>* all_fallback_locales) { 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(all_fallback_locales); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!application_locale.empty() && application_locale != default_locale) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetParentLocales(application_locale, all_fallback_locales); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) all_fallback_locales->push_back(default_locale); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool GetValidLocales(const base::FilePath& locale_path, 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<std::string>* valid_locales, 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* error) { 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<std::string> chrome_locales; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetAllLocales(&chrome_locales); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Enumerate all supplied locales in the extension. 343c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::FileEnumerator locales( 344c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch locale_path, false, base::FileEnumerator::DIRECTORIES); 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath locale_folder; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!(locale_folder = locales.Next()).empty()) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string locale_name = locale_folder.BaseName().MaybeAsASCII(); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (locale_name.empty()) { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; // Not ASCII. 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 352c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (!AddLocale( 353c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch chrome_locales, locale_folder, locale_name, valid_locales, error)) { 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (valid_locales->empty()) { 359d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) *error = errors::kLocalesNoValidLocaleNamesListed; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extensions::MessageBundle* LoadMessageCatalogs( 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& locale_path, 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& default_locale, 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& application_locale, 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<std::string>& valid_locales, 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* error) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> all_fallback_locales; 373c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch GetAllFallbackLocales( 374c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch application_locale, default_locale, &all_fallback_locales); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) std::vector<linked_ptr<base::DictionaryValue> > catalogs; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < all_fallback_locales.size(); ++i) { 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip all parent locales that are not supplied. 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (valid_locales.find(all_fallback_locales[i]) == valid_locales.end()) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) linked_ptr<base::DictionaryValue> catalog( 382c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch LoadMessageFile(locale_path, all_fallback_locales[i], error)); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!catalog.get()) { 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If locale is valid, but messages.json is corrupted or missing, return 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // an error. 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) catalogs.push_back(catalog); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return extensions::MessageBundle::Create(catalogs, error); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool ValidateExtensionLocales(const base::FilePath& extension_path, 396d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const base::DictionaryValue* manifest, 397d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string* error) { 398d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string default_locale = GetDefaultLocaleFromManifest(*manifest, error); 399d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 400d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (default_locale.empty()) 401d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return true; 402d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 403c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch base::FilePath locale_path = extension_path.Append(extensions::kLocaleFolder); 404d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 405d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<std::string> valid_locales; 406d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!GetValidLocales(locale_path, &valid_locales, error)) 407d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 408d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 409d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (std::set<std::string>::const_iterator locale = valid_locales.begin(); 410c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch locale != valid_locales.end(); 411c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ++locale) { 412d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::string locale_error; 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> catalog( 414d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) LoadMessageFile(locale_path, *locale, &locale_error)); 415d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 416d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!locale_error.empty()) { 417d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!error->empty()) 418d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) error->append(" "); 419d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) error->append(locale_error); 420d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 421d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 422d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 423d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return error->empty(); 424d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 425d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ShouldSkipValidation(const base::FilePath& locales_path, 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& locale_path, 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::set<std::string>& all_locales) { 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since we use this string as a key in a DictionaryValue, be paranoid about 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // skipping any strings with '.'. This happens sometimes, for example with 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // '.svn' directories. 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath relative_path; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!locales_path.AppendRelativePath(locale_path, &relative_path)) { 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string subdir = relative_path.MaybeAsASCII(); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (subdir.empty()) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; // Non-ASCII. 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (std::find(subdir.begin(), subdir.end(), '.') != subdir.end()) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (all_locales.find(subdir) == all_locales.end()) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedLocaleForTest::ScopedLocaleForTest() 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : locale_(extension_l10n_util::CurrentLocaleOrDefault()) {} 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedLocaleForTest::ScopedLocaleForTest(const std::string& locale) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : locale_(extension_l10n_util::CurrentLocaleOrDefault()) { 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_l10n_util::SetProcessLocale(locale); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedLocaleForTest::~ScopedLocaleForTest() { 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_l10n_util::SetProcessLocale(locale_); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extension_l10n_util 463