• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 "chrome/browser/sync/glue/extension_util.h"
6 
7 #include "base/file_path.h"
8 #include "base/values.h"
9 #include "chrome/browser/extensions/mock_extension_service.h"
10 #include "chrome/browser/sync/protocol/extension_specifics.pb.h"
11 #include "chrome/common/extensions/extension.h"
12 #include "chrome/common/extensions/extension_constants.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 
16 namespace browser_sync {
17 
18 namespace {
19 
20 using ::testing::_;
21 using ::testing::Return;
22 using ::testing::StrictMock;
23 
24 #if defined(OS_WIN)
25 const FilePath::CharType kExtensionFilePath[] = FILE_PATH_LITERAL("c:\\foo");
26 #elif defined(OS_POSIX)
27 const FilePath::CharType kExtensionFilePath[] = FILE_PATH_LITERAL("/foo");
28 #endif
29 
30 const char kValidId[] = "abcdefghijklmnopabcdefghijklmnop";
31 const char kValidVersion[] = "0.0.0.0";
32 const char kVersion1[] = "1.0.0.1";
33 const char kVersion2[] = "1.0.1.0";
34 const char kVersion3[] = "1.1.0.0";
35 const char kValidUpdateUrl1[] =
36     "http://clients2.google.com/service/update2/crx";
37 const char kValidUpdateUrl2[] =
38     "https://clients2.google.com/service/update2/crx";
39 const char kName[] = "MyExtension";
40 const char kName2[] = "MyExtension2";
41 
42 class ExtensionUtilTest : public testing::Test {
43 };
44 
MakeExtension(bool is_theme,const GURL & update_url,const GURL & launch_url,bool converted_from_user_script,Extension::Location location,int num_plugins,const FilePath & extension_path)45 scoped_refptr<Extension> MakeExtension(
46     bool is_theme, const GURL& update_url,
47     const GURL& launch_url,
48     bool converted_from_user_script,
49     Extension::Location location, int num_plugins,
50     const FilePath& extension_path) {
51   DictionaryValue source;
52   source.SetString(extension_manifest_keys::kName,
53                    "PossiblySyncableExtension");
54   source.SetString(extension_manifest_keys::kVersion, "0.0.0.0");
55   if (is_theme) {
56     source.Set(extension_manifest_keys::kTheme, new DictionaryValue());
57   }
58   if (!update_url.is_empty()) {
59     source.SetString(extension_manifest_keys::kUpdateURL,
60                      update_url.spec());
61   }
62   if (!launch_url.is_empty()) {
63     source.SetString(extension_manifest_keys::kLaunchWebURL,
64                      launch_url.spec());
65   }
66   if (!is_theme) {
67     source.SetBoolean(extension_manifest_keys::kConvertedFromUserScript,
68                       converted_from_user_script);
69     ListValue* plugins = new ListValue();
70     for (int i = 0; i < num_plugins; ++i) {
71       DictionaryValue* plugin = new DictionaryValue();
72       plugin->SetString(extension_manifest_keys::kPluginsPath, "");
73       plugins->Set(i, plugin);
74     }
75     source.Set(extension_manifest_keys::kPlugins, plugins);
76   }
77 
78   std::string error;
79   scoped_refptr<Extension> extension = Extension::Create(
80       extension_path, location, source, Extension::STRICT_ERROR_CHECKS, &error);
81   EXPECT_TRUE(extension);
82   EXPECT_EQ("", error);
83   return extension;
84 }
85 
TEST_F(ExtensionUtilTest,IsExtensionValid)86 TEST_F(ExtensionUtilTest, IsExtensionValid) {
87   {
88     FilePath file_path(kExtensionFilePath);
89     scoped_refptr<Extension> extension(
90         MakeExtension(false, GURL(), GURL(), false,
91                       Extension::INTERNAL, 0, file_path));
92     EXPECT_TRUE(IsExtensionValid(*extension));
93   }
94   {
95     FilePath file_path(kExtensionFilePath);
96     scoped_refptr<Extension> extension(
97         MakeExtension(false, GURL(kValidUpdateUrl1), GURL(),
98                       true, Extension::INTERNAL, 0, file_path));
99     EXPECT_TRUE(IsExtensionValid(*extension));
100   }
101   {
102     FilePath file_path(kExtensionFilePath);
103     scoped_refptr<Extension> extension(
104         MakeExtension(false, GURL(), GURL(), true,
105                       Extension::INTERNAL, 0, file_path));
106     EXPECT_TRUE(IsExtensionValid(*extension));
107   }
108   {
109     FilePath file_path(kExtensionFilePath);
110     scoped_refptr<Extension> extension(
111         MakeExtension(true, GURL(), GURL(), false,
112                       Extension::INTERNAL, 0, file_path));
113     EXPECT_TRUE(IsExtensionValid(*extension));
114   }
115   {
116     FilePath file_path(kExtensionFilePath);
117     scoped_refptr<Extension> extension(
118         MakeExtension(false, GURL(),
119                       GURL("http://www.google.com"), false,
120                       Extension::INTERNAL, 0, file_path));
121     EXPECT_TRUE(IsExtensionValid(*extension));
122   }
123   {
124     FilePath file_path(kExtensionFilePath);
125     scoped_refptr<Extension> extension(
126         MakeExtension(false, GURL(), GURL(), false,
127                       Extension::EXTERNAL_PREF, 0, file_path));
128     EXPECT_FALSE(IsExtensionValid(*extension));
129   }
130   {
131     FilePath file_path(kExtensionFilePath);
132     scoped_refptr<Extension> extension(
133         MakeExtension(
134             false, GURL("http://third-party.update_url.com"), GURL(), true,
135             Extension::INTERNAL, 0, file_path));
136     EXPECT_FALSE(IsExtensionValid(*extension));
137   }
138   // These last 2 tests don't make sense on Chrome OS, where extension plugins
139   // are not allowed.
140 #if !defined(OS_CHROMEOS)
141   {
142     FilePath file_path(kExtensionFilePath);
143     scoped_refptr<Extension> extension(
144         MakeExtension(false, GURL(), GURL(), true,
145                       Extension::INTERNAL, 1, file_path));
146     EXPECT_FALSE(extension && IsExtensionValid(*extension));
147   }
148   {
149     FilePath file_path(kExtensionFilePath);
150     scoped_refptr<Extension> extension(
151         MakeExtension(false, GURL(), GURL(), true,
152                       Extension::INTERNAL, 2, file_path));
153     EXPECT_FALSE(extension && IsExtensionValid(*extension));
154   }
155 #endif
156 }
157 
TEST_F(ExtensionUtilTest,IsExtensionSpecificsUnset)158 TEST_F(ExtensionUtilTest, IsExtensionSpecificsUnset) {
159   {
160     sync_pb::ExtensionSpecifics specifics;
161     EXPECT_TRUE(IsExtensionSpecificsUnset(specifics));
162   }
163 
164   {
165     sync_pb::ExtensionSpecifics specifics;
166     specifics.set_id("a");
167     EXPECT_FALSE(IsExtensionSpecificsUnset(specifics));
168   }
169 
170   {
171     sync_pb::ExtensionSpecifics specifics;
172     specifics.set_version("a");
173     EXPECT_FALSE(IsExtensionSpecificsUnset(specifics));
174   }
175 
176   {
177     sync_pb::ExtensionSpecifics specifics;
178     specifics.set_update_url("a");
179     EXPECT_FALSE(IsExtensionSpecificsUnset(specifics));
180   }
181 
182   {
183     sync_pb::ExtensionSpecifics specifics;
184     specifics.set_enabled(true);
185     EXPECT_FALSE(IsExtensionSpecificsUnset(specifics));
186   }
187 
188   {
189     sync_pb::ExtensionSpecifics specifics;
190     specifics.set_incognito_enabled(true);
191     EXPECT_FALSE(IsExtensionSpecificsUnset(specifics));
192   }
193 
194   {
195     sync_pb::ExtensionSpecifics specifics;
196     specifics.set_name("a");
197     EXPECT_FALSE(IsExtensionSpecificsUnset(specifics));
198   }
199 }
200 
TEST_F(ExtensionUtilTest,IsExtensionSpecificsValid)201 TEST_F(ExtensionUtilTest, IsExtensionSpecificsValid) {
202   sync_pb::ExtensionSpecifics specifics;
203   EXPECT_FALSE(IsExtensionSpecificsValid(specifics));
204   specifics.set_id(kValidId);
205   EXPECT_FALSE(IsExtensionSpecificsValid(specifics));
206   specifics.set_version(kValidVersion);
207   EXPECT_TRUE(IsExtensionSpecificsValid(specifics));
208   EXPECT_FALSE(IsExtensionSpecificsUnset(specifics));
209   specifics.set_update_url(kValidUpdateUrl1);
210   EXPECT_TRUE(IsExtensionSpecificsValid(specifics));
211   EXPECT_FALSE(IsExtensionSpecificsUnset(specifics));
212 
213   {
214     sync_pb::ExtensionSpecifics specifics_copy(specifics);
215     specifics_copy.set_id("invalid");
216     EXPECT_FALSE(IsExtensionSpecificsValid(specifics_copy));
217   }
218 
219   {
220     sync_pb::ExtensionSpecifics specifics_copy(specifics);
221     specifics_copy.set_version("invalid");
222     EXPECT_FALSE(IsExtensionSpecificsValid(specifics_copy));
223   }
224 
225   {
226     sync_pb::ExtensionSpecifics specifics_copy(specifics);
227     specifics_copy.set_update_url("http:invalid.com:invalid");
228     EXPECT_FALSE(IsExtensionSpecificsValid(specifics_copy));
229   }
230 }
231 
TEST_F(ExtensionUtilTest,AreExtensionSpecificsEqual)232 TEST_F(ExtensionUtilTest, AreExtensionSpecificsEqual) {
233   sync_pb::ExtensionSpecifics a, b;
234   EXPECT_TRUE(AreExtensionSpecificsEqual(a, b));
235 
236   a.set_id("a");
237   EXPECT_FALSE(AreExtensionSpecificsEqual(a, b));
238   b.set_id("a");
239   EXPECT_TRUE(AreExtensionSpecificsEqual(a, b));
240 
241   a.set_version("1.5");
242   EXPECT_FALSE(AreExtensionSpecificsEqual(a, b));
243   b.set_version("1.5");
244   EXPECT_TRUE(AreExtensionSpecificsEqual(a, b));
245 
246   a.set_update_url("http://www.foo.com");
247   EXPECT_FALSE(AreExtensionSpecificsEqual(a, b));
248   b.set_update_url("http://www.foo.com");
249   EXPECT_TRUE(AreExtensionSpecificsEqual(a, b));
250 
251   a.set_enabled(true);
252   EXPECT_FALSE(AreExtensionSpecificsEqual(a, b));
253   b.set_enabled(true);
254   EXPECT_TRUE(AreExtensionSpecificsEqual(a, b));
255 
256   a.set_incognito_enabled(true);
257   EXPECT_FALSE(AreExtensionSpecificsEqual(a, b));
258   b.set_incognito_enabled(true);
259   EXPECT_TRUE(AreExtensionSpecificsEqual(a, b));
260 
261   a.set_name("name");
262   EXPECT_FALSE(AreExtensionSpecificsEqual(a, b));
263   b.set_name("name");
264   EXPECT_TRUE(AreExtensionSpecificsEqual(a, b));
265 }
266 
TEST_F(ExtensionUtilTest,CopyUserProperties)267 TEST_F(ExtensionUtilTest, CopyUserProperties) {
268   sync_pb::ExtensionSpecifics dest_specifics;
269   dest_specifics.set_version(kVersion2);
270   dest_specifics.set_update_url(kValidUpdateUrl1);
271   dest_specifics.set_enabled(true);
272   dest_specifics.set_incognito_enabled(false);
273   dest_specifics.set_name(kName);
274 
275   sync_pb::ExtensionSpecifics specifics;
276   specifics.set_id(kValidId);
277   specifics.set_version(kVersion3);
278   specifics.set_update_url(kValidUpdateUrl2);
279   specifics.set_enabled(false);
280   specifics.set_incognito_enabled(true);
281   specifics.set_name(kName2);
282 
283   CopyUserProperties(specifics, &dest_specifics);
284   EXPECT_EQ("", dest_specifics.id());
285   EXPECT_EQ(kVersion2, dest_specifics.version());
286   EXPECT_EQ(kValidUpdateUrl1, dest_specifics.update_url());
287   EXPECT_FALSE(dest_specifics.enabled());
288   EXPECT_TRUE(dest_specifics.incognito_enabled());
289   EXPECT_EQ(kName, dest_specifics.name());
290 }
291 
TEST_F(ExtensionUtilTest,CopyNonUserProperties)292 TEST_F(ExtensionUtilTest, CopyNonUserProperties) {
293   sync_pb::ExtensionSpecifics dest_specifics;
294   dest_specifics.set_id(kValidId);
295   dest_specifics.set_version(kVersion2);
296   dest_specifics.set_update_url(kValidUpdateUrl1);
297   dest_specifics.set_enabled(true);
298   dest_specifics.set_incognito_enabled(false);
299   dest_specifics.set_name(kName);
300 
301   sync_pb::ExtensionSpecifics specifics;
302   specifics.set_id("");
303   specifics.set_version(kVersion3);
304   specifics.set_update_url(kValidUpdateUrl2);
305   specifics.set_enabled(false);
306   specifics.set_incognito_enabled(true);
307   specifics.set_name(kName2);
308 
309   CopyNonUserProperties(specifics, &dest_specifics);
310   EXPECT_EQ("", dest_specifics.id());
311   EXPECT_EQ(kVersion3, dest_specifics.version());
312   EXPECT_EQ(kValidUpdateUrl2, dest_specifics.update_url());
313   EXPECT_TRUE(dest_specifics.enabled());
314   EXPECT_FALSE(dest_specifics.incognito_enabled());
315   EXPECT_EQ(kName2, dest_specifics.name());
316 }
317 
TEST_F(ExtensionUtilTest,AreExtensionSpecificsUserPropertiesEqual)318 TEST_F(ExtensionUtilTest, AreExtensionSpecificsUserPropertiesEqual) {
319   sync_pb::ExtensionSpecifics a, b;
320   EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual(a, b));
321 
322   a.set_id("a");
323   b.set_id("b");
324   EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual(a, b));
325 
326   a.set_version("1.5");
327   b.set_version("1.6");
328   EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual(a, b));
329 
330   a.set_name("name");
331   b.set_name("name2");
332   EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual(a, b));
333 
334   a.set_update_url("http://www.foo.com");
335   b.set_update_url("http://www.foo2.com");
336   EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual(a, b));
337 
338   a.set_enabled(true);
339   EXPECT_FALSE(AreExtensionSpecificsUserPropertiesEqual(a, b));
340   b.set_enabled(true);
341   EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual(a, b));
342 
343   a.set_incognito_enabled(true);
344   EXPECT_FALSE(AreExtensionSpecificsUserPropertiesEqual(a, b));
345   b.set_incognito_enabled(true);
346   EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual(a, b));
347 }
348 
TEST_F(ExtensionUtilTest,AreExtensionSpecificsNonUserPropertiesEqual)349 TEST_F(ExtensionUtilTest, AreExtensionSpecificsNonUserPropertiesEqual) {
350   sync_pb::ExtensionSpecifics a, b;
351   EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual(a, b));
352 
353   a.set_enabled(true);
354   b.set_enabled(false);
355   EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual(a, b));
356 
357   a.set_incognito_enabled(true);
358   b.set_incognito_enabled(false);
359   EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual(a, b));
360 
361   a.set_id("a");
362   EXPECT_FALSE(AreExtensionSpecificsNonUserPropertiesEqual(a, b));
363   b.set_id("a");
364   EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual(a, b));
365 
366   a.set_version("1.5");
367   EXPECT_FALSE(AreExtensionSpecificsNonUserPropertiesEqual(a, b));
368   b.set_version("1.5");
369   EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual(a, b));
370 
371   a.set_update_url("http://www.foo.com");
372   EXPECT_FALSE(AreExtensionSpecificsNonUserPropertiesEqual(a, b));
373   b.set_update_url("http://www.foo.com");
374   EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual(a, b));
375 
376   a.set_name("name");
377   EXPECT_FALSE(AreExtensionSpecificsNonUserPropertiesEqual(a, b));
378   b.set_name("name");
379   EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual(a, b));
380 }
381 
MakeSyncableExtension(const std::string & version_string,const std::string & update_url_spec,const std::string & name,const FilePath & extension_path)382 scoped_refptr<Extension> MakeSyncableExtension(
383     const std::string& version_string,
384     const std::string& update_url_spec,
385     const std::string& name,
386     const FilePath& extension_path) {
387   DictionaryValue source;
388   source.SetString(extension_manifest_keys::kVersion, version_string);
389   source.SetString(extension_manifest_keys::kUpdateURL, update_url_spec);
390   source.SetString(extension_manifest_keys::kName, name);
391   std::string error;
392   scoped_refptr<Extension> extension = Extension::Create(
393       extension_path, Extension::INTERNAL, source,
394       Extension::STRICT_ERROR_CHECKS, &error);
395   EXPECT_TRUE(extension);
396   EXPECT_EQ("", error);
397   return extension;
398 }
399 
TEST_F(ExtensionUtilTest,GetExtensionSpecifics)400 TEST_F(ExtensionUtilTest, GetExtensionSpecifics) {
401   FilePath file_path(kExtensionFilePath);
402   StrictMock<MockExtensionService> mock_extension_service;
403   EXPECT_CALL(mock_extension_service, IsExtensionEnabled(_))
404       .WillOnce(Return(true));
405   EXPECT_CALL(mock_extension_service, IsIncognitoEnabled(_))
406       .WillOnce(Return(false));
407 
408   scoped_refptr<Extension> extension(
409       MakeSyncableExtension(
410           kValidVersion, kValidUpdateUrl1, kName, file_path));
411   sync_pb::ExtensionSpecifics specifics;
412   GetExtensionSpecifics(*extension, mock_extension_service, &specifics);
413   EXPECT_EQ(extension->id(), specifics.id());
414   EXPECT_EQ(extension->VersionString(), kValidVersion);
415   EXPECT_EQ(extension->update_url().spec(), kValidUpdateUrl1);
416   EXPECT_TRUE(specifics.enabled());
417   EXPECT_FALSE(specifics.incognito_enabled());
418   EXPECT_EQ(kName, specifics.name());
419 }
420 
421 // TODO(akalin): Make ExtensionService/ExtensionUpdater testable
422 // enough to be able to write a unittest for SetExtensionProperties().
423 
TEST_F(ExtensionUtilTest,MergeExtensionSpecificsWithUserProperties)424 TEST_F(ExtensionUtilTest, MergeExtensionSpecificsWithUserProperties) {
425   sync_pb::ExtensionSpecifics merged_specifics;
426   merged_specifics.set_id(kValidId);
427   merged_specifics.set_update_url(kValidUpdateUrl1);
428   merged_specifics.set_enabled(true);
429   merged_specifics.set_incognito_enabled(false);
430   merged_specifics.set_version(kVersion2);
431 
432   sync_pb::ExtensionSpecifics specifics;
433   specifics.set_id(kValidId);
434   specifics.set_update_url(kValidUpdateUrl2);
435   merged_specifics.set_enabled(false);
436   merged_specifics.set_incognito_enabled(true);
437 
438   specifics.set_version(kVersion1);
439   {
440     sync_pb::ExtensionSpecifics result = merged_specifics;
441     MergeExtensionSpecifics(specifics, false, &result);
442     EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual(
443         result, merged_specifics));
444     EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual(
445         result, merged_specifics));
446   }
447   {
448     sync_pb::ExtensionSpecifics result = merged_specifics;
449     MergeExtensionSpecifics(specifics, true, &result);
450     EXPECT_TRUE(AreExtensionSpecificsEqual(result, merged_specifics));
451   }
452 
453   specifics.set_version(kVersion2);
454   {
455     sync_pb::ExtensionSpecifics result = merged_specifics;
456     MergeExtensionSpecifics(specifics, false, &result);
457     EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual(
458         result, merged_specifics));
459     EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual(
460         result, specifics));
461   }
462   {
463     sync_pb::ExtensionSpecifics result = merged_specifics;
464     MergeExtensionSpecifics(specifics, true, &result);
465     EXPECT_TRUE(AreExtensionSpecificsEqual(result, specifics));
466   }
467 
468   specifics.set_version(kVersion3);
469   {
470     sync_pb::ExtensionSpecifics result = merged_specifics;
471     MergeExtensionSpecifics(specifics, false, &result);
472     EXPECT_TRUE(AreExtensionSpecificsUserPropertiesEqual(
473         result, merged_specifics));
474     EXPECT_TRUE(AreExtensionSpecificsNonUserPropertiesEqual(
475         result, specifics));
476   }
477   {
478     sync_pb::ExtensionSpecifics result = merged_specifics;
479     MergeExtensionSpecifics(specifics, true, &result);
480     EXPECT_TRUE(AreExtensionSpecificsEqual(result, specifics));
481   }
482 }
483 
484 }  // namespace
485 
486 }  // namespace browser_sync
487