• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/files/file_path.h"
6 #include "chrome/common/extensions/api/plugins/plugins_handler.h"
7 #include "chrome/common/extensions/sync_helper.h"
8 #include "extensions/common/error_utils.h"
9 #include "extensions/common/extension.h"
10 #include "extensions/common/manifest.h"
11 #include "extensions/common/manifest_constants.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "url/gurl.h"
14 
15 namespace extensions {
16 
17 namespace keys = manifest_keys;
18 namespace errors = manifest_errors;
19 
20 class ExtensionSyncTypeTest : public testing::Test {
21  protected:
22   enum SyncTestExtensionType {
23     EXTENSION,
24     APP,
25     USER_SCRIPT,
26     THEME
27   };
28 
MakeSyncTestExtensionWithPluginPermission(SyncTestExtensionType type,const GURL & update_url,const GURL & launch_url,Manifest::Location location,const base::FilePath & extension_path,int creation_flags,int num_plugins,bool has_plugin_permission,const std::string & expected_error)29   static scoped_refptr<Extension> MakeSyncTestExtensionWithPluginPermission(
30       SyncTestExtensionType type,
31       const GURL& update_url,
32       const GURL& launch_url,
33       Manifest::Location location,
34       const base::FilePath& extension_path,
35       int creation_flags,
36       int num_plugins,
37       bool has_plugin_permission,
38       const std::string& expected_error) {
39     base::DictionaryValue source;
40     source.SetString(keys::kName, "PossiblySyncableExtension");
41     source.SetString(keys::kVersion, "0.0.0.0");
42     if (type == APP)
43       source.SetString(keys::kApp, "true");
44     if (type == THEME)
45       source.Set(keys::kTheme, new base::DictionaryValue());
46     if (!update_url.is_empty()) {
47       source.SetString(keys::kUpdateURL, update_url.spec());
48     }
49     if (!launch_url.is_empty()) {
50       source.SetString(keys::kLaunchWebURL, launch_url.spec());
51     }
52     if (type != THEME) {
53       source.SetBoolean(keys::kConvertedFromUserScript, type == USER_SCRIPT);
54       if (num_plugins >= 0) {
55         base::ListValue* plugins = new base::ListValue();
56         for (int i = 0; i < num_plugins; ++i) {
57           base::DictionaryValue* plugin = new base::DictionaryValue();
58           plugin->SetString(keys::kPluginsPath, std::string());
59           plugins->Set(i, plugin);
60         }
61         source.Set(keys::kPlugins, plugins);
62       }
63     }
64     if (has_plugin_permission) {
65       base::ListValue* plugins = new base::ListValue();
66       plugins->Set(0, new base::StringValue("plugin"));
67       source.Set(keys::kPermissions, plugins);
68     }
69 
70     std::string error;
71     scoped_refptr<Extension> extension = Extension::Create(
72         extension_path, location, source, creation_flags, &error);
73     if (expected_error == "")
74       EXPECT_TRUE(extension.get());
75     else
76       EXPECT_FALSE(extension.get());
77     EXPECT_EQ(expected_error, error);
78     return extension;
79   }
80 
MakeSyncTestExtension(SyncTestExtensionType type,const GURL & update_url,const GURL & launch_url,Manifest::Location location,const base::FilePath & extension_path,int creation_flags)81   static scoped_refptr<Extension> MakeSyncTestExtension(
82       SyncTestExtensionType type,
83       const GURL& update_url,
84       const GURL& launch_url,
85       Manifest::Location location,
86       const base::FilePath& extension_path,
87       int creation_flags) {
88     return MakeSyncTestExtensionWithPluginPermission(
89         type, update_url, launch_url, location, extension_path,
90         creation_flags, -1, false, "");
91   }
92 
93   static const char kValidUpdateUrl1[];
94   static const char kValidUpdateUrl2[];
95 };
96 
97 const char ExtensionSyncTypeTest::kValidUpdateUrl1[] =
98     "http://clients2.google.com/service/update2/crx";
99 const char ExtensionSyncTypeTest::kValidUpdateUrl2[] =
100     "https://clients2.google.com/service/update2/crx";
101 
TEST_F(ExtensionSyncTypeTest,NormalExtensionNoUpdateUrl)102 TEST_F(ExtensionSyncTypeTest, NormalExtensionNoUpdateUrl) {
103   scoped_refptr<Extension> extension(
104       MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
105                             Manifest::INTERNAL, base::FilePath(),
106                             Extension::NO_FLAGS));
107   EXPECT_TRUE(sync_helper::IsSyncableExtension(extension.get()));
108 }
109 
TEST_F(ExtensionSyncTypeTest,UserScriptValidUpdateUrl)110 TEST_F(ExtensionSyncTypeTest, UserScriptValidUpdateUrl) {
111   scoped_refptr<Extension> extension(
112       MakeSyncTestExtension(USER_SCRIPT, GURL(kValidUpdateUrl1), GURL(),
113                             Manifest::INTERNAL, base::FilePath(),
114                             Extension::NO_FLAGS));
115   EXPECT_TRUE(sync_helper::IsSyncableExtension(extension.get()));
116 }
117 
TEST_F(ExtensionSyncTypeTest,UserScriptNoUpdateUrl)118 TEST_F(ExtensionSyncTypeTest, UserScriptNoUpdateUrl) {
119   scoped_refptr<Extension> extension(
120       MakeSyncTestExtension(USER_SCRIPT, GURL(), GURL(),
121                             Manifest::INTERNAL, base::FilePath(),
122                             Extension::NO_FLAGS));
123   EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
124 }
125 
TEST_F(ExtensionSyncTypeTest,ThemeNoUpdateUrl)126 TEST_F(ExtensionSyncTypeTest, ThemeNoUpdateUrl) {
127   scoped_refptr<Extension> extension(
128       MakeSyncTestExtension(THEME, GURL(), GURL(),
129                             Manifest::INTERNAL, base::FilePath(),
130                             Extension::NO_FLAGS));
131   EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
132   EXPECT_FALSE(sync_helper::IsSyncableApp(extension.get()));
133 }
134 
TEST_F(ExtensionSyncTypeTest,AppWithLaunchUrl)135 TEST_F(ExtensionSyncTypeTest, AppWithLaunchUrl) {
136   scoped_refptr<Extension> extension(
137       MakeSyncTestExtension(EXTENSION, GURL(), GURL("http://www.google.com"),
138                             Manifest::INTERNAL, base::FilePath(),
139                             Extension::NO_FLAGS));
140   EXPECT_TRUE(sync_helper::IsSyncableApp(extension.get()));
141 }
142 
TEST_F(ExtensionSyncTypeTest,ExtensionExternal)143 TEST_F(ExtensionSyncTypeTest, ExtensionExternal) {
144   scoped_refptr<Extension> extension(
145       MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
146                             Manifest::EXTERNAL_PREF, base::FilePath(),
147                             Extension::NO_FLAGS));
148   EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
149 }
150 
TEST_F(ExtensionSyncTypeTest,UserScriptThirdPartyUpdateUrl)151 TEST_F(ExtensionSyncTypeTest, UserScriptThirdPartyUpdateUrl) {
152   scoped_refptr<Extension> extension(
153       MakeSyncTestExtension(
154           USER_SCRIPT, GURL("http://third-party.update_url.com"), GURL(),
155           Manifest::INTERNAL, base::FilePath(), Extension::NO_FLAGS));
156   EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
157 }
158 
TEST_F(ExtensionSyncTypeTest,OnlyDisplayAppsInLauncher)159 TEST_F(ExtensionSyncTypeTest, OnlyDisplayAppsInLauncher) {
160   scoped_refptr<Extension> extension(
161       MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
162                             Manifest::INTERNAL, base::FilePath(),
163                             Extension::NO_FLAGS));
164 
165   EXPECT_FALSE(extension->ShouldDisplayInAppLauncher());
166   EXPECT_FALSE(extension->ShouldDisplayInNewTabPage());
167 
168   scoped_refptr<Extension> app(
169       MakeSyncTestExtension(APP, GURL(), GURL("http://www.google.com"),
170                             Manifest::INTERNAL, base::FilePath(),
171                             Extension::NO_FLAGS));
172   EXPECT_TRUE(app->ShouldDisplayInAppLauncher());
173   EXPECT_TRUE(app->ShouldDisplayInNewTabPage());
174 }
175 
TEST_F(ExtensionSyncTypeTest,DisplayInXManifestProperties)176 TEST_F(ExtensionSyncTypeTest, DisplayInXManifestProperties) {
177   base::DictionaryValue manifest;
178   manifest.SetString(keys::kName, "TestComponentApp");
179   manifest.SetString(keys::kVersion, "0.0.0.0");
180   manifest.SetString(keys::kApp, "true");
181   manifest.SetString(keys::kPlatformAppBackgroundPage, std::string());
182 
183   std::string error;
184   scoped_refptr<Extension> app;
185 
186   // Default to true.
187   app = Extension::Create(
188       base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
189   EXPECT_EQ(error, std::string());
190   EXPECT_TRUE(app->ShouldDisplayInAppLauncher());
191   EXPECT_TRUE(app->ShouldDisplayInNewTabPage());
192 
193   // Value display_in_NTP defaults to display_in_launcher.
194   manifest.SetBoolean(keys::kDisplayInLauncher, false);
195   app = Extension::Create(
196       base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
197   EXPECT_EQ(error, std::string());
198   EXPECT_FALSE(app->ShouldDisplayInAppLauncher());
199   EXPECT_FALSE(app->ShouldDisplayInNewTabPage());
200 
201   // Value display_in_NTP = true overriding display_in_launcher = false.
202   manifest.SetBoolean(keys::kDisplayInNewTabPage, true);
203   app = Extension::Create(
204       base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
205   EXPECT_EQ(error, std::string());
206   EXPECT_FALSE(app->ShouldDisplayInAppLauncher());
207   EXPECT_TRUE(app->ShouldDisplayInNewTabPage());
208 
209   // Value display_in_NTP = false only, overrides default = true.
210   manifest.Remove(keys::kDisplayInLauncher, NULL);
211   manifest.SetBoolean(keys::kDisplayInNewTabPage, false);
212   app = Extension::Create(
213       base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
214   EXPECT_EQ(error, std::string());
215   EXPECT_TRUE(app->ShouldDisplayInAppLauncher());
216   EXPECT_FALSE(app->ShouldDisplayInNewTabPage());
217 
218   // Error checking.
219   manifest.SetString(keys::kDisplayInNewTabPage, "invalid");
220   app = Extension::Create(
221       base::FilePath(), Manifest::COMPONENT, manifest, 0, &error);
222   EXPECT_EQ(error, std::string(errors::kInvalidDisplayInNewTabPage));
223 }
224 
TEST_F(ExtensionSyncTypeTest,OnlySyncInternal)225 TEST_F(ExtensionSyncTypeTest, OnlySyncInternal) {
226   scoped_refptr<Extension> extension_internal(
227       MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
228                             Manifest::INTERNAL, base::FilePath(),
229                             Extension::NO_FLAGS));
230   EXPECT_TRUE(sync_helper::IsSyncable(extension_internal.get()));
231 
232   scoped_refptr<Extension> extension_noninternal(
233       MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
234                             Manifest::COMPONENT, base::FilePath(),
235                             Extension::NO_FLAGS));
236   EXPECT_FALSE(sync_helper::IsSyncable(extension_noninternal.get()));
237 }
238 
TEST_F(ExtensionSyncTypeTest,DontSyncDefault)239 TEST_F(ExtensionSyncTypeTest, DontSyncDefault) {
240   scoped_refptr<Extension> extension_default(
241       MakeSyncTestExtension(EXTENSION, GURL(), GURL(),
242                             Manifest::INTERNAL, base::FilePath(),
243                             Extension::WAS_INSTALLED_BY_DEFAULT));
244   EXPECT_FALSE(sync_helper::IsSyncable(extension_default.get()));
245 }
246 
247 // These plugin tests don't make sense on Chrome OS, where extension plugins
248 // are not allowed.
249 #if !defined(OS_CHROMEOS)
TEST_F(ExtensionSyncTypeTest,ExtensionWithEmptyPlugins)250 TEST_F(ExtensionSyncTypeTest, ExtensionWithEmptyPlugins) {
251   scoped_refptr<Extension> extension(
252       MakeSyncTestExtensionWithPluginPermission(
253           EXTENSION, GURL(), GURL(),
254           Manifest::INTERNAL, base::FilePath(),
255           Extension::NO_FLAGS, 0, false, ""));
256   if (extension.get())
257     EXPECT_TRUE(sync_helper::IsSyncableExtension(extension.get()));
258 }
259 
TEST_F(ExtensionSyncTypeTest,ExtensionWithPlugin)260 TEST_F(ExtensionSyncTypeTest, ExtensionWithPlugin) {
261   scoped_refptr<Extension> extension(
262       MakeSyncTestExtensionWithPluginPermission(
263           EXTENSION, GURL(), GURL(),
264           Manifest::INTERNAL, base::FilePath(),
265           Extension::NO_FLAGS, 1, false, ""));
266   if (extension.get())
267     EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
268 }
269 
TEST_F(ExtensionSyncTypeTest,ExtensionWithTwoPlugins)270 TEST_F(ExtensionSyncTypeTest, ExtensionWithTwoPlugins) {
271   scoped_refptr<Extension> extension(
272       MakeSyncTestExtensionWithPluginPermission(
273           EXTENSION, GURL(), GURL(),
274           Manifest::INTERNAL, base::FilePath(),
275           Extension::NO_FLAGS, 2, false, ""));
276   if (extension.get())
277     EXPECT_FALSE(sync_helper::IsSyncableExtension(extension.get()));
278 }
279 
TEST_F(ExtensionSyncTypeTest,ExtensionWithPluginPermission)280 TEST_F(ExtensionSyncTypeTest, ExtensionWithPluginPermission) {
281   // Specifying the "plugin" permission in the manifest is an error.
282   scoped_refptr<Extension> extension(
283       MakeSyncTestExtensionWithPluginPermission(
284           EXTENSION, GURL(), GURL(),
285           Manifest::INTERNAL, base::FilePath(),
286           Extension::NO_FLAGS, 0, true,
287           ErrorUtils::FormatErrorMessage(
288               errors::kPermissionNotAllowedInManifest, "plugin")));
289 }
290 
291 #endif // !defined(OS_CHROMEOS)
292 
293 }  // namespace extensions
294