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/i18n/rtl.h"
6#include "base/path_service.h"
7#include "base/strings/utf_string_conversions.h"
8#include "chrome/common/chrome_paths.h"
9#include "chrome/common/extensions/manifest_tests/extension_manifest_test.h"
10#include "chrome/common/extensions/manifest_url_handler.h"
11#include "extensions/common/extension.h"
12#include "extensions/common/manifest_constants.h"
13#include "testing/gtest/include/gtest/gtest.h"
14#include "ui/base/l10n/l10n_util.h"
15
16#if defined(TOOLKIT_GTK)
17#include <gtk/gtk.h>
18#endif
19
20namespace extensions {
21
22namespace errors = manifest_errors;
23namespace keys = manifest_keys;
24
25class InitValueManifestTest : public ExtensionManifestTest {
26};
27
28TEST_F(InitValueManifestTest, InitFromValueInvalid) {
29  Testcase testcases[] = {
30    Testcase("init_invalid_version_missing.json", errors::kInvalidVersion),
31    Testcase("init_invalid_version_invalid.json", errors::kInvalidVersion),
32    Testcase("init_invalid_name_missing.json", errors::kInvalidName),
33    Testcase("init_invalid_name_invalid.json", errors::kInvalidName),
34    Testcase("init_invalid_description_invalid.json",
35             errors::kInvalidDescription),
36    Testcase("init_invalid_icons_invalid.json", errors::kInvalidIcons),
37    Testcase("init_invalid_icons_path_invalid.json", errors::kInvalidIconPath),
38    Testcase("init_invalid_script_invalid.json",
39             errors::kInvalidContentScriptsList),
40    Testcase("init_invalid_script_item_invalid.json",
41             errors::kInvalidContentScript),
42    Testcase("init_invalid_script_matches_missing.json",
43             errors::kInvalidMatches),
44    Testcase("init_invalid_script_matches_invalid.json",
45             errors::kInvalidMatches),
46    Testcase("init_invalid_script_matches_empty.json",
47             errors::kInvalidMatchCount),
48    Testcase("init_invalid_script_match_item_invalid.json",
49             errors::kInvalidMatch),
50    Testcase("init_invalid_script_match_item_invalid_2.json",
51             errors::kInvalidMatch),
52    Testcase("init_invalid_script_files_missing.json", errors::kMissingFile),
53    Testcase("init_invalid_files_js_invalid.json", errors::kInvalidJsList),
54    Testcase("init_invalid_files_empty.json", errors::kMissingFile),
55    Testcase("init_invalid_files_js_empty_css_missing.json",
56             errors::kMissingFile),
57    Testcase("init_invalid_files_js_item_invalid.json", errors::kInvalidJs),
58    Testcase("init_invalid_files_css_invalid.json", errors::kInvalidCssList),
59    Testcase("init_invalid_files_css_item_invalid.json", errors::kInvalidCss),
60    Testcase("init_invalid_permissions_invalid.json",
61             errors::kInvalidPermissions),
62    Testcase("init_invalid_permissions_item_invalid.json",
63             errors::kInvalidPermission),
64    Testcase("init_invalid_page_actions_multi.json",
65             errors::kInvalidPageActionsListSize),
66    Testcase("init_invalid_options_url_invalid.json",
67             errors::kInvalidOptionsPage),
68    Testcase("init_invalid_locale_invalid.json", errors::kInvalidDefaultLocale),
69    Testcase("init_invalid_locale_empty.json", errors::kInvalidDefaultLocale),
70    Testcase("init_invalid_min_chrome_invalid.json",
71             errors::kInvalidMinimumChromeVersion),
72    Testcase("init_invalid_chrome_version_too_low.json",
73             errors::kChromeVersionTooLow),
74    Testcase("init_invalid_short_name_empty.json",
75             errors::kInvalidShortName),
76    Testcase("init_invalid_short_name_type.json",
77             errors::kInvalidShortName),
78  };
79
80  RunTestcases(testcases, arraysize(testcases),
81               EXPECT_TYPE_ERROR);
82}
83
84TEST_F(InitValueManifestTest, InitFromValueValid) {
85  scoped_refptr<Extension> extension(LoadAndExpectSuccess(
86      "init_valid_minimal.json"));
87
88  base::FilePath path;
89  PathService::Get(chrome::DIR_TEST_DATA, &path);
90  path = path.AppendASCII("extensions");
91
92  EXPECT_TRUE(Extension::IdIsValid(extension->id()));
93  EXPECT_EQ("1.0.0.0", extension->VersionString());
94  EXPECT_EQ("my extension", extension->name());
95  EXPECT_EQ(extension->name(), extension->short_name());
96  EXPECT_EQ(extension->id(), extension->url().host());
97  EXPECT_EQ(extension->path(), path);
98  EXPECT_EQ(path, extension->path());
99
100  // Test permissions scheme.
101  // We allow unknown API permissions, so this will be valid until we better
102  // distinguish between API and host permissions.
103  LoadAndExpectSuccess("init_valid_permissions.json");
104
105  // Test with an options page.
106  extension = LoadAndExpectSuccess("init_valid_options.json");
107  EXPECT_EQ("chrome-extension",
108            ManifestURL::GetOptionsPage(extension.get()).scheme());
109  EXPECT_EQ("/options.html",
110            ManifestURL::GetOptionsPage(extension.get()).path());
111
112  // Test optional short_name field.
113  extension = LoadAndExpectSuccess("init_valid_short_name.json");
114  EXPECT_EQ("a very descriptive extension name", extension->name());
115  EXPECT_EQ("concise name", extension->short_name());
116
117  Testcase testcases[] = {
118    // Test that an empty list of page actions does not stop a browser action
119    // from being loaded.
120    Testcase("init_valid_empty_page_actions.json"),
121
122    // Test with a minimum_chrome_version.
123    Testcase("init_valid_minimum_chrome.json"),
124
125    // Test a hosted app with a minimum_chrome_version.
126    Testcase("init_valid_app_minimum_chrome.json"),
127
128    // Test a hosted app with a requirements section.
129    Testcase("init_valid_app_requirements.json"),
130
131    // Verify empty permission settings are considered valid.
132    Testcase("init_valid_permissions_empty.json"),
133
134    // We allow unknown API permissions, so this will be valid until we better
135    // distinguish between API and host permissions.
136    Testcase("init_valid_permissions_unknown.json")
137  };
138
139  RunTestcases(testcases, arraysize(testcases),
140               EXPECT_TYPE_SUCCESS);
141}
142
143TEST_F(InitValueManifestTest, InitFromValueValidNameInRTL) {
144#if defined(TOOLKIT_GTK)
145  GtkTextDirection gtk_dir = gtk_widget_get_default_direction();
146  gtk_widget_set_default_direction(GTK_TEXT_DIR_RTL);
147#else
148  std::string locale = l10n_util::GetApplicationLocale("");
149  base::i18n::SetICUDefaultLocale("he");
150#endif
151
152  // No strong RTL characters in name.
153  scoped_refptr<Extension> extension(LoadAndExpectSuccess(
154      "init_valid_name_no_rtl.json"));
155
156  base::string16 localized_name(ASCIIToUTF16("Dictionary (by Google)"));
157  base::i18n::AdjustStringForLocaleDirection(&localized_name);
158  EXPECT_EQ(localized_name, UTF8ToUTF16(extension->name()));
159
160  // Strong RTL characters in name.
161  extension = LoadAndExpectSuccess("init_valid_name_strong_rtl.json");
162
163  localized_name = WideToUTF16(L"Dictionary (\x05D1\x05D2" L" Google)");
164  base::i18n::AdjustStringForLocaleDirection(&localized_name);
165  EXPECT_EQ(localized_name, UTF8ToUTF16(extension->name()));
166
167  // Reset locale.
168#if defined(TOOLKIT_GTK)
169  gtk_widget_set_default_direction(gtk_dir);
170#else
171  base::i18n::SetICUDefaultLocale(locale);
172#endif
173}
174
175}  // namespace extensions
176