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