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