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