Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(241)

Side by Side Diff: chrome/browser/extensions/extension_service_sync_unittest.cc

Issue 1411773002: Move Sync-specific tests from ExtensionServiceTest into new file (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@su_ext_reenable
Patch Set: move ExternalInstallPrompt override Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/browser/extensions/extension_service_test_base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 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 <string>
6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/files/file_util.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/metrics/field_trial.h"
13 #include "base/test/mock_entropy_provider.h"
14 #include "chrome/browser/extensions/component_loader.h"
15 #include "chrome/browser/extensions/extension_service.h"
16 #include "chrome/browser/extensions/extension_service_test_with_install.h"
17 #include "chrome/browser/extensions/extension_sync_data.h"
18 #include "chrome/browser/extensions/extension_sync_service.h"
19 #include "chrome/browser/extensions/extension_util.h"
20 #include "chrome/browser/extensions/updater/extension_updater.h"
21 #include "chrome/browser/sync/profile_sync_service.h"
22 #include "chrome/browser/sync/profile_sync_service_factory.h"
23 #include "chrome/common/chrome_constants.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "chrome/common/extensions/sync_helper.h"
26 #include "chrome/test/base/testing_profile.h"
27 #include "extensions/browser/app_sorting.h"
28 #include "extensions/browser/extension_prefs.h"
29 #include "extensions/browser/extension_registry.h"
30 #include "extensions/browser/extension_system.h"
31 #include "extensions/browser/management_policy.h"
32 #include "extensions/browser/test_management_policy.h"
33 #include "extensions/common/constants.h"
34 #include "extensions/common/manifest_url_handlers.h"
35 #include "extensions/common/permissions/permission_set.h"
36 #include "sync/api/fake_sync_change_processor.h"
37 #include "sync/api/sync_data.h"
38 #include "sync/api/sync_error_factory_mock.h"
39 #include "testing/gtest/include/gtest/gtest.h"
40
41 #if defined(ENABLE_SUPERVISED_USERS)
42 #include "chrome/browser/supervised_user/permission_request_creator.h"
43 #include "chrome/browser/supervised_user/supervised_user_constants.h"
44 #include "chrome/browser/supervised_user/supervised_user_service.h"
45 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
46 #endif
47
48 using extensions::AppSorting;
49 using extensions::Extension;
50 using extensions::ExtensionPrefs;
51 using extensions::ExtensionSyncData;
52 using extensions::ExtensionSystem;
53 using extensions::Manifest;
54 using extensions::PermissionSet;
55
56 const char good0[] = "behllobkkfkfnphdnhnkndlbkcpglgmj";
57 const char good2[] = "bjafgdebaacbbbecmhlhpofkepfkgcpa";
58 const char good_crx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
59 const char page_action[] = "obcimlgaoabeegjmmpldobjndiealpln";
60 const char theme2_crx[] = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf";
61
62 class ExtensionServiceSyncTest
63 : public extensions::ExtensionServiceTestWithInstall {
64 public:
65 void MockSyncStartFlare(bool* was_called,
66 syncer::ModelType* model_type_passed_in,
67 syncer::ModelType model_type) {
68 *was_called = true;
69 *model_type_passed_in = model_type;
70 }
71
72 protected:
73 // Paths to some of the fake extensions.
74 base::FilePath good0_path() {
75 return data_dir()
76 .AppendASCII("good")
77 .AppendASCII("Extensions")
78 .AppendASCII(good0)
79 .AppendASCII("1.0.0.0");
80 }
81
82 ExtensionSyncService* extension_sync_service() {
83 return ExtensionSyncService::Get(profile());
84 }
85 };
86
87 TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledComponent) {
88 InitializeEmptyExtensionService();
89
90 bool flare_was_called = false;
91 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
92 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
93 extension_sync_service()->SetSyncStartFlareForTesting(
94 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
95 factory.GetWeakPtr(),
96 &flare_was_called, // Safe due to WeakPtrFactory scope.
97 &triggered_type)); // Safe due to WeakPtrFactory scope.
98
99 // Install a component extension.
100 std::string manifest;
101 ASSERT_TRUE(base::ReadFileToString(
102 good0_path().Append(extensions::kManifestFilename), &manifest));
103 service()->component_loader()->Add(manifest, good0_path());
104 ASSERT_FALSE(service()->is_ready());
105 service()->Init();
106 ASSERT_TRUE(service()->is_ready());
107
108 // Extensions added before service is_ready() don't trigger sync startup.
109 EXPECT_FALSE(flare_was_called);
110 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
111 }
112
113 TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledNormal) {
114 InitializeGoodInstalledExtensionService();
115
116 bool flare_was_called = false;
117 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
118 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
119 extension_sync_service()->SetSyncStartFlareForTesting(
120 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
121 factory.GetWeakPtr(),
122 &flare_was_called, // Safe due to WeakPtrFactory scope.
123 &triggered_type)); // Safe due to WeakPtrFactory scope.
124
125 ASSERT_FALSE(service()->is_ready());
126 service()->Init();
127 ASSERT_EQ(3u, loaded_.size());
128 ASSERT_TRUE(service()->is_ready());
129
130 // Extensions added before service is_ready() don't trigger sync startup.
131 EXPECT_FALSE(flare_was_called);
132 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
133 }
134
135 TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupOnInstall) {
136 InitializeEmptyExtensionService();
137 service()->Init();
138 ASSERT_TRUE(service()->is_ready());
139
140 bool flare_was_called = false;
141 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
142 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
143 extension_sync_service()->SetSyncStartFlareForTesting(
144 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
145 factory.GetWeakPtr(),
146 &flare_was_called, // Safe due to WeakPtrFactory scope.
147 &triggered_type)); // Safe due to WeakPtrFactory scope.
148
149 base::FilePath path = data_dir().AppendASCII("good.crx");
150 InstallCRX(path, INSTALL_NEW);
151
152 EXPECT_TRUE(flare_was_called);
153 EXPECT_EQ(syncer::EXTENSIONS, triggered_type);
154
155 // Reset.
156 flare_was_called = false;
157 triggered_type = syncer::UNSPECIFIED;
158
159 // Once sync starts, flare should no longer be invoked.
160 extension_sync_service()->MergeDataAndStartSyncing(
161 syncer::EXTENSIONS,
162 syncer::SyncDataList(),
163 scoped_ptr<syncer::SyncChangeProcessor>(
164 new syncer::FakeSyncChangeProcessor),
165 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
166 path = data_dir().AppendASCII("page_action.crx");
167 InstallCRX(path, INSTALL_NEW);
168 EXPECT_FALSE(flare_was_called);
169 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
170 }
171
172 TEST_F(ExtensionServiceSyncTest, DisableExtensionFromSync) {
173 // Start the extensions service with one external extension already installed.
174 base::FilePath source_install_dir =
175 data_dir().AppendASCII("good").AppendASCII("Extensions");
176 base::FilePath pref_path =
177 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
178
179 InitializeInstalledExtensionService(pref_path, source_install_dir);
180
181 // The user has enabled sync.
182 ProfileSyncService* sync_service =
183 ProfileSyncServiceFactory::GetForProfile(profile());
184 sync_service->SetSyncSetupCompleted();
185
186 service()->Init();
187 ASSERT_TRUE(service()->is_ready());
188
189 ASSERT_EQ(3u, loaded_.size());
190
191 // We start enabled.
192 const Extension* extension = service()->GetExtensionById(good0, true);
193 ASSERT_TRUE(extension);
194 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
195
196 // Sync starts up.
197 extension_sync_service()->MergeDataAndStartSyncing(
198 syncer::EXTENSIONS,
199 syncer::SyncDataList(),
200 make_scoped_ptr(new syncer::FakeSyncChangeProcessor),
201 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
202
203 // Then sync data arrives telling us to disable |good0|.
204 ExtensionSyncData disable_good_crx(*extension, false,
205 Extension::DISABLE_USER_ACTION, false,
206 false, ExtensionSyncData::BOOLEAN_UNSET);
207 syncer::SyncChange sync_change(FROM_HERE,
208 syncer::SyncChange::ACTION_UPDATE,
209 disable_good_crx.GetSyncData());
210 syncer::SyncChangeList list(1, sync_change);
211 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
212
213 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
214 }
215
216 TEST_F(ExtensionServiceSyncTest, IgnoreSyncChangesWhenLocalStateIsMoreRecent) {
217 // Start the extension service with three extensions already installed.
218 base::FilePath source_install_dir =
219 data_dir().AppendASCII("good").AppendASCII("Extensions");
220 base::FilePath pref_path =
221 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
222
223 InitializeInstalledExtensionService(pref_path, source_install_dir);
224
225 // The user has enabled sync.
226 ProfileSyncService* sync_service =
227 ProfileSyncServiceFactory::GetForProfile(profile());
228 sync_service->SetSyncSetupCompleted();
229 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
230 extension_sync_service();
231
232 service()->Init();
233 ASSERT_TRUE(service()->is_ready());
234 ASSERT_EQ(3u, loaded_.size());
235
236 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
237 ASSERT_TRUE(service()->IsExtensionEnabled(good2));
238
239 // Disable and re-enable good0 before first sync data arrives.
240 service()->DisableExtension(good0, Extension::DISABLE_USER_ACTION);
241 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
242 service()->EnableExtension(good0);
243 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
244 // Disable good2 before first sync data arrives (good1 is considered
245 // non-syncable because it has plugin permission).
246 service()->DisableExtension(good2, Extension::DISABLE_USER_ACTION);
247 ASSERT_FALSE(service()->IsExtensionEnabled(good2));
248
249 const Extension* extension0 = service()->GetExtensionById(good0, true);
250 const Extension* extension2 = service()->GetExtensionById(good2, true);
251 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension0));
252 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension2));
253
254 // Now sync data comes in that says to disable good0 and enable good2.
255 ExtensionSyncData disable_good0(*extension0, false,
256 Extension::DISABLE_USER_ACTION, false, false,
257 ExtensionSyncData::BOOLEAN_UNSET);
258 ExtensionSyncData enable_good2(*extension2, true, Extension::DISABLE_NONE,
259 false, false,
260 ExtensionSyncData::BOOLEAN_UNSET);
261 syncer::SyncDataList sync_data;
262 sync_data.push_back(disable_good0.GetSyncData());
263 sync_data.push_back(enable_good2.GetSyncData());
264 extension_sync_service()->MergeDataAndStartSyncing(
265 syncer::EXTENSIONS,
266 sync_data,
267 make_scoped_ptr(new syncer::FakeSyncChangeProcessor),
268 make_scoped_ptr(new syncer::SyncErrorFactoryMock));
269
270 // Both sync changes should be ignored, since the local state was changed
271 // before sync started, and so the local state is considered more recent.
272 EXPECT_TRUE(service()->IsExtensionEnabled(good0));
273 EXPECT_FALSE(service()->IsExtensionEnabled(good2));
274 }
275
276 TEST_F(ExtensionServiceSyncTest, GetSyncData) {
277 InitializeEmptyExtensionService();
278 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
279 const Extension* extension = service()->GetInstalledExtension(good_crx);
280 ASSERT_TRUE(extension);
281
282 extension_sync_service()->MergeDataAndStartSyncing(
283 syncer::EXTENSIONS,
284 syncer::SyncDataList(),
285 scoped_ptr<syncer::SyncChangeProcessor>(
286 new syncer::FakeSyncChangeProcessor),
287 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
288
289 syncer::SyncDataList list =
290 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
291 ASSERT_EQ(list.size(), 1U);
292 scoped_ptr<ExtensionSyncData> data =
293 ExtensionSyncData::CreateFromSyncData(list[0]);
294 ASSERT_TRUE(data.get());
295 EXPECT_EQ(extension->id(), data->id());
296 EXPECT_FALSE(data->uninstalled());
297 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
298 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
299 data->incognito_enabled());
300 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
301 EXPECT_TRUE(data->version().Equals(*extension->version()));
302 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
303 data->update_url());
304 EXPECT_EQ(extension->name(), data->name());
305 }
306
307 TEST_F(ExtensionServiceSyncTest, GetSyncDataTerminated) {
308 InitializeEmptyExtensionService();
309 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
310 TerminateExtension(good_crx);
311 const Extension* extension = service()->GetInstalledExtension(good_crx);
312 ASSERT_TRUE(extension);
313
314 syncer::FakeSyncChangeProcessor processor;
315 extension_sync_service()->MergeDataAndStartSyncing(
316 syncer::EXTENSIONS,
317 syncer::SyncDataList(),
318 scoped_ptr<syncer::SyncChangeProcessor>(
319 new syncer::FakeSyncChangeProcessor),
320 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
321
322 syncer::SyncDataList list =
323 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
324 ASSERT_EQ(list.size(), 1U);
325 scoped_ptr<ExtensionSyncData> data =
326 ExtensionSyncData::CreateFromSyncData(list[0]);
327 ASSERT_TRUE(data.get());
328 EXPECT_EQ(extension->id(), data->id());
329 EXPECT_FALSE(data->uninstalled());
330 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
331 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
332 data->incognito_enabled());
333 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
334 EXPECT_TRUE(data->version().Equals(*extension->version()));
335 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
336 data->update_url());
337 EXPECT_EQ(extension->name(), data->name());
338 }
339
340 TEST_F(ExtensionServiceSyncTest, GetSyncDataFilter) {
341 InitializeEmptyExtensionService();
342 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
343 const Extension* extension = service()->GetInstalledExtension(good_crx);
344 ASSERT_TRUE(extension);
345
346 syncer::FakeSyncChangeProcessor processor;
347 extension_sync_service()->MergeDataAndStartSyncing(
348 syncer::APPS,
349 syncer::SyncDataList(),
350 scoped_ptr<syncer::SyncChangeProcessor>(
351 new syncer::FakeSyncChangeProcessor),
352 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
353
354 syncer::SyncDataList list =
355 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
356 ASSERT_EQ(list.size(), 0U);
357 }
358
359 TEST_F(ExtensionServiceSyncTest, GetSyncExtensionDataUserSettings) {
360 InitializeEmptyExtensionService();
361 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
362 const Extension* extension = service()->GetInstalledExtension(good_crx);
363 ASSERT_TRUE(extension);
364
365 syncer::FakeSyncChangeProcessor processor;
366 extension_sync_service()->MergeDataAndStartSyncing(
367 syncer::EXTENSIONS,
368 syncer::SyncDataList(),
369 scoped_ptr<syncer::SyncChangeProcessor>(
370 new syncer::FakeSyncChangeProcessor),
371 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
372
373 {
374 syncer::SyncDataList list =
375 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
376 ASSERT_EQ(list.size(), 1U);
377 scoped_ptr<ExtensionSyncData> data =
378 ExtensionSyncData::CreateFromSyncData(list[0]);
379 ASSERT_TRUE(data.get());
380 EXPECT_TRUE(data->enabled());
381 EXPECT_FALSE(data->incognito_enabled());
382 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
383 }
384
385 service()->DisableExtension(good_crx, Extension::DISABLE_USER_ACTION);
386 {
387 syncer::SyncDataList list =
388 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
389 ASSERT_EQ(list.size(), 1U);
390 scoped_ptr<ExtensionSyncData> data =
391 ExtensionSyncData::CreateFromSyncData(list[0]);
392 ASSERT_TRUE(data.get());
393 EXPECT_FALSE(data->enabled());
394 EXPECT_FALSE(data->incognito_enabled());
395 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
396 }
397
398 extensions::util::SetIsIncognitoEnabled(good_crx, profile(), true);
399 extensions::util::SetAllowedScriptingOnAllUrls(
400 good_crx, profile(), false);
401 {
402 syncer::SyncDataList list =
403 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
404 ASSERT_EQ(list.size(), 1U);
405 scoped_ptr<ExtensionSyncData> data =
406 ExtensionSyncData::CreateFromSyncData(list[0]);
407 ASSERT_TRUE(data.get());
408 EXPECT_FALSE(data->enabled());
409 EXPECT_TRUE(data->incognito_enabled());
410 EXPECT_EQ(ExtensionSyncData::BOOLEAN_FALSE, data->all_urls_enabled());
411 }
412
413 service()->EnableExtension(good_crx);
414 extensions::util::SetAllowedScriptingOnAllUrls(
415 good_crx, profile(), true);
416 {
417 syncer::SyncDataList list =
418 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
419 ASSERT_EQ(list.size(), 1U);
420 scoped_ptr<ExtensionSyncData> data =
421 ExtensionSyncData::CreateFromSyncData(list[0]);
422 ASSERT_TRUE(data.get());
423 EXPECT_TRUE(data->enabled());
424 EXPECT_TRUE(data->incognito_enabled());
425 EXPECT_EQ(ExtensionSyncData::BOOLEAN_TRUE, data->all_urls_enabled());
426 }
427 }
428
429 TEST_F(ExtensionServiceSyncTest, SyncForUninstalledExternalExtension) {
430 InitializeEmptyExtensionService();
431 InstallCRXWithLocation(
432 data_dir().AppendASCII("good.crx"), Manifest::EXTERNAL_PREF, INSTALL_NEW);
433 const Extension* extension = service()->GetInstalledExtension(good_crx);
434 ASSERT_TRUE(extension);
435
436 syncer::FakeSyncChangeProcessor processor;
437 extension_sync_service()->MergeDataAndStartSyncing(
438 syncer::EXTENSIONS,
439 syncer::SyncDataList(),
440 scoped_ptr<syncer::SyncChangeProcessor>(
441 new syncer::FakeSyncChangeProcessor),
442 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
443
444 UninstallExtension(good_crx, false);
445 EXPECT_TRUE(
446 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
447
448 sync_pb::EntitySpecifics specifics;
449 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
450 sync_pb::ExtensionSpecifics* extension_specifics =
451 app_specifics->mutable_extension();
452 extension_specifics->set_id(good_crx);
453 extension_specifics->set_version("1.0");
454 extension_specifics->set_enabled(true);
455
456 syncer::SyncData sync_data =
457 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
458 syncer::SyncChange sync_change(FROM_HERE,
459 syncer::SyncChange::ACTION_UPDATE,
460 sync_data);
461 syncer::SyncChangeList list(1);
462 list[0] = sync_change;
463
464 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
465 EXPECT_TRUE(
466 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
467 }
468
469 TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettings) {
470 InitializeEmptyExtensionService();
471 const Extension* app =
472 PackAndInstallCRX(data_dir().AppendASCII("app"), INSTALL_NEW);
473 ASSERT_TRUE(app);
474 ASSERT_TRUE(app->is_app());
475
476 syncer::FakeSyncChangeProcessor processor;
477 extension_sync_service()->MergeDataAndStartSyncing(
478 syncer::APPS,
479 syncer::SyncDataList(),
480 scoped_ptr<syncer::SyncChangeProcessor>(
481 new syncer::FakeSyncChangeProcessor),
482 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
483
484 syncer::StringOrdinal initial_ordinal =
485 syncer::StringOrdinal::CreateInitialOrdinal();
486 {
487 syncer::SyncDataList list =
488 extension_sync_service()->GetAllSyncData(syncer::APPS);
489 ASSERT_EQ(list.size(), 1U);
490
491 scoped_ptr<ExtensionSyncData> app_sync_data =
492 ExtensionSyncData::CreateFromSyncData(list[0]);
493 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->app_launch_ordinal()));
494 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
495 }
496
497 AppSorting* sorting = ExtensionPrefs::Get(profile())->app_sorting();
498 sorting->SetAppLaunchOrdinal(app->id(), initial_ordinal.CreateAfter());
499 {
500 syncer::SyncDataList list =
501 extension_sync_service()->GetAllSyncData(syncer::APPS);
502 ASSERT_EQ(list.size(), 1U);
503
504 scoped_ptr<ExtensionSyncData> app_sync_data =
505 ExtensionSyncData::CreateFromSyncData(list[0]);
506 ASSERT_TRUE(app_sync_data.get());
507 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
508 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
509 }
510
511 sorting->SetPageOrdinal(app->id(), initial_ordinal.CreateAfter());
512 {
513 syncer::SyncDataList list =
514 extension_sync_service()->GetAllSyncData(syncer::APPS);
515 ASSERT_EQ(list.size(), 1U);
516
517 scoped_ptr<ExtensionSyncData> app_sync_data =
518 ExtensionSyncData::CreateFromSyncData(list[0]);
519 ASSERT_TRUE(app_sync_data.get());
520 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
521 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->page_ordinal()));
522 }
523 }
524
525 // TODO (rdevlin.cronin): The OnExtensionMoved() method has been removed from
526 // ExtensionService, so this test probably needs a new home. Unfortunately, it
527 // relies pretty heavily on things like InitializeExtension[Sync]Service() and
528 // PackAndInstallCRX(). When we clean up a bit more, this should move out.
529 TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettingsOnExtensionMoved) {
530 InitializeEmptyExtensionService();
531 const size_t kAppCount = 3;
532 const Extension* apps[kAppCount];
533 apps[0] = PackAndInstallCRX(data_dir().AppendASCII("app1"), INSTALL_NEW);
534 apps[1] = PackAndInstallCRX(data_dir().AppendASCII("app2"), INSTALL_NEW);
535 apps[2] = PackAndInstallCRX(data_dir().AppendASCII("app4"), INSTALL_NEW);
536 for (size_t i = 0; i < kAppCount; ++i) {
537 ASSERT_TRUE(apps[i]);
538 ASSERT_TRUE(apps[i]->is_app());
539 }
540
541 syncer::FakeSyncChangeProcessor processor;
542 extension_sync_service()->MergeDataAndStartSyncing(
543 syncer::APPS,
544 syncer::SyncDataList(),
545 scoped_ptr<syncer::SyncChangeProcessor>(
546 new syncer::FakeSyncChangeProcessor),
547 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
548
549 ExtensionPrefs::Get(service()->GetBrowserContext())
550 ->app_sorting()
551 ->OnExtensionMoved(apps[0]->id(), apps[1]->id(), apps[2]->id());
552 {
553 syncer::SyncDataList list =
554 extension_sync_service()->GetAllSyncData(syncer::APPS);
555 ASSERT_EQ(list.size(), 3U);
556
557 scoped_ptr<ExtensionSyncData> data[kAppCount];
558 for (size_t i = 0; i < kAppCount; ++i) {
559 data[i] = ExtensionSyncData::CreateFromSyncData(list[i]);
560 ASSERT_TRUE(data[i].get());
561 }
562
563 // The sync data is not always in the same order our apps were installed in,
564 // so we do that sorting here so we can make sure the values are changed as
565 // expected.
566 syncer::StringOrdinal app_launch_ordinals[kAppCount];
567 for (size_t i = 0; i < kAppCount; ++i) {
568 for (size_t j = 0; j < kAppCount; ++j) {
569 if (apps[i]->id() == data[j]->id())
570 app_launch_ordinals[i] = data[j]->app_launch_ordinal();
571 }
572 }
573
574 EXPECT_TRUE(app_launch_ordinals[1].LessThan(app_launch_ordinals[0]));
575 EXPECT_TRUE(app_launch_ordinals[0].LessThan(app_launch_ordinals[2]));
576 }
577 }
578
579 TEST_F(ExtensionServiceSyncTest, GetSyncDataList) {
580 InitializeEmptyExtensionService();
581 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
582 InstallCRX(data_dir().AppendASCII("page_action.crx"), INSTALL_NEW);
583 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
584 InstallCRX(data_dir().AppendASCII("theme2.crx"), INSTALL_NEW);
585
586 syncer::FakeSyncChangeProcessor processor;
587 extension_sync_service()->MergeDataAndStartSyncing(
588 syncer::APPS,
589 syncer::SyncDataList(),
590 scoped_ptr<syncer::SyncChangeProcessor>(
591 new syncer::FakeSyncChangeProcessor),
592 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
593 extension_sync_service()->MergeDataAndStartSyncing(
594 syncer::EXTENSIONS,
595 syncer::SyncDataList(),
596 scoped_ptr<syncer::SyncChangeProcessor>(
597 new syncer::FakeSyncChangeProcessor),
598 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
599
600 service()->DisableExtension(page_action, Extension::DISABLE_USER_ACTION);
601 TerminateExtension(theme2_crx);
602
603 EXPECT_EQ(0u, extension_sync_service()->GetAllSyncData(syncer::APPS).size());
604 EXPECT_EQ(
605 2u, extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS).size());
606 }
607
608 TEST_F(ExtensionServiceSyncTest, ProcessSyncDataUninstall) {
609 InitializeEmptyExtensionService();
610 syncer::FakeSyncChangeProcessor processor;
611 extension_sync_service()->MergeDataAndStartSyncing(
612 syncer::EXTENSIONS,
613 syncer::SyncDataList(),
614 scoped_ptr<syncer::SyncChangeProcessor>(
615 new syncer::FakeSyncChangeProcessor),
616 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
617
618 sync_pb::EntitySpecifics specifics;
619 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
620 ext_specifics->set_id(good_crx);
621 ext_specifics->set_version("1.0");
622 syncer::SyncData sync_data =
623 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
624 syncer::SyncChange sync_change(FROM_HERE,
625 syncer::SyncChange::ACTION_DELETE,
626 sync_data);
627 syncer::SyncChangeList list(1);
628 list[0] = sync_change;
629
630 // Should do nothing.
631 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
632 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
633
634 // Install the extension.
635 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
636 InstallCRX(extension_path, INSTALL_NEW);
637 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
638
639 // Should uninstall the extension.
640 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
641 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
642
643 // Should again do nothing.
644 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
645 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
646 }
647
648 TEST_F(ExtensionServiceSyncTest, ProcessSyncDataWrongType) {
649 InitializeEmptyExtensionService();
650
651 // Install the extension.
652 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
653 InstallCRX(extension_path, INSTALL_NEW);
654 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
655
656 sync_pb::EntitySpecifics specifics;
657 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
658 sync_pb::ExtensionSpecifics* extension_specifics =
659 app_specifics->mutable_extension();
660 extension_specifics->set_id(good_crx);
661 extension_specifics->set_version(
662 service()->GetInstalledExtension(good_crx)->version()->GetString());
663
664 {
665 extension_specifics->set_enabled(true);
666 syncer::SyncData sync_data =
667 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
668 syncer::SyncChange sync_change(FROM_HERE,
669 syncer::SyncChange::ACTION_DELETE,
670 sync_data);
671 syncer::SyncChangeList list(1);
672 list[0] = sync_change;
673
674 // Should do nothing
675 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
676 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
677 }
678
679 {
680 extension_specifics->set_enabled(false);
681 syncer::SyncData sync_data =
682 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
683 syncer::SyncChange sync_change(FROM_HERE,
684 syncer::SyncChange::ACTION_UPDATE,
685 sync_data);
686 syncer::SyncChangeList list(1);
687 list[0] = sync_change;
688
689 // Should again do nothing.
690 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
691 EXPECT_TRUE(service()->GetExtensionById(good_crx, false));
692 }
693 }
694
695 TEST_F(ExtensionServiceSyncTest, ProcessSyncDataSettings) {
696 InitializeEmptyExtensionService();
697 syncer::FakeSyncChangeProcessor processor;
698 extension_sync_service()->MergeDataAndStartSyncing(
699 syncer::EXTENSIONS,
700 syncer::SyncDataList(),
701 scoped_ptr<syncer::SyncChangeProcessor>(
702 new syncer::FakeSyncChangeProcessor),
703 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
704
705 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
706 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
707 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
708 EXPECT_FALSE(extensions::util::HasSetAllowedScriptingOnAllUrls(
709 good_crx, profile()));
710 const bool kDefaultAllowedScripting =
711 extensions::util::DefaultAllowedScriptingOnAllUrls();
712 EXPECT_EQ(kDefaultAllowedScripting,
713 extensions::util::AllowedScriptingOnAllUrls(good_crx, profile()));
714
715 sync_pb::EntitySpecifics specifics;
716 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
717 ext_specifics->set_id(good_crx);
718 ext_specifics->set_version(
719 service()->GetInstalledExtension(good_crx)->version()->GetString());
720 ext_specifics->set_enabled(false);
721
722 {
723 syncer::SyncData sync_data =
724 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
725 syncer::SyncChange sync_change(FROM_HERE,
726 syncer::SyncChange::ACTION_UPDATE,
727 sync_data);
728 syncer::SyncChangeList list(1);
729 list[0] = sync_change;
730 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
731 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
732 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
733 EXPECT_FALSE(extensions::util::HasSetAllowedScriptingOnAllUrls(
734 good_crx, profile()));
735 EXPECT_EQ(kDefaultAllowedScripting,
736 extensions::util::AllowedScriptingOnAllUrls(good_crx, profile()));
737 }
738
739 {
740 ext_specifics->set_enabled(true);
741 ext_specifics->set_incognito_enabled(true);
742 syncer::SyncData sync_data =
743 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
744 syncer::SyncChange sync_change(FROM_HERE,
745 syncer::SyncChange::ACTION_UPDATE,
746 sync_data);
747 syncer::SyncChangeList list(1);
748 list[0] = sync_change;
749 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
750 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
751 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
752 }
753
754 {
755 ext_specifics->set_enabled(false);
756 ext_specifics->set_incognito_enabled(true);
757 syncer::SyncData sync_data =
758 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
759 syncer::SyncChange sync_change(FROM_HERE,
760 syncer::SyncChange::ACTION_UPDATE,
761 sync_data);
762 syncer::SyncChangeList list(1);
763 list[0] = sync_change;
764 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
765 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
766 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
767 }
768
769 {
770 ext_specifics->set_enabled(true);
771 ext_specifics->set_all_urls_enabled(!kDefaultAllowedScripting);
772 syncer::SyncData sync_data =
773 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
774 syncer::SyncChange sync_change(FROM_HERE,
775 syncer::SyncChange::ACTION_UPDATE,
776 sync_data);
777 syncer::SyncChangeList list(1);
778 list[0] = sync_change;
779 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
780 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
781 EXPECT_TRUE(extensions::util::HasSetAllowedScriptingOnAllUrls(
782 good_crx, profile()));
783 EXPECT_EQ(!kDefaultAllowedScripting,
784 extensions::util::AllowedScriptingOnAllUrls(good_crx, profile()));
785 }
786
787 {
788 ext_specifics->set_all_urls_enabled(kDefaultAllowedScripting);
789 syncer::SyncData sync_data =
790 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
791 syncer::SyncChange sync_change(FROM_HERE,
792 syncer::SyncChange::ACTION_UPDATE,
793 sync_data);
794 syncer::SyncChangeList list(1);
795 list[0] = sync_change;
796 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
797 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
798 EXPECT_TRUE(extensions::util::HasSetAllowedScriptingOnAllUrls(
799 good_crx, profile()));
800 EXPECT_EQ(kDefaultAllowedScripting,
801 extensions::util::AllowedScriptingOnAllUrls(good_crx, profile()));
802 }
803
804 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
805 }
806
807 TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNewExtension) {
808 InitializeEmptyExtensionService();
809 syncer::FakeSyncChangeProcessor processor;
810 extension_sync_service()->MergeDataAndStartSyncing(
811 syncer::EXTENSIONS,
812 syncer::SyncDataList(),
813 scoped_ptr<syncer::SyncChangeProcessor>(
814 new syncer::FakeSyncChangeProcessor),
815 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
816
817 const base::FilePath path = data_dir().AppendASCII("good.crx");
818 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
819
820 struct TestCase {
821 const char* name; // For failure output only.
822 bool sync_enabled; // The "enabled" flag coming in from Sync.
823 // The disable reason(s) coming in from Sync, or -1 for "not set".
824 int sync_disable_reasons;
825 // The disable reason(s) that should be set on the installed extension.
826 // This will usually be the same as |sync_disable_reasons|, but see the
827 // "Legacy" case.
828 int expect_disable_reasons;
829 // Whether the extension's permissions should be auto-granted during
830 // installation.
831 bool expect_permissions_granted;
832 } test_cases[] = {
833 // Standard case: Extension comes in enabled; permissions should be granted
834 // during installation.
835 { "Standard", true, 0, 0, true },
836 // If the extension comes in disabled, its permissions should still be
837 // granted (the user already approved them on another machine).
838 { "Disabled", false, Extension::DISABLE_USER_ACTION,
839 Extension::DISABLE_USER_ACTION, true },
840 // Legacy case (<M45): No disable reasons come in from Sync (see
841 // crbug.com/484214). After installation, the reason should be set to
842 // DISABLE_UNKNOWN_FROM_SYNC.
843 { "Legacy", false, -1, Extension::DISABLE_UNKNOWN_FROM_SYNC, true },
844 // If the extension came in disabled due to a permissions increase, then the
845 // user has *not* approved the permissions, and they shouldn't be granted.
846 // crbug.com/484214
847 { "PermissionsIncrease", false, Extension::DISABLE_PERMISSIONS_INCREASE,
848 Extension::DISABLE_PERMISSIONS_INCREASE, false },
849 };
850
851 for (const TestCase& test_case : test_cases) {
852 SCOPED_TRACE(test_case.name);
853
854 sync_pb::EntitySpecifics specifics;
855 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
856 ext_specifics->set_id(good_crx);
857 ext_specifics->set_version(base::Version("1").GetString());
858 ext_specifics->set_enabled(test_case.sync_enabled);
859 if (test_case.sync_disable_reasons != -1)
860 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
861
862 syncer::SyncData sync_data =
863 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
864 syncer::SyncChange sync_change(FROM_HERE,
865 syncer::SyncChange::ACTION_UPDATE,
866 sync_data);
867 syncer::SyncChangeList list(1, sync_change);
868 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
869
870 ASSERT_TRUE(service()->pending_extension_manager()->IsIdPending(good_crx));
871 UpdateExtension(good_crx, path, test_case.sync_enabled ? ENABLED
872 : DISABLED);
873 EXPECT_EQ(test_case.expect_disable_reasons,
874 prefs->GetDisableReasons(good_crx));
875 scoped_ptr<const PermissionSet> permissions =
876 prefs->GetGrantedPermissions(good_crx);
877 EXPECT_EQ(test_case.expect_permissions_granted, !permissions->IsEmpty());
878 ASSERT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
879
880 // Remove the extension again, so we can install it again for the next case.
881 UninstallExtension(good_crx, false,
882 test_case.sync_enabled ? Extension::ENABLED
883 : Extension::DISABLED);
884 }
885 }
886
887 TEST_F(ExtensionServiceSyncTest, ProcessSyncDataTerminatedExtension) {
888 InitializeExtensionServiceWithUpdater();
889 syncer::FakeSyncChangeProcessor processor;
890 extension_sync_service()->MergeDataAndStartSyncing(
891 syncer::EXTENSIONS,
892 syncer::SyncDataList(),
893 scoped_ptr<syncer::SyncChangeProcessor>(
894 new syncer::FakeSyncChangeProcessor),
895 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
896
897 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
898 TerminateExtension(good_crx);
899 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
900 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
901
902 sync_pb::EntitySpecifics specifics;
903 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
904 ext_specifics->set_id(good_crx);
905 ext_specifics->set_version(
906 service()->GetInstalledExtension(good_crx)->version()->GetString());
907 ext_specifics->set_enabled(false);
908 ext_specifics->set_incognito_enabled(true);
909 syncer::SyncData sync_data =
910 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
911 syncer::SyncChange sync_change(FROM_HERE,
912 syncer::SyncChange::ACTION_UPDATE,
913 sync_data);
914 syncer::SyncChangeList list(1);
915 list[0] = sync_change;
916
917 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
918 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
919 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
920
921 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
922 }
923
924 TEST_F(ExtensionServiceSyncTest, ProcessSyncDataVersionCheck) {
925 InitializeExtensionServiceWithUpdater();
926 syncer::FakeSyncChangeProcessor processor;
927 extension_sync_service()->MergeDataAndStartSyncing(
928 syncer::EXTENSIONS,
929 syncer::SyncDataList(),
930 scoped_ptr<syncer::SyncChangeProcessor>(
931 new syncer::FakeSyncChangeProcessor),
932 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
933
934 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
935 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
936 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
937
938 sync_pb::EntitySpecifics specifics;
939 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
940 ext_specifics->set_id(good_crx);
941 ext_specifics->set_enabled(true);
942
943 const base::Version installed_version =
944 *service()->GetInstalledExtension(good_crx)->version();
945
946 {
947 ext_specifics->set_version(installed_version.GetString());
948 syncer::SyncData sync_data =
949 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
950 syncer::SyncChange sync_change(FROM_HERE,
951 syncer::SyncChange::ACTION_UPDATE,
952 sync_data);
953 syncer::SyncChangeList list(1, sync_change);
954
955 // Should do nothing if extension version == sync version.
956 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
957 EXPECT_FALSE(service()->updater()->WillCheckSoon());
958 // Make sure the version we'll send back to sync didn't change.
959 syncer::SyncDataList data =
960 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
961 ASSERT_EQ(1u, data.size());
962 scoped_ptr<ExtensionSyncData> extension_data =
963 ExtensionSyncData::CreateFromSyncData(data[0]);
964 ASSERT_TRUE(extension_data);
965 EXPECT_TRUE(installed_version.Equals(extension_data->version()));
966 }
967
968 // Should do nothing if extension version > sync version.
969 {
970 ext_specifics->set_version("0.0.0.0");
971 syncer::SyncData sync_data =
972 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
973 syncer::SyncChange sync_change(FROM_HERE,
974 syncer::SyncChange::ACTION_UPDATE,
975 sync_data);
976 syncer::SyncChangeList list(1, sync_change);
977
978 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
979 EXPECT_FALSE(service()->updater()->WillCheckSoon());
980 // Make sure the version we'll send back to sync didn't change.
981 syncer::SyncDataList data =
982 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
983 ASSERT_EQ(1u, data.size());
984 scoped_ptr<ExtensionSyncData> extension_data =
985 ExtensionSyncData::CreateFromSyncData(data[0]);
986 ASSERT_TRUE(extension_data);
987 EXPECT_TRUE(installed_version.Equals(extension_data->version()));
988 }
989
990 // Should kick off an update if extension version < sync version.
991 {
992 const base::Version new_version("9.9.9.9");
993 ext_specifics->set_version(new_version.GetString());
994 syncer::SyncData sync_data =
995 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
996 syncer::SyncChange sync_change(FROM_HERE,
997 syncer::SyncChange::ACTION_UPDATE,
998 sync_data);
999 syncer::SyncChangeList list(1, sync_change);
1000
1001 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1002 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1003 // Make sure that we'll send the NEW version back to sync, even though we
1004 // haven't actually updated yet. This is to prevent the data in sync from
1005 // flip-flopping back and forth until all clients are up to date.
1006 syncer::SyncDataList data =
1007 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1008 ASSERT_EQ(1u, data.size());
1009 scoped_ptr<ExtensionSyncData> extension_data =
1010 ExtensionSyncData::CreateFromSyncData(data[0]);
1011 ASSERT_TRUE(extension_data);
1012 EXPECT_TRUE(new_version.Equals(extension_data->version()));
1013 }
1014
1015 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1016 }
1017
1018 TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNotInstalled) {
1019 InitializeExtensionServiceWithUpdater();
1020 syncer::FakeSyncChangeProcessor processor;
1021 extension_sync_service()->MergeDataAndStartSyncing(
1022 syncer::EXTENSIONS,
1023 syncer::SyncDataList(),
1024 scoped_ptr<syncer::SyncChangeProcessor>(
1025 new syncer::FakeSyncChangeProcessor),
1026 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
1027
1028 sync_pb::EntitySpecifics specifics;
1029 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1030 ext_specifics->set_id(good_crx);
1031 ext_specifics->set_enabled(false);
1032 ext_specifics->set_incognito_enabled(true);
1033 ext_specifics->set_update_url("http://www.google.com/");
1034 ext_specifics->set_version("1.2.3.4");
1035 syncer::SyncData sync_data =
1036 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
1037 syncer::SyncChange sync_change(FROM_HERE,
1038 syncer::SyncChange::ACTION_UPDATE,
1039 sync_data);
1040 syncer::SyncChangeList list(1);
1041 list[0] = sync_change;
1042
1043 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1044 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1045 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1046 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1047 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1048 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1049
1050 const extensions::PendingExtensionInfo* info;
1051 EXPECT_TRUE(
1052 (info = service()->pending_extension_manager()->GetById(good_crx)));
1053 EXPECT_EQ(ext_specifics->update_url(), info->update_url().spec());
1054 EXPECT_TRUE(info->is_from_sync());
1055 EXPECT_EQ(Manifest::INTERNAL, info->install_source());
1056 // TODO(akalin): Figure out a way to test |info.ShouldAllowInstall()|.
1057 }
1058
1059 TEST_F(ExtensionServiceSyncTest, ProcessSyncDataEnableDisable) {
1060 InitializeEmptyExtensionService();
1061 extension_sync_service()->MergeDataAndStartSyncing(
1062 syncer::EXTENSIONS,
1063 syncer::SyncDataList(),
1064 scoped_ptr<syncer::SyncChangeProcessor>(
1065 new syncer::FakeSyncChangeProcessor),
1066 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
1067
1068 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1069
1070 struct TestCase {
1071 const char* name; // For failure output only.
1072 // Set of disable reasons before any Sync data comes in. If this is != 0,
1073 // the extension is disabled.
1074 int previous_disable_reasons;
1075 bool sync_enable; // The enabled flag coming in from Sync.
1076 // The disable reason(s) coming in from Sync, or -1 for "not set".
1077 int sync_disable_reasons;
1078 // The expected set of disable reasons after processing the Sync update. The
1079 // extension should be disabled iff this is != 0.
1080 int expect_disable_reasons;
1081 } test_cases[] = {
1082 { "NopEnable", 0, true, 0, 0 },
1083 { "NopDisable", Extension::DISABLE_USER_ACTION, false,
1084 Extension::DISABLE_USER_ACTION, Extension::DISABLE_USER_ACTION },
1085 { "Disable", 0, false, Extension::DISABLE_USER_ACTION,
1086 Extension::DISABLE_USER_ACTION },
1087 { "DisableLegacy", 0, false, -1, Extension::DISABLE_UNKNOWN_FROM_SYNC },
1088 { "AddDisableReason", Extension::DISABLE_REMOTE_INSTALL, false,
1089 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION,
1090 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION },
1091 { "AddDisableReasonLegacy", Extension::DISABLE_USER_ACTION, false, -1,
1092 Extension::DISABLE_USER_ACTION | Extension::DISABLE_UNKNOWN_FROM_SYNC},
1093 { "RemoveDisableReason",
1094 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION, false,
1095 Extension::DISABLE_USER_ACTION, Extension::DISABLE_USER_ACTION },
1096 { "Enable", Extension::DISABLE_USER_ACTION, true, 0, 0 },
1097 { "EnableLegacy", Extension::DISABLE_USER_ACTION, true, -1, 0 },
1098 };
1099
1100 for (const TestCase& test_case : test_cases) {
1101 SCOPED_TRACE(test_case.name);
1102
1103 std::string id;
1104 std::string version;
1105 // Don't keep |extension| around longer than necessary.
1106 {
1107 const Extension* extension =
1108 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1109 // The extension should now be installed and enabled.
1110 ASSERT_TRUE(extension);
1111 id = extension->id();
1112 version = extension->VersionString();
1113 }
1114 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1115
1116 // Disable it if the test case says so.
1117 if (test_case.previous_disable_reasons) {
1118 service()->DisableExtension(id, test_case.previous_disable_reasons);
1119 ASSERT_TRUE(registry()->disabled_extensions().Contains(id));
1120 }
1121
1122 // Now a sync update comes in.
1123 sync_pb::EntitySpecifics specifics;
1124 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1125 ext_specifics->set_id(id);
1126 ext_specifics->set_enabled(test_case.sync_enable);
1127 ext_specifics->set_version(version);
1128 if (test_case.sync_disable_reasons != -1)
1129 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1130
1131 syncer::SyncData sync_data =
1132 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
1133 syncer::SyncChange sync_change(FROM_HERE,
1134 syncer::SyncChange::ACTION_UPDATE,
1135 sync_data);
1136 syncer::SyncChangeList list(1, sync_change);
1137 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1138
1139 // Check expectations.
1140 const bool expect_enabled = !test_case.expect_disable_reasons;
1141 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1142 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
1143
1144 // Remove the extension again, so we can install it again for the next case.
1145 UninstallExtension(id, false, expect_enabled ? Extension::ENABLED
1146 : Extension::DISABLED);
1147 }
1148 }
1149
1150 TEST_F(ExtensionServiceSyncTest, ProcessSyncDataDeferredEnable) {
1151 InitializeEmptyExtensionService();
1152 extension_sync_service()->MergeDataAndStartSyncing(
1153 syncer::EXTENSIONS,
1154 syncer::SyncDataList(),
1155 scoped_ptr<syncer::SyncChangeProcessor>(
1156 new syncer::FakeSyncChangeProcessor),
1157 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
1158
1159 base::FilePath base_path = data_dir().AppendASCII("permissions_increase");
1160 base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1161
1162 base::FilePath path = base_path.AppendASCII("v1");
1163 const Extension* extension = PackAndInstallCRX(path, pem_path, INSTALL_NEW);
1164 // The extension must now be installed and enabled.
1165 ASSERT_TRUE(extension);
1166 ASSERT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
1167
1168 // Save the id, as the extension object will be destroyed during updating.
1169 std::string id = extension->id();
1170
1171 // Update to a new version with increased permissions.
1172 path = base_path.AppendASCII("v2");
1173 PackCRXAndUpdateExtension(id, path, pem_path, DISABLED);
1174
1175 // Now a sync update comes in, telling us to re-enable a *newer* version.
1176 sync_pb::EntitySpecifics specifics;
1177 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1178 ext_specifics->set_id(id);
1179 ext_specifics->set_version("3");
1180 ext_specifics->set_enabled(true);
1181 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
1182
1183 syncer::SyncData sync_data =
1184 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
1185 syncer::SyncChange sync_change(FROM_HERE,
1186 syncer::SyncChange::ACTION_UPDATE,
1187 sync_data);
1188 syncer::SyncChangeList list(1, sync_change);
1189 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1190
1191 // Since the version didn't match, the extension should still be disabled.
1192 EXPECT_TRUE(registry()->disabled_extensions().Contains(id));
1193
1194 // After we update to the matching version, the extension should get enabled.
1195 path = base_path.AppendASCII("v3");
1196 PackCRXAndUpdateExtension(id, path, pem_path, ENABLED);
1197 }
1198
1199 TEST_F(ExtensionServiceSyncTest, ProcessSyncDataPermissionApproval) {
1200 // This is the update URL specified in the test extension. Setting it here is
1201 // necessary to make it considered syncable.
1202 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1203 switches::kAppsGalleryUpdateURL,
1204 "http://localhost/autoupdate/updates.xml");
1205
1206 InitializeEmptyExtensionService();
1207 extension_sync_service()->MergeDataAndStartSyncing(
1208 syncer::EXTENSIONS,
1209 syncer::SyncDataList(),
1210 scoped_ptr<syncer::SyncChangeProcessor>(
1211 new syncer::FakeSyncChangeProcessor),
1212 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
1213
1214 const base::FilePath base_path =
1215 data_dir().AppendASCII("permissions_increase");
1216 const base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1217 const base::FilePath path_v1 = base_path.AppendASCII("v1");
1218 const base::FilePath path_v2 = base_path.AppendASCII("v2");
1219
1220 base::ScopedTempDir crx_dir;
1221 ASSERT_TRUE(crx_dir.CreateUniqueTempDir());
1222 const base::FilePath crx_path_v1 = crx_dir.path().AppendASCII("temp1.crx");
1223 PackCRX(path_v1, pem_path, crx_path_v1);
1224 const base::FilePath crx_path_v2 = crx_dir.path().AppendASCII("temp2.crx");
1225 PackCRX(path_v2, pem_path, crx_path_v2);
1226
1227 const std::string v1("1");
1228 const std::string v2("2");
1229
1230 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1231
1232 struct TestCase {
1233 const char* name; // For failure output only.
1234 const std::string& sync_version; // The version coming in from Sync.
1235 // The disable reason(s) coming in from Sync, or -1 for "not set".
1236 int sync_disable_reasons;
1237 // The expected set of disable reasons after processing the Sync update. The
1238 // extension should be enabled iff this is 0.
1239 int expect_disable_reasons;
1240 // Whether the extension's permissions should be auto-granted.
1241 bool expect_permissions_granted;
1242 } test_cases[] = {
1243 // Sync tells us to re-enable an older version. No permissions should be
1244 // granted, since we can't be sure if the user actually approved the right
1245 // set of permissions.
1246 { "OldVersion", v1, 0, Extension::DISABLE_PERMISSIONS_INCREASE, false },
1247 // Legacy case: Sync tells us to re-enable the extension, but doesn't
1248 // specify disable reasons. No permissions should be granted.
1249 { "Legacy", v2, -1, Extension::DISABLE_PERMISSIONS_INCREASE, false },
1250 // Sync tells us to re-enable the extension and explicitly removes the
1251 // disable reasons. Now the extension should have its permissions granted.
1252 { "GrantPermissions", v2, 0, Extension::DISABLE_NONE, true },
1253 };
1254
1255 for (const TestCase& test_case : test_cases) {
1256 SCOPED_TRACE(test_case.name);
1257
1258 std::string id;
1259 // Don't keep |extension| around longer than necessary (it'll be destroyed
1260 // during updating).
1261 {
1262 const Extension* extension = InstallCRX(crx_path_v1, INSTALL_NEW);
1263 // The extension should now be installed and enabled.
1264 ASSERT_TRUE(extension);
1265 ASSERT_EQ(v1, extension->VersionString());
1266 id = extension->id();
1267 }
1268 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1269
1270 scoped_ptr<const PermissionSet> granted_permissions_v1 =
1271 prefs->GetGrantedPermissions(id);
1272
1273 // Update to a new version with increased permissions.
1274 UpdateExtension(id, crx_path_v2, DISABLED);
1275
1276 // Now the extension should be disabled due to a permissions increase.
1277 {
1278 const Extension* extension =
1279 registry()->disabled_extensions().GetByID(id);
1280 ASSERT_TRUE(extension);
1281 ASSERT_EQ(v2, extension->VersionString());
1282 }
1283 ASSERT_TRUE(prefs->HasDisableReason(
1284 id, Extension::DISABLE_PERMISSIONS_INCREASE));
1285
1286 // No new permissions should have been granted.
1287 scoped_ptr<const PermissionSet> granted_permissions_v2 =
1288 prefs->GetGrantedPermissions(id);
1289 ASSERT_EQ(*granted_permissions_v1, *granted_permissions_v2);
1290
1291 // Now a sync update comes in.
1292 sync_pb::EntitySpecifics specifics;
1293 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1294 ext_specifics->set_id(id);
1295 ext_specifics->set_enabled(true);
1296 ext_specifics->set_version(test_case.sync_version);
1297 if (test_case.sync_disable_reasons != -1)
1298 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1299
1300 syncer::SyncData sync_data =
1301 syncer::SyncData::CreateLocalData(good_crx, "Name", specifics);
1302 syncer::SyncChange sync_change(FROM_HERE,
1303 syncer::SyncChange::ACTION_UPDATE,
1304 sync_data);
1305 syncer::SyncChangeList list(1, sync_change);
1306 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1307
1308 // Check expectations.
1309 const bool expect_enabled = !test_case.expect_disable_reasons;
1310 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1311 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
1312 scoped_ptr<const PermissionSet> granted_permissions =
1313 prefs->GetGrantedPermissions(id);
1314 if (test_case.expect_permissions_granted) {
1315 scoped_ptr<const PermissionSet> active_permissions =
1316 prefs->GetActivePermissions(id);
1317 EXPECT_EQ(*granted_permissions, *active_permissions);
1318 } else {
1319 EXPECT_EQ(*granted_permissions, *granted_permissions_v1);
1320 }
1321
1322 // Remove the extension again, so we can install it again for the next case.
1323 UninstallExtension(id, false, expect_enabled ? Extension::ENABLED
1324 : Extension::DISABLED);
1325 }
1326 }
1327
1328 #if defined(ENABLE_SUPERVISED_USERS)
1329
1330 class ExtensionServiceTestSupervised : public ExtensionServiceSyncTest,
1331 public SupervisedUserService::Delegate {
1332 public:
1333 void SetUp() override {
1334 ExtensionServiceSyncTest::SetUp();
1335
1336 // This is the update URL specified in the permissions test extension.
1337 // Setting it here is necessary to make the extension considered syncable.
1338 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1339 switches::kAppsGalleryUpdateURL,
1340 "http://localhost/autoupdate/updates.xml");
1341 }
1342
1343 void TearDown() override {
1344 supervised_user_service()->SetDelegate(nullptr);
1345
1346 ExtensionServiceSyncTest::TearDown();
1347 }
1348
1349 protected:
1350 void InitServices(bool profile_is_supervised) {
1351 ExtensionServiceInitParams params = CreateDefaultInitParams();
1352 params.profile_is_supervised = profile_is_supervised;
1353 InitializeExtensionService(params);
1354
1355 supervised_user_service()->SetDelegate(this);
1356 supervised_user_service()->Init();
1357 }
1358
1359 std::string InstallPermissionsTestExtension() {
1360 const std::string version("1");
1361
1362 const Extension* extension =
1363 PackAndInstallCRX(dir_path(version), pem_path(), INSTALL_NEW,
1364 Extension::WAS_INSTALLED_BY_CUSTODIAN);
1365 // The extension must now be installed and enabled.
1366 EXPECT_TRUE(extension);
1367 EXPECT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
1368 EXPECT_EQ(version, extension->VersionString());
1369
1370 return extension->id();
1371 }
1372
1373 void UpdatePermissionsTestExtension(const std::string& id,
1374 const std::string& version,
1375 UpdateState expected_state) {
1376 PackCRXAndUpdateExtension(id, dir_path(version), pem_path(),
1377 expected_state);
1378 const Extension* extension = registry()->GetInstalledExtension(id);
1379 ASSERT_TRUE(extension);
1380 // The version should have been updated.
1381 EXPECT_EQ(version, extension->VersionString());
1382 }
1383
1384 SupervisedUserService* supervised_user_service() {
1385 return SupervisedUserServiceFactory::GetForProfile(profile());
1386 }
1387
1388 static std::string UpdateRequestId(const std::string& extension_id,
1389 const std::string& version) {
1390 return SupervisedUserService::GetExtensionUpdateRequestId(
1391 extension_id, base::Version(version));
1392 }
1393
1394 private:
1395 // This prevents the legacy supervised user init code from running.
1396 bool SetActive(bool active) override { return true; }
1397
1398 base::FilePath base_path() const {
1399 return data_dir().AppendASCII("permissions_increase");
1400 }
1401 base::FilePath dir_path(const std::string& version) const {
1402 return base_path().AppendASCII("v" + version);
1403 }
1404 base::FilePath pem_path() const {
1405 return base_path().AppendASCII("permissions.pem");
1406 }
1407 };
1408
1409 class MockPermissionRequestCreator : public PermissionRequestCreator {
1410 public:
1411 MockPermissionRequestCreator() {}
1412 ~MockPermissionRequestCreator() override {}
1413
1414 bool IsEnabled() const override { return true; }
1415
1416 void CreateURLAccessRequest(const GURL& url_requested,
1417 const SuccessCallback& callback) override {
1418 FAIL();
1419 }
1420
1421 MOCK_METHOD2(CreateExtensionUpdateRequest,
1422 void(const std::string& id,
1423 const SupervisedUserService::SuccessCallback& callback));
1424
1425 private:
1426 DISALLOW_COPY_AND_ASSIGN(MockPermissionRequestCreator);
1427 };
1428
1429 TEST_F(ExtensionServiceTestSupervised, InstallOnlyAllowedByCustodian) {
1430 InitServices(true /* profile_is_supervised */);
1431
1432 base::FilePath path1 = data_dir().AppendASCII("good.crx");
1433 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
1434 const Extension* extensions[] = {
1435 InstallCRX(path1, INSTALL_FAILED),
1436 InstallCRX(path2, INSTALL_NEW, Extension::WAS_INSTALLED_BY_CUSTODIAN)
1437 };
1438
1439 // Only the extension with the "installed by custodian" flag should have been
1440 // installed and enabled.
1441 EXPECT_FALSE(extensions[0]);
1442 ASSERT_TRUE(extensions[1]);
1443 EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id()));
1444 }
1445
1446 TEST_F(ExtensionServiceTestSupervised, PreinstalledExtension) {
1447 InitServices(false /* profile_is_supervised */);
1448
1449 // Install an extension.
1450 base::FilePath path = data_dir().AppendASCII("good.crx");
1451 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1452 std::string id = extension->id();
1453
1454 // Now make the profile supervised.
1455 profile()->AsTestingProfile()->SetSupervisedUserId(
1456 supervised_users::kChildAccountSUID);
1457
1458 // The extension should not be enabled anymore.
1459 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
1460 }
1461
1462 TEST_F(ExtensionServiceTestSupervised, UpdateWithoutPermissionIncrease) {
1463 InitServices(true /* profile_is_supervised */);
1464
1465 base::FilePath base_path = data_dir().AppendASCII("autoupdate");
1466 base::FilePath pem_path = base_path.AppendASCII("key.pem");
1467
1468 const Extension* extension =
1469 PackAndInstallCRX(base_path.AppendASCII("v1"), pem_path, INSTALL_NEW,
1470 Extension::WAS_INSTALLED_BY_CUSTODIAN);
1471 // The extension must now be installed and enabled.
1472 ASSERT_TRUE(extension);
1473 ASSERT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
1474
1475 // Save the id, as the extension object will be destroyed during updating.
1476 std::string id = extension->id();
1477
1478 std::string old_version = extension->VersionString();
1479
1480 // Update to a new version.
1481 PackCRXAndUpdateExtension(id, base_path.AppendASCII("v2"), pem_path, ENABLED);
1482
1483 // The extension should still be there and enabled.
1484 extension = registry()->enabled_extensions().GetByID(id);
1485 ASSERT_TRUE(extension);
1486 // The version should have changed.
1487 EXPECT_NE(extension->VersionString(), old_version);
1488 }
1489
1490 TEST_F(ExtensionServiceTestSupervised, UpdateWithPermissionIncreaseNoApproval) {
1491 // Explicitly disable the "need custodian approval" field trial.
1492 base::FieldTrialList field_trial_list(new base::MockEntropyProvider());
1493 base::FieldTrialList::CreateFieldTrial(
1494 "SupervisedUserExtensionPermissionIncrease", "");
1495
1496 InitServices(true /* profile_is_supervised */);
1497
1498 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1499 supervised_user_service()->AddPermissionRequestCreator(
1500 make_scoped_ptr(creator));
1501
1502 std::string id = InstallPermissionsTestExtension();
1503
1504 // Update to a new version with increased permissions.
1505 // Since we don't require the custodian's approval, no permission request
1506 // should be created.
1507 const std::string version2("2");
1508 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
1509 UpdateRequestId(id, version2), testing::_))
1510 .Times(0);
1511 UpdatePermissionsTestExtension(id, version2, DISABLED);
1512 }
1513
1514 TEST_F(ExtensionServiceTestSupervised,
1515 UpdateWithPermissionIncreaseApprovalOldVersion) {
1516 // Explicitly enable the "need custodian approval" field trial.
1517 base::FieldTrialList field_trial_list(new base::MockEntropyProvider());
1518 base::FieldTrialList::CreateFieldTrial(
1519 "SupervisedUserExtensionPermissionIncrease", "NeedCustodianApproval");
1520
1521 InitServices(true /* profile_is_supervised */);
1522
1523 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1524 supervised_user_service()->AddPermissionRequestCreator(
1525 make_scoped_ptr(creator));
1526
1527 const std::string version1("1");
1528 const std::string version2("2");
1529
1530 std::string id = InstallPermissionsTestExtension();
1531
1532 // Update to a new version with increased permissions.
1533 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
1534 UpdateRequestId(id, version2), testing::_));
1535 UpdatePermissionsTestExtension(id, version2, DISABLED);
1536
1537 // Simulate a custodian approval for re-enabling the extension coming in
1538 // through Sync, but set the old version. This can happen when there already
1539 // was a pending request for an earlier version of the extension.
1540 sync_pb::EntitySpecifics specifics;
1541 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1542 ext_specifics->set_id(id);
1543 ext_specifics->set_enabled(true);
1544 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
1545 ext_specifics->set_installed_by_custodian(true);
1546 ext_specifics->set_version(version1);
1547
1548 // Attempting to re-enable an old version should result in a permission
1549 // request for the current version.
1550 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
1551 UpdateRequestId(id, version2), testing::_));
1552
1553 syncer::SyncData sync_data =
1554 syncer::SyncData::CreateLocalData(id, "Name", specifics);
1555 syncer::SyncChange sync_change(FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
1556 sync_data);
1557 syncer::SyncChangeList change_list(1, sync_change);
1558 extension_sync_service()->ProcessSyncChanges(FROM_HERE, change_list);
1559 // The re-enable should be ignored, since the version doesn't match.
1560 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
1561 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
1562 id, base::Version(version1)));
1563 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
1564 id, base::Version(version2)));
1565 }
1566
1567 TEST_F(ExtensionServiceTestSupervised,
1568 UpdateWithPermissionIncreaseApprovalMatchingVersion) {
1569 // Explicitly enable the "need custodian approval" field trial.
1570 base::FieldTrialList field_trial_list(new base::MockEntropyProvider());
1571 base::FieldTrialList::CreateFieldTrial(
1572 "SupervisedUserExtensionPermissionIncrease", "NeedCustodianApproval");
1573
1574 InitServices(true /* profile_is_supervised */);
1575
1576 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1577 supervised_user_service()->AddPermissionRequestCreator(
1578 make_scoped_ptr(creator));
1579
1580 std::string id = InstallPermissionsTestExtension();
1581
1582 // Update to a new version with increased permissions.
1583 const std::string version2("2");
1584 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
1585 UpdateRequestId(id, version2), testing::_));
1586 UpdatePermissionsTestExtension(id, version2, DISABLED);
1587
1588 // Simulate a custodian approval for re-enabling the extension coming in
1589 // through Sync.
1590 sync_pb::EntitySpecifics specifics;
1591 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1592 ext_specifics->set_id(id);
1593 ext_specifics->set_enabled(true);
1594 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
1595 ext_specifics->set_installed_by_custodian(true);
1596 ext_specifics->set_version(version2);
1597
1598 syncer::SyncData sync_data =
1599 syncer::SyncData::CreateLocalData(id, "Name", specifics);
1600 syncer::SyncChange sync_change(FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
1601 sync_data);
1602 syncer::SyncChangeList change_list(1, sync_change);
1603 extension_sync_service()->ProcessSyncChanges(FROM_HERE, change_list);
1604 // The extension should have gotten re-enabled.
1605 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1606 }
1607
1608 TEST_F(ExtensionServiceTestSupervised,
1609 UpdateWithPermissionIncreaseApprovalNewVersion) {
1610 // Explicitly enable the "need custodian approval" field trial.
1611 base::FieldTrialList field_trial_list(new base::MockEntropyProvider());
1612 base::FieldTrialList::CreateFieldTrial(
1613 "SupervisedUserExtensionPermissionIncrease", "NeedCustodianApproval");
1614
1615 InitServices(true /* profile_is_supervised */);
1616
1617 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1618 supervised_user_service()->AddPermissionRequestCreator(
1619 make_scoped_ptr(creator));
1620
1621 std::string id = InstallPermissionsTestExtension();
1622
1623 // Update to a new version with increased permissions.
1624 const std::string version2("2");
1625 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
1626 UpdateRequestId(id, version2), testing::_));
1627 UpdatePermissionsTestExtension(id, version2, DISABLED);
1628
1629 // Simulate a custodian approval for re-enabling the extension coming in
1630 // through Sync. Set a newer version than we have installed.
1631 const std::string version3("3");
1632 sync_pb::EntitySpecifics specifics;
1633 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1634 ext_specifics->set_id(id);
1635 ext_specifics->set_enabled(true);
1636 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
1637 ext_specifics->set_installed_by_custodian(true);
1638 ext_specifics->set_version(version3);
1639
1640 // This should *not* result in a new permission request.
1641 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
1642 UpdateRequestId(id, version3), testing::_))
1643 .Times(0);
1644
1645 syncer::SyncData sync_data =
1646 syncer::SyncData::CreateLocalData(id, "Name", specifics);
1647 syncer::SyncChange sync_change(FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
1648 sync_data);
1649 syncer::SyncChangeList change_list(1, sync_change);
1650 extension_sync_service()->ProcessSyncChanges(FROM_HERE, change_list);
1651 // The re-enable should be delayed until the extension is updated to the
1652 // matching version.
1653 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
1654 EXPECT_TRUE(extension_sync_service()->HasPendingReenable(
1655 id, base::Version(version3)));
1656
1657 // Update to the matching version. Now the extension should get enabled.
1658 UpdatePermissionsTestExtension(id, version3, ENABLED);
1659 }
1660
1661 TEST_F(ExtensionServiceSyncTest, SyncUninstallByCustodianSkipsPolicy) {
1662 InitializeEmptyExtensionService();
1663 extension_sync_service()->MergeDataAndStartSyncing(
1664 syncer::EXTENSIONS,
1665 syncer::SyncDataList(),
1666 scoped_ptr<syncer::SyncChangeProcessor>(
1667 new syncer::FakeSyncChangeProcessor),
1668 scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
1669
1670 // Install two extensions.
1671 base::FilePath path1 = data_dir().AppendASCII("good.crx");
1672 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
1673 const Extension* extensions[] = {
1674 InstallCRX(path1, INSTALL_NEW),
1675 InstallCRX(path2, INSTALL_NEW, Extension::WAS_INSTALLED_BY_CUSTODIAN)
1676 };
1677
1678 // Add a policy provider that will disallow any changes.
1679 extensions::TestManagementPolicyProvider provider(
1680 extensions::TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS);
1681 ExtensionSystem::Get(
1682 browser_context())->management_policy()->RegisterProvider(&provider);
1683
1684 // Create a sync deletion for each extension.
1685 syncer::SyncChangeList change_list;
1686 for (size_t i = 0; i < arraysize(extensions); i++) {
1687 const std::string& id = extensions[i]->id();
1688 sync_pb::EntitySpecifics specifics;
1689 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1690 ext_specifics->set_id(id);
1691 ext_specifics->set_version("1.0");
1692 ext_specifics->set_installed_by_custodian(
1693 extensions[i]->was_installed_by_custodian());
1694 syncer::SyncData sync_data =
1695 syncer::SyncData::CreateLocalData(id, "Name", specifics);
1696 change_list.push_back(syncer::SyncChange(FROM_HERE,
1697 syncer::SyncChange::ACTION_DELETE,
1698 sync_data));
1699 }
1700
1701 // Save the extension ids, as uninstalling destroys the Extension instance.
1702 std::string extension_ids[] = {
1703 extensions[0]->id(),
1704 extensions[1]->id()
1705 };
1706
1707 // Now apply the uninstallations.
1708 extension_sync_service()->ProcessSyncChanges(FROM_HERE, change_list);
1709
1710 // Uninstalling the extension without installed_by_custodian should have been
1711 // blocked by policy, so it should still be there.
1712 EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_ids[0]));
1713
1714 // But installed_by_custodian should result in bypassing the policy check.
1715 EXPECT_FALSE(
1716 registry()->GenerateInstalledExtensionsSet()->Contains(extension_ids[1]));
1717 }
1718
1719 #endif // defined(ENABLE_SUPERVISED_USERS)
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/extensions/extension_service_test_base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698