• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 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 "base/file_util.h"
6 #include "base/files/file_path.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/memory/linked_ptr.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/path_service.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/values.h"
13 #include "chrome/common/chrome_paths.h"
14 #include "chrome/common/extensions/extension_l10n_util.h"
15 #include "chrome/common/extensions/message_bundle.h"
16 #include "extensions/common/constants.h"
17 #include "extensions/common/error_utils.h"
18 #include "extensions/common/manifest_constants.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "ui/base/l10n/l10n_util.h"
22 
23 using extensions::kLocaleFolder;
24 using extensions::kMessagesFilename;
25 using extensions::MessageBundle;
26 
27 namespace errors = extensions::manifest_errors;
28 namespace keys = extensions::manifest_keys;
29 
30 namespace {
31 
TEST(ExtensionL10nUtil,ValidateLocalesWithBadLocale)32 TEST(ExtensionL10nUtil, ValidateLocalesWithBadLocale) {
33   base::ScopedTempDir temp;
34   ASSERT_TRUE(temp.CreateUniqueTempDir());
35 
36   base::FilePath src_path = temp.path().Append(kLocaleFolder);
37   base::FilePath locale = src_path.AppendASCII("ms");
38   ASSERT_TRUE(base::CreateDirectory(locale));
39 
40   base::FilePath messages_file = locale.Append(kMessagesFilename);
41   std::string data = "{ \"name\":";
42   ASSERT_TRUE(file_util::WriteFile(messages_file, data.c_str(), data.length()));
43 
44   base::DictionaryValue manifest;
45   manifest.SetString(keys::kDefaultLocale, "en");
46   std::string error;
47   EXPECT_FALSE(extension_l10n_util::ValidateExtensionLocales(
48       temp.path(), &manifest, &error));
49   EXPECT_THAT(error,
50               testing::HasSubstr(
51                   UTF16ToUTF8(messages_file.LossyDisplayName())));
52 }
53 
TEST(ExtensionL10nUtil,GetValidLocalesEmptyLocaleFolder)54 TEST(ExtensionL10nUtil, GetValidLocalesEmptyLocaleFolder) {
55   base::ScopedTempDir temp;
56   ASSERT_TRUE(temp.CreateUniqueTempDir());
57 
58   base::FilePath src_path = temp.path().Append(kLocaleFolder);
59   ASSERT_TRUE(base::CreateDirectory(src_path));
60 
61   std::string error;
62   std::set<std::string> locales;
63   EXPECT_FALSE(extension_l10n_util::GetValidLocales(src_path,
64                                                     &locales,
65                                                     &error));
66 
67   EXPECT_TRUE(locales.empty());
68 }
69 
TEST(ExtensionL10nUtil,GetValidLocalesWithValidLocaleNoMessagesFile)70 TEST(ExtensionL10nUtil, GetValidLocalesWithValidLocaleNoMessagesFile) {
71   base::ScopedTempDir temp;
72   ASSERT_TRUE(temp.CreateUniqueTempDir());
73 
74   base::FilePath src_path = temp.path().Append(kLocaleFolder);
75   ASSERT_TRUE(base::CreateDirectory(src_path));
76   ASSERT_TRUE(base::CreateDirectory(src_path.AppendASCII("sr")));
77 
78   std::string error;
79   std::set<std::string> locales;
80   EXPECT_FALSE(extension_l10n_util::GetValidLocales(src_path,
81                                                     &locales,
82                                                     &error));
83 
84   EXPECT_TRUE(locales.empty());
85 }
86 
TEST(ExtensionL10nUtil,GetValidLocalesWithUnsupportedLocale)87 TEST(ExtensionL10nUtil, GetValidLocalesWithUnsupportedLocale) {
88   base::ScopedTempDir temp;
89   ASSERT_TRUE(temp.CreateUniqueTempDir());
90 
91   base::FilePath src_path = temp.path().Append(kLocaleFolder);
92   ASSERT_TRUE(base::CreateDirectory(src_path));
93   // Supported locale.
94   base::FilePath locale_1 = src_path.AppendASCII("sr");
95   ASSERT_TRUE(base::CreateDirectory(locale_1));
96   std::string data("whatever");
97   ASSERT_TRUE(file_util::WriteFile(
98       locale_1.Append(kMessagesFilename),
99       data.c_str(), data.length()));
100   // Unsupported locale.
101   ASSERT_TRUE(base::CreateDirectory(src_path.AppendASCII("xxx_yyy")));
102 
103   std::string error;
104   std::set<std::string> locales;
105   EXPECT_TRUE(extension_l10n_util::GetValidLocales(src_path,
106                                                    &locales,
107                                                    &error));
108 
109   EXPECT_FALSE(locales.empty());
110   EXPECT_TRUE(locales.find("sr") != locales.end());
111   EXPECT_FALSE(locales.find("xxx_yyy") != locales.end());
112 }
113 
TEST(ExtensionL10nUtil,GetValidLocalesWithValidLocalesAndMessagesFile)114 TEST(ExtensionL10nUtil, GetValidLocalesWithValidLocalesAndMessagesFile) {
115   base::FilePath install_dir;
116   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &install_dir));
117   install_dir = install_dir.AppendASCII("extensions")
118       .AppendASCII("good")
119       .AppendASCII("Extensions")
120       .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
121       .AppendASCII("1.0.0.0")
122       .Append(kLocaleFolder);
123 
124   std::string error;
125   std::set<std::string> locales;
126   EXPECT_TRUE(extension_l10n_util::GetValidLocales(install_dir,
127                                                    &locales,
128                                                    &error));
129   EXPECT_EQ(3U, locales.size());
130   EXPECT_TRUE(locales.find("sr") != locales.end());
131   EXPECT_TRUE(locales.find("en") != locales.end());
132   EXPECT_TRUE(locales.find("en_US") != locales.end());
133 }
134 
TEST(ExtensionL10nUtil,LoadMessageCatalogsValidFallback)135 TEST(ExtensionL10nUtil, LoadMessageCatalogsValidFallback) {
136   base::FilePath install_dir;
137   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &install_dir));
138   install_dir = install_dir.AppendASCII("extensions")
139       .AppendASCII("good")
140       .AppendASCII("Extensions")
141       .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj")
142       .AppendASCII("1.0.0.0")
143       .Append(kLocaleFolder);
144 
145   std::string error;
146   std::set<std::string> locales;
147   EXPECT_TRUE(extension_l10n_util::GetValidLocales(install_dir,
148                                                    &locales,
149                                                    &error));
150 
151   scoped_ptr<MessageBundle> bundle(extension_l10n_util::LoadMessageCatalogs(
152       install_dir, "sr", "en_US", locales, &error));
153   ASSERT_FALSE(NULL == bundle.get());
154   EXPECT_TRUE(error.empty());
155   EXPECT_EQ("Color", bundle->GetL10nMessage("color"));
156   EXPECT_EQ("Not in the US or GB.", bundle->GetL10nMessage("not_in_US_or_GB"));
157 }
158 
TEST(ExtensionL10nUtil,LoadMessageCatalogsMissingFiles)159 TEST(ExtensionL10nUtil, LoadMessageCatalogsMissingFiles) {
160   base::ScopedTempDir temp;
161   ASSERT_TRUE(temp.CreateUniqueTempDir());
162 
163   base::FilePath src_path = temp.path().Append(kLocaleFolder);
164   ASSERT_TRUE(base::CreateDirectory(src_path));
165 
166   std::set<std::string> valid_locales;
167   valid_locales.insert("sr");
168   valid_locales.insert("en");
169   std::string error;
170   EXPECT_TRUE(NULL == extension_l10n_util::LoadMessageCatalogs(src_path,
171                                                                "en",
172                                                                "sr",
173                                                                valid_locales,
174                                                                &error));
175   EXPECT_FALSE(error.empty());
176 }
177 
TEST(ExtensionL10nUtil,LoadMessageCatalogsBadJSONFormat)178 TEST(ExtensionL10nUtil, LoadMessageCatalogsBadJSONFormat) {
179   base::ScopedTempDir temp;
180   ASSERT_TRUE(temp.CreateUniqueTempDir());
181 
182   base::FilePath src_path = temp.path().Append(kLocaleFolder);
183   ASSERT_TRUE(base::CreateDirectory(src_path));
184 
185   base::FilePath locale = src_path.AppendASCII("sr");
186   ASSERT_TRUE(base::CreateDirectory(locale));
187 
188   std::string data = "{ \"name\":";
189   base::FilePath messages_file = locale.Append(kMessagesFilename);
190   ASSERT_TRUE(file_util::WriteFile(messages_file, data.c_str(), data.length()));
191 
192   std::set<std::string> valid_locales;
193   valid_locales.insert("sr");
194   valid_locales.insert("en_US");
195   std::string error;
196   EXPECT_TRUE(NULL == extension_l10n_util::LoadMessageCatalogs(src_path,
197                                                                "en_US",
198                                                                "sr",
199                                                                valid_locales,
200                                                                &error));
201   EXPECT_EQ(
202       extensions::ErrorUtils::FormatErrorMessage(
203           errors::kLocalesInvalidLocale,
204           base::UTF16ToUTF8(messages_file.LossyDisplayName()),
205           "Line: 1, column: 10, Unexpected token."),
206       error);
207 }
208 
TEST(ExtensionL10nUtil,LoadMessageCatalogsDuplicateKeys)209 TEST(ExtensionL10nUtil, LoadMessageCatalogsDuplicateKeys) {
210   base::ScopedTempDir temp;
211   ASSERT_TRUE(temp.CreateUniqueTempDir());
212 
213   base::FilePath src_path = temp.path().Append(kLocaleFolder);
214   ASSERT_TRUE(base::CreateDirectory(src_path));
215 
216   base::FilePath locale_1 = src_path.AppendASCII("en");
217   ASSERT_TRUE(base::CreateDirectory(locale_1));
218 
219   std::string data =
220     "{ \"name\": { \"message\": \"something\" }, "
221     "\"name\": { \"message\": \"something else\" } }";
222   ASSERT_TRUE(
223       file_util::WriteFile(locale_1.Append(kMessagesFilename),
224                            data.c_str(), data.length()));
225 
226   base::FilePath locale_2 = src_path.AppendASCII("sr");
227   ASSERT_TRUE(base::CreateDirectory(locale_2));
228 
229   ASSERT_TRUE(
230       file_util::WriteFile(locale_2.Append(kMessagesFilename),
231                            data.c_str(), data.length()));
232 
233   std::set<std::string> valid_locales;
234   valid_locales.insert("sr");
235   valid_locales.insert("en");
236   std::string error;
237   // JSON parser hides duplicates. We are going to get only one key/value
238   // pair at the end.
239   scoped_ptr<MessageBundle> message_bundle(
240       extension_l10n_util::LoadMessageCatalogs(src_path,
241                                                "en",
242                                                "sr",
243                                                valid_locales,
244                                                &error));
245   EXPECT_TRUE(NULL != message_bundle.get());
246   EXPECT_TRUE(error.empty());
247 }
248 
249 // Caller owns the returned object.
CreateManifestBundle()250 MessageBundle* CreateManifestBundle() {
251   linked_ptr<base::DictionaryValue> catalog(new base::DictionaryValue);
252 
253   base::DictionaryValue* name_tree = new base::DictionaryValue();
254   name_tree->SetString("message", "name");
255   catalog->Set("name", name_tree);
256 
257   base::DictionaryValue* short_name_tree = new base::DictionaryValue();
258   short_name_tree->SetString("message", "short_name");
259   catalog->Set("short_name", short_name_tree);
260 
261   base::DictionaryValue* description_tree = new base::DictionaryValue();
262   description_tree->SetString("message", "description");
263   catalog->Set("description", description_tree);
264 
265   base::DictionaryValue* action_title_tree = new base::DictionaryValue();
266   action_title_tree->SetString("message", "action title");
267   catalog->Set("title", action_title_tree);
268 
269   base::DictionaryValue* omnibox_keyword_tree = new base::DictionaryValue();
270   omnibox_keyword_tree->SetString("message", "omnibox keyword");
271   catalog->Set("omnibox_keyword", omnibox_keyword_tree);
272 
273   base::DictionaryValue* file_handler_title_tree = new base::DictionaryValue();
274   file_handler_title_tree->SetString("message", "file handler title");
275   catalog->Set("file_handler_title", file_handler_title_tree);
276 
277   base::DictionaryValue* launch_local_path_tree = new base::DictionaryValue();
278   launch_local_path_tree->SetString("message", "main.html");
279   catalog->Set("launch_local_path", launch_local_path_tree);
280 
281   base::DictionaryValue* launch_web_url_tree = new base::DictionaryValue();
282   launch_web_url_tree->SetString("message", "http://www.google.com/");
283   catalog->Set("launch_web_url", launch_web_url_tree);
284 
285   base::DictionaryValue* first_command_description_tree =
286       new base::DictionaryValue();
287   first_command_description_tree->SetString("message", "first command");
288   catalog->Set("first_command_description", first_command_description_tree);
289 
290   base::DictionaryValue* second_command_description_tree =
291       new base::DictionaryValue();
292   second_command_description_tree->SetString("message", "second command");
293   catalog->Set("second_command_description", second_command_description_tree);
294 
295   base::DictionaryValue* url_country_tree = new base::DictionaryValue();
296   url_country_tree->SetString("message", "de");
297   catalog->Set("country", url_country_tree);
298 
299   std::vector<linked_ptr<base::DictionaryValue> > catalogs;
300   catalogs.push_back(catalog);
301 
302   std::string error;
303   MessageBundle* bundle = MessageBundle::Create(catalogs, &error);
304   EXPECT_TRUE(bundle);
305   EXPECT_TRUE(error.empty());
306 
307   return bundle;
308 }
309 
TEST(ExtensionL10nUtil,LocalizeEmptyManifest)310 TEST(ExtensionL10nUtil, LocalizeEmptyManifest) {
311   base::DictionaryValue manifest;
312   std::string error;
313   scoped_ptr<MessageBundle> messages(CreateManifestBundle());
314 
315   EXPECT_FALSE(
316       extension_l10n_util::LocalizeManifest(*messages, &manifest, &error));
317   EXPECT_EQ(std::string(errors::kInvalidName), error);
318 }
319 
TEST(ExtensionL10nUtil,LocalizeManifestWithoutNameMsgAndEmptyDescription)320 TEST(ExtensionL10nUtil, LocalizeManifestWithoutNameMsgAndEmptyDescription) {
321   base::DictionaryValue manifest;
322   manifest.SetString(keys::kName, "no __MSG");
323   std::string error;
324   scoped_ptr<MessageBundle> messages(CreateManifestBundle());
325 
326   EXPECT_TRUE(
327       extension_l10n_util::LocalizeManifest(*messages, &manifest, &error));
328 
329   std::string result;
330   ASSERT_TRUE(manifest.GetString(keys::kName, &result));
331   EXPECT_EQ("no __MSG", result);
332 
333   EXPECT_FALSE(manifest.HasKey(keys::kDescription));
334 
335   EXPECT_TRUE(error.empty());
336 }
337 
TEST(ExtensionL10nUtil,LocalizeManifestWithNameMsgAndEmptyDescription)338 TEST(ExtensionL10nUtil, LocalizeManifestWithNameMsgAndEmptyDescription) {
339   base::DictionaryValue manifest;
340   manifest.SetString(keys::kName, "__MSG_name__");
341   std::string error;
342   scoped_ptr<MessageBundle> messages(CreateManifestBundle());
343 
344   EXPECT_TRUE(
345       extension_l10n_util::LocalizeManifest(*messages, &manifest, &error));
346 
347   std::string result;
348   ASSERT_TRUE(manifest.GetString(keys::kName, &result));
349   EXPECT_EQ("name", result);
350 
351   EXPECT_FALSE(manifest.HasKey(keys::kDescription));
352 
353   EXPECT_TRUE(error.empty());
354 }
355 
TEST(ExtensionL10nUtil,LocalizeManifestWithLocalLaunchURL)356 TEST(ExtensionL10nUtil, LocalizeManifestWithLocalLaunchURL) {
357   base::DictionaryValue manifest;
358   manifest.SetString(keys::kName, "name");
359   manifest.SetString(keys::kLaunchLocalPath, "__MSG_launch_local_path__");
360   std::string error;
361   scoped_ptr<MessageBundle> messages(CreateManifestBundle());
362 
363   EXPECT_TRUE(
364       extension_l10n_util::LocalizeManifest(*messages, &manifest, &error));
365 
366   std::string result;
367   ASSERT_TRUE(manifest.GetString(keys::kLaunchLocalPath, &result));
368   EXPECT_EQ("main.html", result);
369 
370   EXPECT_TRUE(error.empty());
371 }
372 
TEST(ExtensionL10nUtil,LocalizeManifestWithHostedLaunchURL)373 TEST(ExtensionL10nUtil, LocalizeManifestWithHostedLaunchURL) {
374   base::DictionaryValue manifest;
375   manifest.SetString(keys::kName, "name");
376   manifest.SetString(keys::kLaunchWebURL, "__MSG_launch_web_url__");
377   std::string error;
378   scoped_ptr<MessageBundle> messages(CreateManifestBundle());
379 
380   EXPECT_TRUE(
381       extension_l10n_util::LocalizeManifest(*messages, &manifest, &error));
382 
383   std::string result;
384   ASSERT_TRUE(manifest.GetString(keys::kLaunchWebURL, &result));
385   EXPECT_EQ("http://www.google.com/", result);
386 
387   EXPECT_TRUE(error.empty());
388 }
389 
TEST(ExtensionL10nUtil,LocalizeManifestWithBadNameMsg)390 TEST(ExtensionL10nUtil, LocalizeManifestWithBadNameMsg) {
391   base::DictionaryValue manifest;
392   manifest.SetString(keys::kName, "__MSG_name_is_bad__");
393   manifest.SetString(keys::kDescription, "__MSG_description__");
394   std::string error;
395   scoped_ptr<MessageBundle> messages(CreateManifestBundle());
396 
397   EXPECT_FALSE(
398       extension_l10n_util::LocalizeManifest(*messages, &manifest, &error));
399 
400   std::string result;
401   ASSERT_TRUE(manifest.GetString(keys::kName, &result));
402   EXPECT_EQ("__MSG_name_is_bad__", result);
403 
404   ASSERT_TRUE(manifest.GetString(keys::kDescription, &result));
405   EXPECT_EQ("__MSG_description__", result);
406 
407   EXPECT_EQ("Variable __MSG_name_is_bad__ used but not defined.", error);
408 }
409 
TEST(ExtensionL10nUtil,LocalizeManifestWithNameDescriptionDefaultTitleMsgs)410 TEST(ExtensionL10nUtil, LocalizeManifestWithNameDescriptionDefaultTitleMsgs) {
411   base::DictionaryValue manifest;
412   manifest.SetString(keys::kName, "__MSG_name__");
413   manifest.SetString(keys::kDescription, "__MSG_description__");
414   std::string action_title(keys::kBrowserAction);
415   action_title.append(".");
416   action_title.append(keys::kPageActionDefaultTitle);
417   manifest.SetString(action_title, "__MSG_title__");
418 
419   std::string error;
420   scoped_ptr<MessageBundle> messages(CreateManifestBundle());
421 
422   EXPECT_TRUE(
423       extension_l10n_util::LocalizeManifest(*messages, &manifest, &error));
424 
425   std::string result;
426   ASSERT_TRUE(manifest.GetString(keys::kName, &result));
427   EXPECT_EQ("name", result);
428 
429   ASSERT_TRUE(manifest.GetString(keys::kDescription, &result));
430   EXPECT_EQ("description", result);
431 
432   ASSERT_TRUE(manifest.GetString(action_title, &result));
433   EXPECT_EQ("action title", result);
434 
435   EXPECT_TRUE(error.empty());
436 }
437 
TEST(ExtensionL10nUtil,LocalizeManifestWithNameDescriptionOmniboxMsgs)438 TEST(ExtensionL10nUtil, LocalizeManifestWithNameDescriptionOmniboxMsgs) {
439   base::DictionaryValue manifest;
440   manifest.SetString(keys::kName, "__MSG_name__");
441   manifest.SetString(keys::kDescription, "__MSG_description__");
442   manifest.SetString(keys::kOmniboxKeyword, "__MSG_omnibox_keyword__");
443 
444   std::string error;
445   scoped_ptr<MessageBundle> messages(CreateManifestBundle());
446 
447   EXPECT_TRUE(
448       extension_l10n_util::LocalizeManifest(*messages, &manifest, &error));
449 
450   std::string result;
451   ASSERT_TRUE(manifest.GetString(keys::kName, &result));
452   EXPECT_EQ("name", result);
453 
454   ASSERT_TRUE(manifest.GetString(keys::kDescription, &result));
455   EXPECT_EQ("description", result);
456 
457   ASSERT_TRUE(manifest.GetString(keys::kOmniboxKeyword, &result));
458   EXPECT_EQ("omnibox keyword", result);
459 
460   EXPECT_TRUE(error.empty());
461 }
462 
TEST(ExtensionL10nUtil,LocalizeManifestWithNameDescriptionFileHandlerTitle)463 TEST(ExtensionL10nUtil, LocalizeManifestWithNameDescriptionFileHandlerTitle) {
464   base::DictionaryValue manifest;
465   manifest.SetString(keys::kName, "__MSG_name__");
466   manifest.SetString(keys::kDescription, "__MSG_description__");
467   base::ListValue* handlers = new base::ListValue();
468   manifest.Set(keys::kFileBrowserHandlers, handlers);
469   base::DictionaryValue* handler = new base::DictionaryValue();
470   handlers->Append(handler);
471   handler->SetString(keys::kPageActionDefaultTitle,
472                      "__MSG_file_handler_title__");
473 
474   std::string error;
475   scoped_ptr<MessageBundle> messages(CreateManifestBundle());
476 
477   EXPECT_TRUE(
478       extension_l10n_util::LocalizeManifest(*messages, &manifest, &error));
479 
480   std::string result;
481   ASSERT_TRUE(manifest.GetString(keys::kName, &result));
482   EXPECT_EQ("name", result);
483 
484   ASSERT_TRUE(manifest.GetString(keys::kDescription, &result));
485   EXPECT_EQ("description", result);
486 
487   ASSERT_TRUE(handler->GetString(keys::kPageActionDefaultTitle, &result));
488   EXPECT_EQ("file handler title", result);
489 
490   EXPECT_TRUE(error.empty());
491 }
492 
TEST(ExtensionL10nUtil,LocalizeManifestWithNameDescriptionCommandDescription)493 TEST(ExtensionL10nUtil, LocalizeManifestWithNameDescriptionCommandDescription) {
494   base::DictionaryValue manifest;
495   manifest.SetString(keys::kName, "__MSG_name__");
496   manifest.SetString(keys::kDescription, "__MSG_description__");
497   base::DictionaryValue* commands = new DictionaryValue();
498   std::string commands_title(keys::kCommands);
499   manifest.Set(commands_title, commands);
500 
501   base::DictionaryValue* first_command = new DictionaryValue();
502   commands->Set("first_command", first_command);
503   first_command->SetString(keys::kDescription,
504                            "__MSG_first_command_description__");
505 
506   base::DictionaryValue* second_command = new DictionaryValue();
507   commands->Set("second_command", second_command);
508   second_command->SetString(keys::kDescription,
509                             "__MSG_second_command_description__");
510 
511   std::string error;
512   scoped_ptr<MessageBundle> messages(CreateManifestBundle());
513 
514   EXPECT_TRUE(
515       extension_l10n_util::LocalizeManifest(*messages, &manifest, &error));
516 
517   std::string result;
518   ASSERT_TRUE(manifest.GetString(keys::kName, &result));
519   EXPECT_EQ("name", result);
520 
521   ASSERT_TRUE(manifest.GetString(keys::kDescription, &result));
522   EXPECT_EQ("description", result);
523 
524   ASSERT_TRUE(manifest.GetString("commands.first_command.description",
525                                  &result));
526   EXPECT_EQ("first command", result);
527 
528   ASSERT_TRUE(manifest.GetString("commands.second_command.description",
529                                  &result));
530   EXPECT_EQ("second command", result);
531 
532   EXPECT_TRUE(error.empty());
533 }
534 
TEST(ExtensionL10nUtil,LocalizeManifestWithShortName)535 TEST(ExtensionL10nUtil, LocalizeManifestWithShortName) {
536   base::DictionaryValue manifest;
537   manifest.SetString(keys::kName, "extension name");
538   manifest.SetString(keys::kShortName, "__MSG_short_name__");
539 
540   std::string error;
541   scoped_ptr<MessageBundle> messages(CreateManifestBundle());
542 
543   EXPECT_TRUE(
544       extension_l10n_util::LocalizeManifest(*messages, &manifest, &error));
545   EXPECT_TRUE(error.empty());
546 
547   std::string result;
548   ASSERT_TRUE(manifest.GetString(keys::kShortName, &result));
549   EXPECT_EQ("short_name", result);
550 }
551 
TEST(ExtensionL10nUtil,LocalizeManifestWithBadShortName)552 TEST(ExtensionL10nUtil, LocalizeManifestWithBadShortName) {
553   base::DictionaryValue manifest;
554   manifest.SetString(keys::kName, "extension name");
555   manifest.SetString(keys::kShortName, "__MSG_short_name_bad__");
556 
557   std::string error;
558   scoped_ptr<MessageBundle> messages(CreateManifestBundle());
559 
560   EXPECT_FALSE(
561       extension_l10n_util::LocalizeManifest(*messages, &manifest, &error));
562   EXPECT_FALSE(error.empty());
563 
564   std::string result;
565   ASSERT_TRUE(manifest.GetString(keys::kShortName, &result));
566   EXPECT_EQ("__MSG_short_name_bad__", result);
567 }
568 
TEST(ExtensionL10nUtil,LocalizeManifestWithSearchProviderMsgs)569 TEST(ExtensionL10nUtil, LocalizeManifestWithSearchProviderMsgs) {
570   base::DictionaryValue manifest;
571   manifest.SetString(keys::kName, "__MSG_name__");
572   manifest.SetString(keys::kDescription, "__MSG_description__");
573 
574   base::DictionaryValue* search_provider = new base::DictionaryValue;
575   search_provider->SetString("name", "__MSG_country__");
576   search_provider->SetString("keyword", "__MSG_omnibox_keyword__");
577   search_provider->SetString("search_url", "http://www.foo.__MSG_country__");
578   search_provider->SetString("favicon_url", "http://www.foo.__MSG_country__");
579   search_provider->SetString("suggest_url", "http://www.foo.__MSG_country__");
580   manifest.Set(keys::kSearchProvider, search_provider);
581 
582   std::string error;
583   scoped_ptr<MessageBundle> messages(CreateManifestBundle());
584 
585   EXPECT_TRUE(
586       extension_l10n_util::LocalizeManifest(*messages, &manifest, &error));
587 
588   std::string result;
589   ASSERT_TRUE(manifest.GetString(keys::kName, &result));
590   EXPECT_EQ("name", result);
591 
592   ASSERT_TRUE(manifest.GetString(keys::kDescription, &result));
593   EXPECT_EQ("description", result);
594 
595   std::string key_prefix(keys::kSearchProvider);
596   key_prefix += '.';
597   ASSERT_TRUE(manifest.GetString(key_prefix + "name", &result));
598   EXPECT_EQ("de", result);
599 
600   ASSERT_TRUE(manifest.GetString(key_prefix + "keyword", &result));
601   EXPECT_EQ("omnibox keyword", result);
602 
603   ASSERT_TRUE(manifest.GetString(key_prefix + "search_url", &result));
604   EXPECT_EQ("http://www.foo.de", result);
605 
606   ASSERT_TRUE(manifest.GetString(key_prefix + "favicon_url", &result));
607   EXPECT_EQ("http://www.foo.de", result);
608 
609   ASSERT_TRUE(manifest.GetString(key_prefix + "suggest_url", &result));
610   EXPECT_EQ("http://www.foo.de", result);
611 
612   EXPECT_TRUE(error.empty());
613 }
614 
615 // Try with NULL manifest.
TEST(ExtensionL10nUtil,ShouldRelocalizeManifestWithNullManifest)616 TEST(ExtensionL10nUtil, ShouldRelocalizeManifestWithNullManifest) {
617   EXPECT_FALSE(extension_l10n_util::ShouldRelocalizeManifest(NULL));
618 }
619 
620 // Try with default and current locales missing.
TEST(ExtensionL10nUtil,ShouldRelocalizeManifestEmptyManifest)621 TEST(ExtensionL10nUtil, ShouldRelocalizeManifestEmptyManifest) {
622   base::DictionaryValue manifest;
623   EXPECT_FALSE(extension_l10n_util::ShouldRelocalizeManifest(&manifest));
624 }
625 
626 // Try with missing current_locale.
TEST(ExtensionL10nUtil,ShouldRelocalizeManifestWithDefaultLocale)627 TEST(ExtensionL10nUtil, ShouldRelocalizeManifestWithDefaultLocale) {
628   base::DictionaryValue manifest;
629   manifest.SetString(keys::kDefaultLocale, "en_US");
630   EXPECT_TRUE(extension_l10n_util::ShouldRelocalizeManifest(&manifest));
631 }
632 
633 // Try with missing default_locale.
TEST(ExtensionL10nUtil,ShouldRelocalizeManifestWithCurrentLocale)634 TEST(ExtensionL10nUtil, ShouldRelocalizeManifestWithCurrentLocale) {
635   base::DictionaryValue manifest;
636   manifest.SetString(keys::kCurrentLocale,
637                      extension_l10n_util::CurrentLocaleOrDefault());
638   EXPECT_FALSE(extension_l10n_util::ShouldRelocalizeManifest(&manifest));
639 }
640 
641 // Try with all data present, but with same current_locale as system locale.
TEST(ExtensionL10nUtil,ShouldRelocalizeManifestSameCurrentLocale)642 TEST(ExtensionL10nUtil, ShouldRelocalizeManifestSameCurrentLocale) {
643   base::DictionaryValue manifest;
644   manifest.SetString(keys::kDefaultLocale, "en_US");
645   manifest.SetString(keys::kCurrentLocale,
646                      extension_l10n_util::CurrentLocaleOrDefault());
647   EXPECT_FALSE(extension_l10n_util::ShouldRelocalizeManifest(&manifest));
648 }
649 
650 // Try with all data present, but with different current_locale.
TEST(ExtensionL10nUtil,ShouldRelocalizeManifestDifferentCurrentLocale)651 TEST(ExtensionL10nUtil, ShouldRelocalizeManifestDifferentCurrentLocale) {
652   base::DictionaryValue manifest;
653   manifest.SetString(keys::kDefaultLocale, "en_US");
654   manifest.SetString(keys::kCurrentLocale, "sr");
655   EXPECT_TRUE(extension_l10n_util::ShouldRelocalizeManifest(&manifest));
656 }
657 
TEST(ExtensionL10nUtil,GetAllFallbackLocales)658 TEST(ExtensionL10nUtil, GetAllFallbackLocales) {
659   std::vector<std::string> fallback_locales;
660   extension_l10n_util::GetAllFallbackLocales("en_US", "all", &fallback_locales);
661   ASSERT_EQ(3U, fallback_locales.size());
662 
663   CHECK_EQ("en_US", fallback_locales[0]);
664   CHECK_EQ("en", fallback_locales[1]);
665   CHECK_EQ("all", fallback_locales[2]);
666 }
667 
668 }  // namespace
669