blob: a283a8e86be88b0d1b0368c138b43f8914701752 [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
avia2f4804a2015-12-24 23:11:135#include <stddef.h>
6
treibb6af28cd2015-12-01 11:19:467#include <map>
treib9afc6212015-10-30 18:49:588#include <string>
limasdf3d102542015-12-09 03:58:459#include <utility>
treib9afc6212015-10-30 18:49:5810
11#include "base/bind.h"
12#include "base/command_line.h"
13#include "base/files/file_util.h"
avia2f4804a2015-12-24 23:11:1314#include "base/macros.h"
treib9afc6212015-10-30 18:49:5815#include "base/memory/scoped_ptr.h"
16#include "base/memory/weak_ptr.h"
17#include "base/metrics/field_trial.h"
18#include "base/test/mock_entropy_provider.h"
19#include "chrome/browser/extensions/component_loader.h"
20#include "chrome/browser/extensions/extension_service.h"
21#include "chrome/browser/extensions/extension_service_test_with_install.h"
22#include "chrome/browser/extensions/extension_sync_data.h"
23#include "chrome/browser/extensions/extension_sync_service.h"
24#include "chrome/browser/extensions/extension_util.h"
25#include "chrome/browser/extensions/updater/extension_updater.h"
treib9afc6212015-10-30 18:49:5826#include "chrome/browser/sync/profile_sync_service_factory.h"
27#include "chrome/common/chrome_constants.h"
28#include "chrome/common/chrome_switches.h"
29#include "chrome/common/extensions/sync_helper.h"
30#include "chrome/test/base/testing_profile.h"
blundell7282b512015-11-09 07:21:1131#include "components/browser_sync/browser/profile_sync_service.h"
rdevlin.cronin738501d2015-11-05 21:51:3632#include "components/crx_file/id_util.h"
treibb6af28cd2015-12-01 11:19:4633#include "components/variations/variations_associated_data.h"
treib9afc6212015-10-30 18:49:5834#include "extensions/browser/app_sorting.h"
35#include "extensions/browser/extension_prefs.h"
36#include "extensions/browser/extension_registry.h"
37#include "extensions/browser/extension_system.h"
38#include "extensions/browser/management_policy.h"
39#include "extensions/browser/test_management_policy.h"
40#include "extensions/common/constants.h"
rdevlin.cronin738501d2015-11-05 21:51:3641#include "extensions/common/extension_builder.h"
treib9afc6212015-10-30 18:49:5842#include "extensions/common/manifest_url_handlers.h"
43#include "extensions/common/permissions/permission_set.h"
rdevlin.cronin738501d2015-11-05 21:51:3644#include "extensions/common/value_builder.h"
treib9afc6212015-10-30 18:49:5845#include "sync/api/fake_sync_change_processor.h"
asargente48ab752016-03-12 00:59:2046#include "sync/api/sync_change_processor_wrapper_for_test.h"
treib9afc6212015-10-30 18:49:5847#include "sync/api/sync_data.h"
48#include "sync/api/sync_error_factory_mock.h"
49#include "testing/gtest/include/gtest/gtest.h"
50
51#if defined(ENABLE_SUPERVISED_USERS)
52#include "chrome/browser/supervised_user/permission_request_creator.h"
53#include "chrome/browser/supervised_user/supervised_user_constants.h"
54#include "chrome/browser/supervised_user/supervised_user_service.h"
55#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
56#endif
57
58using extensions::AppSorting;
59using extensions::Extension;
60using extensions::ExtensionPrefs;
61using extensions::ExtensionSyncData;
62using extensions::ExtensionSystem;
63using extensions::Manifest;
64using extensions::PermissionSet;
treib65f103042015-12-03 10:21:3665using syncer::SyncChange;
66using syncer::SyncChangeList;
67
68namespace {
treib9afc6212015-10-30 18:49:5869
70const char good0[] = "behllobkkfkfnphdnhnkndlbkcpglgmj";
71const char good2[] = "bjafgdebaacbbbecmhlhpofkepfkgcpa";
72const char good_crx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
73const char page_action[] = "obcimlgaoabeegjmmpldobjndiealpln";
74const char theme2_crx[] = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf";
75
treib65f103042015-12-03 10:21:3676SyncChangeList MakeSyncChangeList(const std::string& id,
77 const sync_pb::EntitySpecifics& specifics,
78 SyncChange::SyncChangeType change_type) {
79 syncer::SyncData sync_data =
80 syncer::SyncData::CreateLocalData(id, "Name", specifics);
81 return SyncChangeList(1, SyncChange(FROM_HERE, change_type, sync_data));
82}
83
asargente48ab752016-03-12 00:59:2084// This is a FakeSyncChangeProcessor specialization that maintains a store of
85// SyncData items in the superclass' data_ member variable, treating it like a
86// map keyed by the extension id from the SyncData. Each instance of this class
87// should only be used for one model type (which should be either extensions or
88// apps) to match how the real sync system handles things.
89class StatefulChangeProcessor : public syncer::FakeSyncChangeProcessor {
90 public:
91 explicit StatefulChangeProcessor(syncer::ModelType expected_type)
92 : expected_type_(expected_type) {
93 EXPECT_TRUE(expected_type == syncer::ModelType::EXTENSIONS ||
94 expected_type == syncer::ModelType::APPS);
95 }
96
97 ~StatefulChangeProcessor() override {}
98
99 // We let our parent class, FakeSyncChangeProcessor, handle saving the
100 // changes for us, but in addition we "apply" these changes by treating
101 // the FakeSyncChangeProcessor's SyncDataList as a map keyed by extension
102 // id.
103 syncer::SyncError ProcessSyncChanges(
104 const tracked_objects::Location& from_here,
105 const syncer::SyncChangeList& change_list) override {
106 syncer::FakeSyncChangeProcessor::ProcessSyncChanges(from_here, change_list);
107 for (const auto& change : change_list) {
108 syncer::SyncData sync_data = change.sync_data();
109 EXPECT_EQ(expected_type_, sync_data.GetDataType());
110
111 scoped_ptr<ExtensionSyncData> modified =
112 ExtensionSyncData::CreateFromSyncData(sync_data);
113
114 // Start by removing any existing entry for this extension id.
115 syncer::SyncDataList& data_list = data();
116 for (auto iter = data_list.begin(); iter != data_list.end(); ++iter) {
117 scoped_ptr<ExtensionSyncData> existing =
118 ExtensionSyncData::CreateFromSyncData(*iter);
119 if (existing->id() == modified->id()) {
120 data_list.erase(iter);
121 break;
122 }
123 }
124
125 // Now add in the new data for this id, if appropriate.
126 if (change.change_type() == SyncChange::ACTION_ADD ||
127 change.change_type() == SyncChange::ACTION_UPDATE) {
128 data_list.push_back(sync_data);
129 } else if (change.change_type() != SyncChange::ACTION_DELETE) {
130 ADD_FAILURE() << "Unexpected change type " << change.change_type();
131 }
132 }
133 return syncer::SyncError();
134 }
135
136 // We override this to help catch the error of trying to use a single
137 // StatefulChangeProcessor to process changes for both extensions and apps
138 // sync data.
139 syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override {
140 EXPECT_EQ(expected_type_, type);
141 return FakeSyncChangeProcessor::GetAllSyncData(type);
142 }
143
144 // This is a helper to vend a wrapped version of this object suitable for
145 // passing in to MergeDataAndStartSyncing, which takes a
146 // scoped_ptr<SyncChangeProcessor>, since in tests we typically don't want to
147 // give up ownership of a local change processor.
148 scoped_ptr<syncer::SyncChangeProcessor> GetWrapped() {
149 return make_scoped_ptr(new syncer::SyncChangeProcessorWrapperForTest(this));
150 }
151
152 protected:
153 // The expected ModelType of changes that this processor will see.
154 syncer::ModelType expected_type_;
155
156 DISALLOW_COPY_AND_ASSIGN(StatefulChangeProcessor);
157};
158
treib65f103042015-12-03 10:21:36159} // namespace
160
treib9afc6212015-10-30 18:49:58161class ExtensionServiceSyncTest
162 : public extensions::ExtensionServiceTestWithInstall {
163 public:
164 void MockSyncStartFlare(bool* was_called,
165 syncer::ModelType* model_type_passed_in,
166 syncer::ModelType model_type) {
167 *was_called = true;
168 *model_type_passed_in = model_type;
169 }
170
asargente48ab752016-03-12 00:59:20171 // Helper to call MergeDataAndStartSyncing with no server data and dummy
172 // change processor / error factory.
173 void StartSyncing(syncer::ModelType type) {
174 ASSERT_TRUE(type == syncer::EXTENSIONS || type == syncer::APPS);
175 extension_sync_service()->MergeDataAndStartSyncing(
176 type, syncer::SyncDataList(),
177 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
178 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
179 }
180
treib9afc6212015-10-30 18:49:58181 protected:
182 // Paths to some of the fake extensions.
183 base::FilePath good0_path() {
184 return data_dir()
185 .AppendASCII("good")
186 .AppendASCII("Extensions")
187 .AppendASCII(good0)
188 .AppendASCII("1.0.0.0");
189 }
190
191 ExtensionSyncService* extension_sync_service() {
192 return ExtensionSyncService::Get(profile());
193 }
194};
195
196TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledComponent) {
197 InitializeEmptyExtensionService();
198
199 bool flare_was_called = false;
200 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
201 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
202 extension_sync_service()->SetSyncStartFlareForTesting(
203 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
204 factory.GetWeakPtr(),
205 &flare_was_called, // Safe due to WeakPtrFactory scope.
206 &triggered_type)); // Safe due to WeakPtrFactory scope.
207
208 // Install a component extension.
209 std::string manifest;
210 ASSERT_TRUE(base::ReadFileToString(
211 good0_path().Append(extensions::kManifestFilename), &manifest));
212 service()->component_loader()->Add(manifest, good0_path());
213 ASSERT_FALSE(service()->is_ready());
214 service()->Init();
215 ASSERT_TRUE(service()->is_ready());
216
217 // Extensions added before service is_ready() don't trigger sync startup.
218 EXPECT_FALSE(flare_was_called);
219 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
220}
221
222TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledNormal) {
223 InitializeGoodInstalledExtensionService();
224
225 bool flare_was_called = false;
226 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
227 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
228 extension_sync_service()->SetSyncStartFlareForTesting(
229 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
230 factory.GetWeakPtr(),
231 &flare_was_called, // Safe due to WeakPtrFactory scope.
232 &triggered_type)); // Safe due to WeakPtrFactory scope.
233
234 ASSERT_FALSE(service()->is_ready());
235 service()->Init();
236 ASSERT_EQ(3u, loaded_.size());
237 ASSERT_TRUE(service()->is_ready());
238
239 // Extensions added before service is_ready() don't trigger sync startup.
240 EXPECT_FALSE(flare_was_called);
241 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
242}
243
244TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupOnInstall) {
245 InitializeEmptyExtensionService();
246 service()->Init();
247 ASSERT_TRUE(service()->is_ready());
248
249 bool flare_was_called = false;
250 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
251 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
252 extension_sync_service()->SetSyncStartFlareForTesting(
253 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
254 factory.GetWeakPtr(),
255 &flare_was_called, // Safe due to WeakPtrFactory scope.
256 &triggered_type)); // Safe due to WeakPtrFactory scope.
257
258 base::FilePath path = data_dir().AppendASCII("good.crx");
259 InstallCRX(path, INSTALL_NEW);
260
261 EXPECT_TRUE(flare_was_called);
262 EXPECT_EQ(syncer::EXTENSIONS, triggered_type);
263
264 // Reset.
265 flare_was_called = false;
266 triggered_type = syncer::UNSPECIFIED;
267
268 // Once sync starts, flare should no longer be invoked.
269 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36270 syncer::EXTENSIONS, syncer::SyncDataList(),
271 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
272 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58273 path = data_dir().AppendASCII("page_action.crx");
274 InstallCRX(path, INSTALL_NEW);
275 EXPECT_FALSE(flare_was_called);
276 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
277}
278
279TEST_F(ExtensionServiceSyncTest, DisableExtensionFromSync) {
280 // Start the extensions service with one external extension already installed.
281 base::FilePath source_install_dir =
282 data_dir().AppendASCII("good").AppendASCII("Extensions");
283 base::FilePath pref_path =
284 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
285
286 InitializeInstalledExtensionService(pref_path, source_install_dir);
287
288 // The user has enabled sync.
289 ProfileSyncService* sync_service =
290 ProfileSyncServiceFactory::GetForProfile(profile());
maxboguefe00952a2016-01-19 19:02:01291 sync_service->SetFirstSetupComplete();
treib9afc6212015-10-30 18:49:58292
293 service()->Init();
294 ASSERT_TRUE(service()->is_ready());
295
296 ASSERT_EQ(3u, loaded_.size());
297
298 // We start enabled.
299 const Extension* extension = service()->GetExtensionById(good0, true);
300 ASSERT_TRUE(extension);
301 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
302
303 // Sync starts up.
304 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36305 syncer::EXTENSIONS, syncer::SyncDataList(),
306 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
307 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58308
309 // Then sync data arrives telling us to disable |good0|.
310 ExtensionSyncData disable_good_crx(*extension, false,
311 Extension::DISABLE_USER_ACTION, false,
312 false, ExtensionSyncData::BOOLEAN_UNSET);
treib65f103042015-12-03 10:21:36313 SyncChangeList list(
314 1, disable_good_crx.GetSyncChange(SyncChange::ACTION_UPDATE));
treib9afc6212015-10-30 18:49:58315 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
316
317 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
318}
319
320TEST_F(ExtensionServiceSyncTest, IgnoreSyncChangesWhenLocalStateIsMoreRecent) {
321 // Start the extension service with three extensions already installed.
322 base::FilePath source_install_dir =
323 data_dir().AppendASCII("good").AppendASCII("Extensions");
324 base::FilePath pref_path =
325 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
326
327 InitializeInstalledExtensionService(pref_path, source_install_dir);
328
329 // The user has enabled sync.
330 ProfileSyncService* sync_service =
331 ProfileSyncServiceFactory::GetForProfile(profile());
maxboguefe00952a2016-01-19 19:02:01332 sync_service->SetFirstSetupComplete();
treib9afc6212015-10-30 18:49:58333 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
334 extension_sync_service();
335
336 service()->Init();
337 ASSERT_TRUE(service()->is_ready());
338 ASSERT_EQ(3u, loaded_.size());
339
340 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
341 ASSERT_TRUE(service()->IsExtensionEnabled(good2));
342
343 // Disable and re-enable good0 before first sync data arrives.
344 service()->DisableExtension(good0, Extension::DISABLE_USER_ACTION);
345 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
346 service()->EnableExtension(good0);
347 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
348 // Disable good2 before first sync data arrives (good1 is considered
349 // non-syncable because it has plugin permission).
350 service()->DisableExtension(good2, Extension::DISABLE_USER_ACTION);
351 ASSERT_FALSE(service()->IsExtensionEnabled(good2));
352
353 const Extension* extension0 = service()->GetExtensionById(good0, true);
354 const Extension* extension2 = service()->GetExtensionById(good2, true);
355 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension0));
356 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension2));
357
358 // Now sync data comes in that says to disable good0 and enable good2.
359 ExtensionSyncData disable_good0(*extension0, false,
360 Extension::DISABLE_USER_ACTION, false, false,
361 ExtensionSyncData::BOOLEAN_UNSET);
362 ExtensionSyncData enable_good2(*extension2, true, Extension::DISABLE_NONE,
363 false, false,
364 ExtensionSyncData::BOOLEAN_UNSET);
365 syncer::SyncDataList sync_data;
366 sync_data.push_back(disable_good0.GetSyncData());
367 sync_data.push_back(enable_good2.GetSyncData());
368 extension_sync_service()->MergeDataAndStartSyncing(
369 syncer::EXTENSIONS,
370 sync_data,
treib65f103042015-12-03 10:21:36371 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
372 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58373
374 // Both sync changes should be ignored, since the local state was changed
375 // before sync started, and so the local state is considered more recent.
376 EXPECT_TRUE(service()->IsExtensionEnabled(good0));
377 EXPECT_FALSE(service()->IsExtensionEnabled(good2));
378}
379
treibb794dd52015-12-01 18:47:14380TEST_F(ExtensionServiceSyncTest, DontSelfNotify) {
381 // Start the extension service with three extensions already installed.
382 base::FilePath source_install_dir =
383 data_dir().AppendASCII("good").AppendASCII("Extensions");
384 base::FilePath pref_path =
385 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
386
387 InitializeInstalledExtensionService(pref_path, source_install_dir);
388
389 // The user has enabled sync.
maxboguefe00952a2016-01-19 19:02:01390 ProfileSyncServiceFactory::GetForProfile(profile())->SetFirstSetupComplete();
treibb794dd52015-12-01 18:47:14391 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
392 extension_sync_service();
393
394 service()->Init();
395 ASSERT_TRUE(service()->is_ready());
396 ASSERT_EQ(3u, loaded_.size());
397 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
398
399 syncer::FakeSyncChangeProcessor* processor =
400 new syncer::FakeSyncChangeProcessor;
401 extension_sync_service()->MergeDataAndStartSyncing(
402 syncer::EXTENSIONS,
403 syncer::SyncDataList(),
404 make_scoped_ptr(processor),
treib65f103042015-12-03 10:21:36405 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treibb794dd52015-12-01 18:47:14406
407 processor->changes().clear();
408
409 // Simulate various incoming sync changes, and make sure they don't result in
410 // any outgoing changes.
411
412 {
413 const Extension* extension = service()->GetExtensionById(good0, true);
414 ASSERT_TRUE(extension);
415
416 // Disable the extension.
417 ExtensionSyncData data(*extension, false, Extension::DISABLE_USER_ACTION,
418 false, false, ExtensionSyncData::BOOLEAN_UNSET);
treib65f103042015-12-03 10:21:36419 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14420
421 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
422
423 EXPECT_TRUE(processor->changes().empty());
424 }
425
426 {
427 const Extension* extension = service()->GetExtensionById(good0, true);
428 ASSERT_TRUE(extension);
429
430 // Set incognito enabled to true.
431 ExtensionSyncData data(*extension, false, Extension::DISABLE_NONE, true,
432 false, ExtensionSyncData::BOOLEAN_UNSET);
treib65f103042015-12-03 10:21:36433 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14434
435 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
436
437 EXPECT_TRUE(processor->changes().empty());
438 }
439
440 {
441 const Extension* extension = service()->GetExtensionById(good0, true);
442 ASSERT_TRUE(extension);
443
444 // Add another disable reason.
445 ExtensionSyncData data(*extension, false,
446 Extension::DISABLE_USER_ACTION |
447 Extension::DISABLE_PERMISSIONS_INCREASE,
448 false, false, ExtensionSyncData::BOOLEAN_UNSET);
treib65f103042015-12-03 10:21:36449 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14450
451 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
452
453 EXPECT_TRUE(processor->changes().empty());
454 }
455
456 {
457 const Extension* extension = service()->GetExtensionById(good0, true);
458 ASSERT_TRUE(extension);
459
460 // Uninstall the extension.
461 ExtensionSyncData data(*extension, false,
462 Extension::DISABLE_USER_ACTION |
463 Extension::DISABLE_PERMISSIONS_INCREASE,
464 false, false, ExtensionSyncData::BOOLEAN_UNSET);
treib65f103042015-12-03 10:21:36465 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_DELETE));
treibb794dd52015-12-01 18:47:14466
467 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
468
469 EXPECT_TRUE(processor->changes().empty());
470 }
471}
472
treib9afc6212015-10-30 18:49:58473TEST_F(ExtensionServiceSyncTest, GetSyncData) {
474 InitializeEmptyExtensionService();
475 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
476 const Extension* extension = service()->GetInstalledExtension(good_crx);
477 ASSERT_TRUE(extension);
478
479 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36480 syncer::EXTENSIONS, syncer::SyncDataList(),
481 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
482 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58483
484 syncer::SyncDataList list =
485 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
486 ASSERT_EQ(list.size(), 1U);
487 scoped_ptr<ExtensionSyncData> data =
488 ExtensionSyncData::CreateFromSyncData(list[0]);
489 ASSERT_TRUE(data.get());
490 EXPECT_EQ(extension->id(), data->id());
491 EXPECT_FALSE(data->uninstalled());
492 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
493 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
494 data->incognito_enabled());
495 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
robpercivaldcd8b102016-01-25 19:39:00496 EXPECT_EQ(data->version(), *extension->version());
treib9afc6212015-10-30 18:49:58497 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
498 data->update_url());
499 EXPECT_EQ(extension->name(), data->name());
500}
501
treib29e1b9b12015-11-11 08:50:56502TEST_F(ExtensionServiceSyncTest, GetSyncDataDisableReasons) {
503 InitializeEmptyExtensionService();
504 const Extension* extension =
505 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
506 ASSERT_TRUE(extension);
507
treib29e1b9b12015-11-11 08:50:56508 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36509 syncer::EXTENSIONS, syncer::SyncDataList(),
510 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
511 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib29e1b9b12015-11-11 08:50:56512
513 {
514 syncer::SyncDataList list =
515 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
516 ASSERT_EQ(list.size(), 1U);
517 scoped_ptr<ExtensionSyncData> data =
518 ExtensionSyncData::CreateFromSyncData(list[0]);
519 ASSERT_TRUE(data.get());
520 EXPECT_TRUE(data->enabled());
521 EXPECT_TRUE(data->supports_disable_reasons());
522 EXPECT_EQ(Extension::DISABLE_NONE, data->disable_reasons());
523 }
524
525 // Syncable disable reason, should propagate to sync.
526 service()->DisableExtension(good_crx, Extension::DISABLE_USER_ACTION);
527 {
528 syncer::SyncDataList list =
529 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
530 ASSERT_EQ(list.size(), 1U);
531 scoped_ptr<ExtensionSyncData> data =
532 ExtensionSyncData::CreateFromSyncData(list[0]);
533 ASSERT_TRUE(data.get());
534 EXPECT_FALSE(data->enabled());
535 EXPECT_TRUE(data->supports_disable_reasons());
536 EXPECT_EQ(Extension::DISABLE_USER_ACTION, data->disable_reasons());
537 }
538 service()->EnableExtension(good_crx);
539
540 // Non-syncable disable reason. The sync data should still say "enabled".
541 service()->DisableExtension(good_crx, Extension::DISABLE_RELOAD);
542 {
543 syncer::SyncDataList list =
544 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
545 ASSERT_EQ(list.size(), 1U);
546 scoped_ptr<ExtensionSyncData> data =
547 ExtensionSyncData::CreateFromSyncData(list[0]);
548 ASSERT_TRUE(data.get());
549 EXPECT_TRUE(data->enabled());
550 EXPECT_TRUE(data->supports_disable_reasons());
551 EXPECT_EQ(Extension::DISABLE_NONE, data->disable_reasons());
552 }
553 service()->EnableExtension(good_crx);
554
555 // Both a syncable and a non-syncable disable reason, only the former should
556 // propagate to sync.
557 service()->DisableExtension(
558 good_crx, Extension::DISABLE_USER_ACTION | Extension::DISABLE_RELOAD);
559 {
560 syncer::SyncDataList list =
561 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
562 ASSERT_EQ(list.size(), 1U);
563 scoped_ptr<ExtensionSyncData> data =
564 ExtensionSyncData::CreateFromSyncData(list[0]);
565 ASSERT_TRUE(data.get());
566 EXPECT_FALSE(data->enabled());
567 EXPECT_TRUE(data->supports_disable_reasons());
568 EXPECT_EQ(Extension::DISABLE_USER_ACTION, data->disable_reasons());
569 }
570 service()->EnableExtension(good_crx);
571}
572
treib9afc6212015-10-30 18:49:58573TEST_F(ExtensionServiceSyncTest, GetSyncDataTerminated) {
574 InitializeEmptyExtensionService();
575 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
576 TerminateExtension(good_crx);
577 const Extension* extension = service()->GetInstalledExtension(good_crx);
578 ASSERT_TRUE(extension);
579
treib9afc6212015-10-30 18:49:58580 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36581 syncer::EXTENSIONS, syncer::SyncDataList(),
582 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
583 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58584
585 syncer::SyncDataList list =
586 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
587 ASSERT_EQ(list.size(), 1U);
588 scoped_ptr<ExtensionSyncData> data =
589 ExtensionSyncData::CreateFromSyncData(list[0]);
590 ASSERT_TRUE(data.get());
591 EXPECT_EQ(extension->id(), data->id());
592 EXPECT_FALSE(data->uninstalled());
593 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
594 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
595 data->incognito_enabled());
596 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
robpercivaldcd8b102016-01-25 19:39:00597 EXPECT_EQ(data->version(), *extension->version());
treib9afc6212015-10-30 18:49:58598 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
599 data->update_url());
600 EXPECT_EQ(extension->name(), data->name());
601}
602
603TEST_F(ExtensionServiceSyncTest, GetSyncDataFilter) {
604 InitializeEmptyExtensionService();
605 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
606 const Extension* extension = service()->GetInstalledExtension(good_crx);
607 ASSERT_TRUE(extension);
608
treib9afc6212015-10-30 18:49:58609 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36610 syncer::APPS, syncer::SyncDataList(),
611 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
612 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58613
614 syncer::SyncDataList list =
615 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
616 ASSERT_EQ(list.size(), 0U);
617}
618
619TEST_F(ExtensionServiceSyncTest, GetSyncExtensionDataUserSettings) {
620 InitializeEmptyExtensionService();
621 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
622 const Extension* extension = service()->GetInstalledExtension(good_crx);
623 ASSERT_TRUE(extension);
624
treib9afc6212015-10-30 18:49:58625 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36626 syncer::EXTENSIONS, syncer::SyncDataList(),
627 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
628 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58629
630 {
631 syncer::SyncDataList list =
632 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
633 ASSERT_EQ(list.size(), 1U);
634 scoped_ptr<ExtensionSyncData> data =
635 ExtensionSyncData::CreateFromSyncData(list[0]);
636 ASSERT_TRUE(data.get());
637 EXPECT_TRUE(data->enabled());
638 EXPECT_FALSE(data->incognito_enabled());
639 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
640 }
641
642 service()->DisableExtension(good_crx, Extension::DISABLE_USER_ACTION);
643 {
644 syncer::SyncDataList list =
645 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
646 ASSERT_EQ(list.size(), 1U);
647 scoped_ptr<ExtensionSyncData> data =
648 ExtensionSyncData::CreateFromSyncData(list[0]);
649 ASSERT_TRUE(data.get());
650 EXPECT_FALSE(data->enabled());
651 EXPECT_FALSE(data->incognito_enabled());
652 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
653 }
654
655 extensions::util::SetIsIncognitoEnabled(good_crx, profile(), true);
656 extensions::util::SetAllowedScriptingOnAllUrls(
657 good_crx, profile(), false);
658 {
659 syncer::SyncDataList list =
660 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
661 ASSERT_EQ(list.size(), 1U);
662 scoped_ptr<ExtensionSyncData> data =
663 ExtensionSyncData::CreateFromSyncData(list[0]);
664 ASSERT_TRUE(data.get());
665 EXPECT_FALSE(data->enabled());
666 EXPECT_TRUE(data->incognito_enabled());
667 EXPECT_EQ(ExtensionSyncData::BOOLEAN_FALSE, data->all_urls_enabled());
668 }
669
670 service()->EnableExtension(good_crx);
671 extensions::util::SetAllowedScriptingOnAllUrls(
672 good_crx, profile(), true);
673 {
674 syncer::SyncDataList list =
675 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
676 ASSERT_EQ(list.size(), 1U);
677 scoped_ptr<ExtensionSyncData> data =
678 ExtensionSyncData::CreateFromSyncData(list[0]);
679 ASSERT_TRUE(data.get());
680 EXPECT_TRUE(data->enabled());
681 EXPECT_TRUE(data->incognito_enabled());
682 EXPECT_EQ(ExtensionSyncData::BOOLEAN_TRUE, data->all_urls_enabled());
683 }
684}
685
686TEST_F(ExtensionServiceSyncTest, SyncForUninstalledExternalExtension) {
687 InitializeEmptyExtensionService();
688 InstallCRXWithLocation(
689 data_dir().AppendASCII("good.crx"), Manifest::EXTERNAL_PREF, INSTALL_NEW);
690 const Extension* extension = service()->GetInstalledExtension(good_crx);
691 ASSERT_TRUE(extension);
692
treib9afc6212015-10-30 18:49:58693 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36694 syncer::EXTENSIONS, syncer::SyncDataList(),
695 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
696 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:20697 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:58698
699 UninstallExtension(good_crx, false);
700 EXPECT_TRUE(
701 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
702
703 sync_pb::EntitySpecifics specifics;
704 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
705 sync_pb::ExtensionSpecifics* extension_specifics =
706 app_specifics->mutable_extension();
707 extension_specifics->set_id(good_crx);
708 extension_specifics->set_version("1.0");
709 extension_specifics->set_enabled(true);
710
treib65f103042015-12-03 10:21:36711 SyncChangeList list =
712 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:58713
714 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
715 EXPECT_TRUE(
716 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
717}
718
719TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettings) {
720 InitializeEmptyExtensionService();
721 const Extension* app =
722 PackAndInstallCRX(data_dir().AppendASCII("app"), INSTALL_NEW);
723 ASSERT_TRUE(app);
724 ASSERT_TRUE(app->is_app());
725
treib9afc6212015-10-30 18:49:58726 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36727 syncer::APPS, syncer::SyncDataList(),
728 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
729 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58730
731 syncer::StringOrdinal initial_ordinal =
732 syncer::StringOrdinal::CreateInitialOrdinal();
733 {
734 syncer::SyncDataList list =
735 extension_sync_service()->GetAllSyncData(syncer::APPS);
736 ASSERT_EQ(list.size(), 1U);
737
738 scoped_ptr<ExtensionSyncData> app_sync_data =
739 ExtensionSyncData::CreateFromSyncData(list[0]);
740 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->app_launch_ordinal()));
741 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
742 }
743
deepak.m14ba69e62015-11-17 05:42:12744 AppSorting* sorting = ExtensionSystem::Get(profile())->app_sorting();
treib9afc6212015-10-30 18:49:58745 sorting->SetAppLaunchOrdinal(app->id(), initial_ordinal.CreateAfter());
746 {
747 syncer::SyncDataList list =
748 extension_sync_service()->GetAllSyncData(syncer::APPS);
749 ASSERT_EQ(list.size(), 1U);
750
751 scoped_ptr<ExtensionSyncData> app_sync_data =
752 ExtensionSyncData::CreateFromSyncData(list[0]);
753 ASSERT_TRUE(app_sync_data.get());
754 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
755 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
756 }
757
758 sorting->SetPageOrdinal(app->id(), initial_ordinal.CreateAfter());
759 {
760 syncer::SyncDataList list =
761 extension_sync_service()->GetAllSyncData(syncer::APPS);
762 ASSERT_EQ(list.size(), 1U);
763
764 scoped_ptr<ExtensionSyncData> app_sync_data =
765 ExtensionSyncData::CreateFromSyncData(list[0]);
766 ASSERT_TRUE(app_sync_data.get());
767 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
768 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->page_ordinal()));
769 }
770}
771
772// TODO (rdevlin.cronin): The OnExtensionMoved() method has been removed from
773// ExtensionService, so this test probably needs a new home. Unfortunately, it
774// relies pretty heavily on things like InitializeExtension[Sync]Service() and
775// PackAndInstallCRX(). When we clean up a bit more, this should move out.
776TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettingsOnExtensionMoved) {
777 InitializeEmptyExtensionService();
778 const size_t kAppCount = 3;
779 const Extension* apps[kAppCount];
780 apps[0] = PackAndInstallCRX(data_dir().AppendASCII("app1"), INSTALL_NEW);
781 apps[1] = PackAndInstallCRX(data_dir().AppendASCII("app2"), INSTALL_NEW);
782 apps[2] = PackAndInstallCRX(data_dir().AppendASCII("app4"), INSTALL_NEW);
783 for (size_t i = 0; i < kAppCount; ++i) {
784 ASSERT_TRUE(apps[i]);
785 ASSERT_TRUE(apps[i]->is_app());
786 }
787
treib9afc6212015-10-30 18:49:58788 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36789 syncer::APPS, syncer::SyncDataList(),
790 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
791 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58792
deepak.m14ba69e62015-11-17 05:42:12793 ExtensionSystem::Get(service()->GetBrowserContext())
treib9afc6212015-10-30 18:49:58794 ->app_sorting()
795 ->OnExtensionMoved(apps[0]->id(), apps[1]->id(), apps[2]->id());
796 {
797 syncer::SyncDataList list =
798 extension_sync_service()->GetAllSyncData(syncer::APPS);
799 ASSERT_EQ(list.size(), 3U);
800
801 scoped_ptr<ExtensionSyncData> data[kAppCount];
802 for (size_t i = 0; i < kAppCount; ++i) {
803 data[i] = ExtensionSyncData::CreateFromSyncData(list[i]);
804 ASSERT_TRUE(data[i].get());
805 }
806
807 // The sync data is not always in the same order our apps were installed in,
808 // so we do that sorting here so we can make sure the values are changed as
809 // expected.
810 syncer::StringOrdinal app_launch_ordinals[kAppCount];
811 for (size_t i = 0; i < kAppCount; ++i) {
812 for (size_t j = 0; j < kAppCount; ++j) {
813 if (apps[i]->id() == data[j]->id())
814 app_launch_ordinals[i] = data[j]->app_launch_ordinal();
815 }
816 }
817
818 EXPECT_TRUE(app_launch_ordinals[1].LessThan(app_launch_ordinals[0]));
819 EXPECT_TRUE(app_launch_ordinals[0].LessThan(app_launch_ordinals[2]));
820 }
821}
822
823TEST_F(ExtensionServiceSyncTest, GetSyncDataList) {
824 InitializeEmptyExtensionService();
825 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
826 InstallCRX(data_dir().AppendASCII("page_action.crx"), INSTALL_NEW);
827 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
828 InstallCRX(data_dir().AppendASCII("theme2.crx"), INSTALL_NEW);
829
treib9afc6212015-10-30 18:49:58830 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36831 syncer::APPS, syncer::SyncDataList(),
832 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
833 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58834 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36835 syncer::EXTENSIONS, syncer::SyncDataList(),
836 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
837 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58838
839 service()->DisableExtension(page_action, Extension::DISABLE_USER_ACTION);
840 TerminateExtension(theme2_crx);
841
842 EXPECT_EQ(0u, extension_sync_service()->GetAllSyncData(syncer::APPS).size());
843 EXPECT_EQ(
844 2u, extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS).size());
845}
846
847TEST_F(ExtensionServiceSyncTest, ProcessSyncDataUninstall) {
848 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:58849 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36850 syncer::EXTENSIONS, syncer::SyncDataList(),
851 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
852 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58853
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("1.0");
treib65f103042015-12-03 10:21:36858
859 SyncChangeList list =
860 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:58861
862 // Should do nothing.
863 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
864 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
865
866 // Install the extension.
867 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
868 InstallCRX(extension_path, INSTALL_NEW);
869 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
870
871 // Should uninstall the extension.
872 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
873 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
874
875 // Should again do nothing.
876 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
877 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
878}
879
880TEST_F(ExtensionServiceSyncTest, ProcessSyncDataWrongType) {
881 InitializeEmptyExtensionService();
asargente48ab752016-03-12 00:59:20882 StartSyncing(syncer::EXTENSIONS);
883 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:58884
885 // Install the extension.
886 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
887 InstallCRX(extension_path, INSTALL_NEW);
888 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
889
890 sync_pb::EntitySpecifics specifics;
891 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
892 sync_pb::ExtensionSpecifics* extension_specifics =
893 app_specifics->mutable_extension();
894 extension_specifics->set_id(good_crx);
895 extension_specifics->set_version(
896 service()->GetInstalledExtension(good_crx)->version()->GetString());
897
898 {
899 extension_specifics->set_enabled(true);
treib65f103042015-12-03 10:21:36900
901 SyncChangeList list =
902 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:58903
904 // Should do nothing
905 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
906 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
907 }
908
909 {
910 extension_specifics->set_enabled(false);
treib65f103042015-12-03 10:21:36911
912 SyncChangeList list =
913 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:58914
915 // Should again do nothing.
916 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
917 EXPECT_TRUE(service()->GetExtensionById(good_crx, false));
918 }
919}
920
921TEST_F(ExtensionServiceSyncTest, ProcessSyncDataSettings) {
922 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:58923 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36924 syncer::EXTENSIONS, syncer::SyncDataList(),
925 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
926 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58927
928 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
929 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
930 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
931 EXPECT_FALSE(extensions::util::HasSetAllowedScriptingOnAllUrls(
932 good_crx, profile()));
933 const bool kDefaultAllowedScripting =
934 extensions::util::DefaultAllowedScriptingOnAllUrls();
935 EXPECT_EQ(kDefaultAllowedScripting,
936 extensions::util::AllowedScriptingOnAllUrls(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_version(
942 service()->GetInstalledExtension(good_crx)->version()->GetString());
943 ext_specifics->set_enabled(false);
944
945 {
treib65f103042015-12-03 10:21:36946 SyncChangeList list =
947 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
948
treib9afc6212015-10-30 18:49:58949 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
950 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
951 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
952 EXPECT_FALSE(extensions::util::HasSetAllowedScriptingOnAllUrls(
953 good_crx, profile()));
954 EXPECT_EQ(kDefaultAllowedScripting,
955 extensions::util::AllowedScriptingOnAllUrls(good_crx, profile()));
956 }
957
958 {
959 ext_specifics->set_enabled(true);
960 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:36961
962 SyncChangeList list =
963 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
964
treib9afc6212015-10-30 18:49:58965 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
966 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
967 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
968 }
969
970 {
971 ext_specifics->set_enabled(false);
972 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:36973
974 SyncChangeList list =
975 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
976
treib9afc6212015-10-30 18:49:58977 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
978 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
979 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
980 }
981
982 {
983 ext_specifics->set_enabled(true);
984 ext_specifics->set_all_urls_enabled(!kDefaultAllowedScripting);
treib65f103042015-12-03 10:21:36985
986 SyncChangeList list =
987 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
988
treib9afc6212015-10-30 18:49:58989 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
990 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
991 EXPECT_TRUE(extensions::util::HasSetAllowedScriptingOnAllUrls(
992 good_crx, profile()));
993 EXPECT_EQ(!kDefaultAllowedScripting,
994 extensions::util::AllowedScriptingOnAllUrls(good_crx, profile()));
995 }
996
997 {
998 ext_specifics->set_all_urls_enabled(kDefaultAllowedScripting);
treib65f103042015-12-03 10:21:36999
1000 SyncChangeList list =
1001 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1002
treib9afc6212015-10-30 18:49:581003 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1004 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1005 EXPECT_TRUE(extensions::util::HasSetAllowedScriptingOnAllUrls(
1006 good_crx, profile()));
1007 EXPECT_EQ(kDefaultAllowedScripting,
1008 extensions::util::AllowedScriptingOnAllUrls(good_crx, profile()));
1009 }
1010
1011 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1012}
1013
1014TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNewExtension) {
1015 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581016 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361017 syncer::EXTENSIONS, syncer::SyncDataList(),
1018 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
1019 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:581020
1021 const base::FilePath path = data_dir().AppendASCII("good.crx");
1022 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1023
1024 struct TestCase {
1025 const char* name; // For failure output only.
1026 bool sync_enabled; // The "enabled" flag coming in from Sync.
1027 // The disable reason(s) coming in from Sync, or -1 for "not set".
1028 int sync_disable_reasons;
1029 // The disable reason(s) that should be set on the installed extension.
1030 // This will usually be the same as |sync_disable_reasons|, but see the
1031 // "Legacy" case.
1032 int expect_disable_reasons;
1033 // Whether the extension's permissions should be auto-granted during
1034 // installation.
1035 bool expect_permissions_granted;
1036 } test_cases[] = {
1037 // Standard case: Extension comes in enabled; permissions should be granted
1038 // during installation.
1039 { "Standard", true, 0, 0, true },
1040 // If the extension comes in disabled, its permissions should still be
1041 // granted (the user already approved them on another machine).
1042 { "Disabled", false, Extension::DISABLE_USER_ACTION,
1043 Extension::DISABLE_USER_ACTION, true },
1044 // Legacy case (<M45): No disable reasons come in from Sync (see
1045 // crbug.com/484214). After installation, the reason should be set to
treib3b91e9f2015-11-04 11:29:411046 // DISABLE_USER_ACTION (default assumption).
1047 { "Legacy", false, -1, Extension::DISABLE_USER_ACTION, true },
treib9afc6212015-10-30 18:49:581048 // If the extension came in disabled due to a permissions increase, then the
1049 // user has *not* approved the permissions, and they shouldn't be granted.
1050 // crbug.com/484214
1051 { "PermissionsIncrease", false, Extension::DISABLE_PERMISSIONS_INCREASE,
1052 Extension::DISABLE_PERMISSIONS_INCREASE, false },
1053 };
1054
1055 for (const TestCase& test_case : test_cases) {
1056 SCOPED_TRACE(test_case.name);
1057
1058 sync_pb::EntitySpecifics specifics;
1059 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1060 ext_specifics->set_id(good_crx);
1061 ext_specifics->set_version(base::Version("1").GetString());
1062 ext_specifics->set_enabled(test_case.sync_enabled);
1063 if (test_case.sync_disable_reasons != -1)
1064 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1065
treib65f103042015-12-03 10:21:361066 SyncChangeList list =
1067 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1068
treib9afc6212015-10-30 18:49:581069 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1070
1071 ASSERT_TRUE(service()->pending_extension_manager()->IsIdPending(good_crx));
1072 UpdateExtension(good_crx, path, test_case.sync_enabled ? ENABLED
1073 : DISABLED);
1074 EXPECT_EQ(test_case.expect_disable_reasons,
1075 prefs->GetDisableReasons(good_crx));
1076 scoped_ptr<const PermissionSet> permissions =
1077 prefs->GetGrantedPermissions(good_crx);
1078 EXPECT_EQ(test_case.expect_permissions_granted, !permissions->IsEmpty());
1079 ASSERT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1080
1081 // Remove the extension again, so we can install it again for the next case.
1082 UninstallExtension(good_crx, false,
1083 test_case.sync_enabled ? Extension::ENABLED
1084 : Extension::DISABLED);
1085 }
1086}
1087
1088TEST_F(ExtensionServiceSyncTest, ProcessSyncDataTerminatedExtension) {
1089 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581090 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361091 syncer::EXTENSIONS, syncer::SyncDataList(),
1092 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
1093 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:581094
1095 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1096 TerminateExtension(good_crx);
1097 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1098 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1099
1100 sync_pb::EntitySpecifics specifics;
1101 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1102 ext_specifics->set_id(good_crx);
1103 ext_specifics->set_version(
1104 service()->GetInstalledExtension(good_crx)->version()->GetString());
1105 ext_specifics->set_enabled(false);
1106 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361107
1108 SyncChangeList list =
1109 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581110
1111 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1112 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1113 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1114
1115 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1116}
1117
1118TEST_F(ExtensionServiceSyncTest, ProcessSyncDataVersionCheck) {
1119 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581120 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361121 syncer::EXTENSIONS, syncer::SyncDataList(),
1122 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
1123 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:581124
1125 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1126 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1127 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1128
1129 sync_pb::EntitySpecifics specifics;
1130 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1131 ext_specifics->set_id(good_crx);
1132 ext_specifics->set_enabled(true);
1133
1134 const base::Version installed_version =
1135 *service()->GetInstalledExtension(good_crx)->version();
1136
1137 {
1138 ext_specifics->set_version(installed_version.GetString());
treib65f103042015-12-03 10:21:361139
1140 SyncChangeList list =
1141 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581142
1143 // Should do nothing if extension version == sync version.
1144 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1145 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1146 // Make sure the version we'll send back to sync didn't change.
1147 syncer::SyncDataList data =
1148 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1149 ASSERT_EQ(1u, data.size());
1150 scoped_ptr<ExtensionSyncData> extension_data =
1151 ExtensionSyncData::CreateFromSyncData(data[0]);
1152 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001153 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581154 }
1155
1156 // Should do nothing if extension version > sync version.
1157 {
1158 ext_specifics->set_version("0.0.0.0");
treib65f103042015-12-03 10:21:361159
1160 SyncChangeList list =
1161 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581162
1163 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1164 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1165 // Make sure the version we'll send back to sync didn't change.
1166 syncer::SyncDataList data =
1167 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1168 ASSERT_EQ(1u, data.size());
1169 scoped_ptr<ExtensionSyncData> extension_data =
1170 ExtensionSyncData::CreateFromSyncData(data[0]);
1171 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001172 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581173 }
1174
1175 // Should kick off an update if extension version < sync version.
1176 {
1177 const base::Version new_version("9.9.9.9");
1178 ext_specifics->set_version(new_version.GetString());
treib65f103042015-12-03 10:21:361179
1180 SyncChangeList list =
1181 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581182
1183 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1184 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1185 // Make sure that we'll send the NEW version back to sync, even though we
1186 // haven't actually updated yet. This is to prevent the data in sync from
1187 // flip-flopping back and forth until all clients are up to date.
1188 syncer::SyncDataList data =
1189 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1190 ASSERT_EQ(1u, data.size());
1191 scoped_ptr<ExtensionSyncData> extension_data =
1192 ExtensionSyncData::CreateFromSyncData(data[0]);
1193 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001194 EXPECT_EQ(new_version, extension_data->version());
treib9afc6212015-10-30 18:49:581195 }
1196
1197 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1198}
1199
1200TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNotInstalled) {
1201 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581202 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361203 syncer::EXTENSIONS, syncer::SyncDataList(),
1204 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
1205 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:581206
1207 sync_pb::EntitySpecifics specifics;
1208 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1209 ext_specifics->set_id(good_crx);
1210 ext_specifics->set_enabled(false);
1211 ext_specifics->set_incognito_enabled(true);
1212 ext_specifics->set_update_url("http://www.google.com/");
1213 ext_specifics->set_version("1.2.3.4");
treib65f103042015-12-03 10:21:361214
1215 SyncChangeList list =
1216 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581217
1218 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1219 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1220 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1221 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1222 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1223 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1224
1225 const extensions::PendingExtensionInfo* info;
1226 EXPECT_TRUE(
1227 (info = service()->pending_extension_manager()->GetById(good_crx)));
1228 EXPECT_EQ(ext_specifics->update_url(), info->update_url().spec());
1229 EXPECT_TRUE(info->is_from_sync());
1230 EXPECT_EQ(Manifest::INTERNAL, info->install_source());
1231 // TODO(akalin): Figure out a way to test |info.ShouldAllowInstall()|.
1232}
1233
1234TEST_F(ExtensionServiceSyncTest, ProcessSyncDataEnableDisable) {
1235 InitializeEmptyExtensionService();
1236 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361237 syncer::EXTENSIONS, syncer::SyncDataList(),
1238 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
1239 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:581240
1241 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1242
1243 struct TestCase {
1244 const char* name; // For failure output only.
1245 // Set of disable reasons before any Sync data comes in. If this is != 0,
1246 // the extension is disabled.
1247 int previous_disable_reasons;
1248 bool sync_enable; // The enabled flag coming in from Sync.
1249 // The disable reason(s) coming in from Sync, or -1 for "not set".
1250 int sync_disable_reasons;
1251 // The expected set of disable reasons after processing the Sync update. The
1252 // extension should be disabled iff this is != 0.
1253 int expect_disable_reasons;
1254 } test_cases[] = {
1255 { "NopEnable", 0, true, 0, 0 },
1256 { "NopDisable", Extension::DISABLE_USER_ACTION, false,
1257 Extension::DISABLE_USER_ACTION, Extension::DISABLE_USER_ACTION },
treib29e1b9b12015-11-11 08:50:561258 { "Enable", Extension::DISABLE_USER_ACTION, true, 0, 0 },
treib9afc6212015-10-30 18:49:581259 { "Disable", 0, false, Extension::DISABLE_USER_ACTION,
1260 Extension::DISABLE_USER_ACTION },
treib9afc6212015-10-30 18:49:581261 { "AddDisableReason", Extension::DISABLE_REMOTE_INSTALL, false,
1262 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION,
1263 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION },
treib9afc6212015-10-30 18:49:581264 { "RemoveDisableReason",
1265 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION, false,
1266 Extension::DISABLE_USER_ACTION, Extension::DISABLE_USER_ACTION },
treib29e1b9b12015-11-11 08:50:561267 { "PreserveLocalDisableReason", Extension::DISABLE_RELOAD, true, 0,
1268 Extension::DISABLE_RELOAD },
1269 { "PreserveOnlyLocalDisableReason",
1270 Extension::DISABLE_USER_ACTION | Extension::DISABLE_RELOAD, true, 0,
1271 Extension::DISABLE_RELOAD },
1272
1273 // Interaction with Chrome clients <=M44, which don't sync disable_reasons
1274 // at all (any existing reasons are preserved).
1275 { "M44Enable", Extension::DISABLE_USER_ACTION, true, -1, 0 },
1276 // An M44 client enables an extension that had been disabled on a new
1277 // client. The disable reasons are still be there, but should be ignored.
1278 { "M44ReEnable", Extension::DISABLE_USER_ACTION, true,
1279 Extension::DISABLE_USER_ACTION, 0 },
1280 { "M44Disable", 0, false, -1, Extension::DISABLE_USER_ACTION },
1281 { "M44ReDisable", 0, false, 0, Extension::DISABLE_USER_ACTION },
1282 { "M44AlreadyDisabledByUser", Extension::DISABLE_USER_ACTION, false, -1,
1283 Extension::DISABLE_USER_ACTION},
1284 { "M44AlreadyDisabledWithOtherReason", Extension::DISABLE_REMOTE_INSTALL,
1285 false, -1,
1286 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION },
treib9afc6212015-10-30 18:49:581287 };
1288
1289 for (const TestCase& test_case : test_cases) {
1290 SCOPED_TRACE(test_case.name);
1291
1292 std::string id;
1293 std::string version;
1294 // Don't keep |extension| around longer than necessary.
1295 {
1296 const Extension* extension =
1297 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1298 // The extension should now be installed and enabled.
1299 ASSERT_TRUE(extension);
1300 id = extension->id();
1301 version = extension->VersionString();
1302 }
1303 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1304
1305 // Disable it if the test case says so.
1306 if (test_case.previous_disable_reasons) {
1307 service()->DisableExtension(id, test_case.previous_disable_reasons);
1308 ASSERT_TRUE(registry()->disabled_extensions().Contains(id));
1309 }
1310
1311 // Now a sync update comes in.
1312 sync_pb::EntitySpecifics specifics;
1313 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1314 ext_specifics->set_id(id);
1315 ext_specifics->set_enabled(test_case.sync_enable);
1316 ext_specifics->set_version(version);
1317 if (test_case.sync_disable_reasons != -1)
1318 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1319
treib65f103042015-12-03 10:21:361320 SyncChangeList list =
1321 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1322
treib9afc6212015-10-30 18:49:581323 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1324
1325 // Check expectations.
1326 const bool expect_enabled = !test_case.expect_disable_reasons;
1327 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1328 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
1329
1330 // Remove the extension again, so we can install it again for the next case.
1331 UninstallExtension(id, false, expect_enabled ? Extension::ENABLED
1332 : Extension::DISABLED);
1333 }
1334}
1335
1336TEST_F(ExtensionServiceSyncTest, ProcessSyncDataDeferredEnable) {
1337 InitializeEmptyExtensionService();
1338 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361339 syncer::EXTENSIONS, syncer::SyncDataList(),
1340 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
1341 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:581342
1343 base::FilePath base_path = data_dir().AppendASCII("permissions_increase");
1344 base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1345
1346 base::FilePath path = base_path.AppendASCII("v1");
1347 const Extension* extension = PackAndInstallCRX(path, pem_path, INSTALL_NEW);
1348 // The extension must now be installed and enabled.
1349 ASSERT_TRUE(extension);
1350 ASSERT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
1351
1352 // Save the id, as the extension object will be destroyed during updating.
1353 std::string id = extension->id();
1354
1355 // Update to a new version with increased permissions.
1356 path = base_path.AppendASCII("v2");
1357 PackCRXAndUpdateExtension(id, path, pem_path, DISABLED);
1358
1359 // Now a sync update comes in, telling us to re-enable a *newer* version.
1360 sync_pb::EntitySpecifics specifics;
1361 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1362 ext_specifics->set_id(id);
1363 ext_specifics->set_version("3");
1364 ext_specifics->set_enabled(true);
1365 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
1366
treib65f103042015-12-03 10:21:361367 SyncChangeList list =
1368 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1369
treib9afc6212015-10-30 18:49:581370 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1371
1372 // Since the version didn't match, the extension should still be disabled.
1373 EXPECT_TRUE(registry()->disabled_extensions().Contains(id));
1374
1375 // After we update to the matching version, the extension should get enabled.
1376 path = base_path.AppendASCII("v3");
1377 PackCRXAndUpdateExtension(id, path, pem_path, ENABLED);
1378}
1379
1380TEST_F(ExtensionServiceSyncTest, ProcessSyncDataPermissionApproval) {
1381 // This is the update URL specified in the test extension. Setting it here is
1382 // necessary to make it considered syncable.
1383 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1384 switches::kAppsGalleryUpdateURL,
1385 "http://localhost/autoupdate/updates.xml");
1386
1387 InitializeEmptyExtensionService();
1388 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361389 syncer::EXTENSIONS, syncer::SyncDataList(),
1390 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
1391 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:581392
1393 const base::FilePath base_path =
1394 data_dir().AppendASCII("permissions_increase");
1395 const base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1396 const base::FilePath path_v1 = base_path.AppendASCII("v1");
1397 const base::FilePath path_v2 = base_path.AppendASCII("v2");
1398
1399 base::ScopedTempDir crx_dir;
1400 ASSERT_TRUE(crx_dir.CreateUniqueTempDir());
1401 const base::FilePath crx_path_v1 = crx_dir.path().AppendASCII("temp1.crx");
1402 PackCRX(path_v1, pem_path, crx_path_v1);
1403 const base::FilePath crx_path_v2 = crx_dir.path().AppendASCII("temp2.crx");
1404 PackCRX(path_v2, pem_path, crx_path_v2);
1405
1406 const std::string v1("1");
1407 const std::string v2("2");
1408
1409 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1410
1411 struct TestCase {
1412 const char* name; // For failure output only.
1413 const std::string& sync_version; // The version coming in from Sync.
1414 // The disable reason(s) coming in from Sync, or -1 for "not set".
1415 int sync_disable_reasons;
1416 // The expected set of disable reasons after processing the Sync update. The
1417 // extension should be enabled iff this is 0.
1418 int expect_disable_reasons;
1419 // Whether the extension's permissions should be auto-granted.
1420 bool expect_permissions_granted;
1421 } test_cases[] = {
1422 // Sync tells us to re-enable an older version. No permissions should be
1423 // granted, since we can't be sure if the user actually approved the right
1424 // set of permissions.
1425 { "OldVersion", v1, 0, Extension::DISABLE_PERMISSIONS_INCREASE, false },
1426 // Legacy case: Sync tells us to re-enable the extension, but doesn't
1427 // specify disable reasons. No permissions should be granted.
1428 { "Legacy", v2, -1, Extension::DISABLE_PERMISSIONS_INCREASE, false },
1429 // Sync tells us to re-enable the extension and explicitly removes the
1430 // disable reasons. Now the extension should have its permissions granted.
1431 { "GrantPermissions", v2, 0, Extension::DISABLE_NONE, true },
1432 };
1433
1434 for (const TestCase& test_case : test_cases) {
1435 SCOPED_TRACE(test_case.name);
1436
1437 std::string id;
1438 // Don't keep |extension| around longer than necessary (it'll be destroyed
1439 // during updating).
1440 {
1441 const Extension* extension = InstallCRX(crx_path_v1, INSTALL_NEW);
1442 // The extension should now be installed and enabled.
1443 ASSERT_TRUE(extension);
1444 ASSERT_EQ(v1, extension->VersionString());
1445 id = extension->id();
1446 }
1447 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1448
1449 scoped_ptr<const PermissionSet> granted_permissions_v1 =
1450 prefs->GetGrantedPermissions(id);
1451
1452 // Update to a new version with increased permissions.
1453 UpdateExtension(id, crx_path_v2, DISABLED);
1454
1455 // Now the extension should be disabled due to a permissions increase.
1456 {
1457 const Extension* extension =
1458 registry()->disabled_extensions().GetByID(id);
1459 ASSERT_TRUE(extension);
1460 ASSERT_EQ(v2, extension->VersionString());
1461 }
1462 ASSERT_TRUE(prefs->HasDisableReason(
1463 id, Extension::DISABLE_PERMISSIONS_INCREASE));
1464
1465 // No new permissions should have been granted.
1466 scoped_ptr<const PermissionSet> granted_permissions_v2 =
1467 prefs->GetGrantedPermissions(id);
1468 ASSERT_EQ(*granted_permissions_v1, *granted_permissions_v2);
1469
1470 // Now a sync update comes in.
1471 sync_pb::EntitySpecifics specifics;
1472 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1473 ext_specifics->set_id(id);
1474 ext_specifics->set_enabled(true);
1475 ext_specifics->set_version(test_case.sync_version);
1476 if (test_case.sync_disable_reasons != -1)
1477 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1478
treib65f103042015-12-03 10:21:361479 SyncChangeList list =
1480 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1481
treib9afc6212015-10-30 18:49:581482 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1483
1484 // Check expectations.
1485 const bool expect_enabled = !test_case.expect_disable_reasons;
1486 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1487 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
1488 scoped_ptr<const PermissionSet> granted_permissions =
1489 prefs->GetGrantedPermissions(id);
1490 if (test_case.expect_permissions_granted) {
1491 scoped_ptr<const PermissionSet> active_permissions =
1492 prefs->GetActivePermissions(id);
1493 EXPECT_EQ(*granted_permissions, *active_permissions);
1494 } else {
1495 EXPECT_EQ(*granted_permissions, *granted_permissions_v1);
1496 }
1497
1498 // Remove the extension again, so we can install it again for the next case.
1499 UninstallExtension(id, false, expect_enabled ? Extension::ENABLED
1500 : Extension::DISABLED);
1501 }
1502}
1503
treib227b2582015-12-09 09:28:261504// Regression test for crbug.com/558299
1505TEST_F(ExtensionServiceSyncTest, DontSyncThemes) {
1506 InitializeEmptyExtensionService();
1507
1508 // The user has enabled sync.
maxboguefe00952a2016-01-19 19:02:011509 ProfileSyncServiceFactory::GetForProfile(profile())->SetFirstSetupComplete();
treib227b2582015-12-09 09:28:261510 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
1511 extension_sync_service();
1512
1513 service()->Init();
1514 ASSERT_TRUE(service()->is_ready());
1515
1516 syncer::FakeSyncChangeProcessor* processor =
1517 new syncer::FakeSyncChangeProcessor;
1518 extension_sync_service()->MergeDataAndStartSyncing(
1519 syncer::EXTENSIONS,
1520 syncer::SyncDataList(),
1521 make_scoped_ptr(processor),
1522 make_scoped_ptr(new syncer::SyncErrorFactoryMock));
1523
1524 processor->changes().clear();
1525
1526 // Sanity check: Installing an extension should result in a sync change.
1527 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1528 EXPECT_EQ(1u, processor->changes().size());
1529
1530 processor->changes().clear();
1531
1532 // Installing a theme should not result in a sync change (themes are handled
1533 // separately by ThemeSyncableService).
1534 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
1535 EXPECT_TRUE(processor->changes().empty());
1536}
1537
treib9afc6212015-10-30 18:49:581538#if defined(ENABLE_SUPERVISED_USERS)
1539
1540class ExtensionServiceTestSupervised : public ExtensionServiceSyncTest,
1541 public SupervisedUserService::Delegate {
1542 public:
treibb6af28cd2015-12-01 11:19:461543 ExtensionServiceTestSupervised()
1544 : field_trial_list_(new base::MockEntropyProvider()) {}
1545
treib9afc6212015-10-30 18:49:581546 void SetUp() override {
1547 ExtensionServiceSyncTest::SetUp();
1548
1549 // This is the update URL specified in the permissions test extension.
1550 // Setting it here is necessary to make the extension considered syncable.
1551 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1552 switches::kAppsGalleryUpdateURL,
1553 "http://localhost/autoupdate/updates.xml");
1554 }
1555
1556 void TearDown() override {
1557 supervised_user_service()->SetDelegate(nullptr);
1558
1559 ExtensionServiceSyncTest::TearDown();
1560 }
1561
1562 protected:
treibb6af28cd2015-12-01 11:19:461563 void InitNeedCustodianApprovalFieldTrial(bool enabled) {
1564 // Group name doesn't matter.
1565 base::FieldTrialList::CreateFieldTrial(
1566 "SupervisedUserExtensionPermissionIncrease", "group");
1567 std::map<std::string, std::string> params;
1568 params["legacy_supervised_user"] = enabled ? "true" : "false";
1569 params["child_account"] = enabled ? "true" : "false";
1570 variations::AssociateVariationParams(
1571 "SupervisedUserExtensionPermissionIncrease", "group", params);
1572 }
1573
treib9afc6212015-10-30 18:49:581574 void InitServices(bool profile_is_supervised) {
1575 ExtensionServiceInitParams params = CreateDefaultInitParams();
1576 params.profile_is_supervised = profile_is_supervised;
1577 InitializeExtensionService(params);
asargente48ab752016-03-12 00:59:201578 StartSyncing(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581579
1580 supervised_user_service()->SetDelegate(this);
1581 supervised_user_service()->Init();
1582 }
1583
1584 std::string InstallPermissionsTestExtension() {
1585 const std::string version("1");
1586
1587 const Extension* extension =
1588 PackAndInstallCRX(dir_path(version), pem_path(), INSTALL_NEW,
1589 Extension::WAS_INSTALLED_BY_CUSTODIAN);
1590 // The extension must now be installed and enabled.
1591 EXPECT_TRUE(extension);
1592 EXPECT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
1593 EXPECT_EQ(version, extension->VersionString());
1594
1595 return extension->id();
1596 }
1597
1598 void UpdatePermissionsTestExtension(const std::string& id,
1599 const std::string& version,
1600 UpdateState expected_state) {
1601 PackCRXAndUpdateExtension(id, dir_path(version), pem_path(),
1602 expected_state);
1603 const Extension* extension = registry()->GetInstalledExtension(id);
1604 ASSERT_TRUE(extension);
1605 // The version should have been updated.
1606 EXPECT_EQ(version, extension->VersionString());
1607 }
1608
1609 SupervisedUserService* supervised_user_service() {
1610 return SupervisedUserServiceFactory::GetForProfile(profile());
1611 }
1612
1613 static std::string UpdateRequestId(const std::string& extension_id,
1614 const std::string& version) {
1615 return SupervisedUserService::GetExtensionUpdateRequestId(
1616 extension_id, base::Version(version));
1617 }
1618
1619 private:
1620 // This prevents the legacy supervised user init code from running.
1621 bool SetActive(bool active) override { return true; }
1622
1623 base::FilePath base_path() const {
1624 return data_dir().AppendASCII("permissions_increase");
1625 }
1626 base::FilePath dir_path(const std::string& version) const {
1627 return base_path().AppendASCII("v" + version);
1628 }
1629 base::FilePath pem_path() const {
1630 return base_path().AppendASCII("permissions.pem");
1631 }
treibb6af28cd2015-12-01 11:19:461632
1633 base::FieldTrialList field_trial_list_;
treib9afc6212015-10-30 18:49:581634};
1635
1636class MockPermissionRequestCreator : public PermissionRequestCreator {
1637 public:
1638 MockPermissionRequestCreator() {}
1639 ~MockPermissionRequestCreator() override {}
1640
1641 bool IsEnabled() const override { return true; }
1642
1643 void CreateURLAccessRequest(const GURL& url_requested,
1644 const SuccessCallback& callback) override {
1645 FAIL();
1646 }
1647
1648 MOCK_METHOD2(CreateExtensionUpdateRequest,
1649 void(const std::string& id,
1650 const SupervisedUserService::SuccessCallback& callback));
1651
1652 private:
1653 DISALLOW_COPY_AND_ASSIGN(MockPermissionRequestCreator);
1654};
1655
1656TEST_F(ExtensionServiceTestSupervised, InstallOnlyAllowedByCustodian) {
1657 InitServices(true /* profile_is_supervised */);
1658
1659 base::FilePath path1 = data_dir().AppendASCII("good.crx");
1660 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
1661 const Extension* extensions[] = {
1662 InstallCRX(path1, INSTALL_FAILED),
1663 InstallCRX(path2, INSTALL_NEW, Extension::WAS_INSTALLED_BY_CUSTODIAN)
1664 };
1665
1666 // Only the extension with the "installed by custodian" flag should have been
1667 // installed and enabled.
1668 EXPECT_FALSE(extensions[0]);
1669 ASSERT_TRUE(extensions[1]);
1670 EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id()));
1671}
1672
1673TEST_F(ExtensionServiceTestSupervised, PreinstalledExtension) {
1674 InitServices(false /* profile_is_supervised */);
1675
1676 // Install an extension.
1677 base::FilePath path = data_dir().AppendASCII("good.crx");
1678 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1679 std::string id = extension->id();
1680
1681 // Now make the profile supervised.
1682 profile()->AsTestingProfile()->SetSupervisedUserId(
1683 supervised_users::kChildAccountSUID);
1684
1685 // The extension should not be enabled anymore.
1686 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
1687}
1688
1689TEST_F(ExtensionServiceTestSupervised, UpdateWithoutPermissionIncrease) {
1690 InitServices(true /* profile_is_supervised */);
1691
1692 base::FilePath base_path = data_dir().AppendASCII("autoupdate");
1693 base::FilePath pem_path = base_path.AppendASCII("key.pem");
1694
1695 const Extension* extension =
1696 PackAndInstallCRX(base_path.AppendASCII("v1"), pem_path, INSTALL_NEW,
1697 Extension::WAS_INSTALLED_BY_CUSTODIAN);
1698 // The extension must now be installed and enabled.
1699 ASSERT_TRUE(extension);
1700 ASSERT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
1701
1702 // Save the id, as the extension object will be destroyed during updating.
1703 std::string id = extension->id();
1704
1705 std::string old_version = extension->VersionString();
1706
1707 // Update to a new version.
1708 PackCRXAndUpdateExtension(id, base_path.AppendASCII("v2"), pem_path, ENABLED);
1709
1710 // The extension should still be there and enabled.
1711 extension = registry()->enabled_extensions().GetByID(id);
1712 ASSERT_TRUE(extension);
1713 // The version should have changed.
1714 EXPECT_NE(extension->VersionString(), old_version);
1715}
1716
1717TEST_F(ExtensionServiceTestSupervised, UpdateWithPermissionIncreaseNoApproval) {
treibb6af28cd2015-12-01 11:19:461718 InitNeedCustodianApprovalFieldTrial(false);
treib9afc6212015-10-30 18:49:581719
1720 InitServices(true /* profile_is_supervised */);
1721
1722 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1723 supervised_user_service()->AddPermissionRequestCreator(
1724 make_scoped_ptr(creator));
1725
1726 std::string id = InstallPermissionsTestExtension();
1727
1728 // Update to a new version with increased permissions.
1729 // Since we don't require the custodian's approval, no permission request
1730 // should be created.
1731 const std::string version2("2");
1732 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
1733 UpdateRequestId(id, version2), testing::_))
1734 .Times(0);
1735 UpdatePermissionsTestExtension(id, version2, DISABLED);
1736}
1737
1738TEST_F(ExtensionServiceTestSupervised,
1739 UpdateWithPermissionIncreaseApprovalOldVersion) {
treibb6af28cd2015-12-01 11:19:461740 InitNeedCustodianApprovalFieldTrial(true);
treib9afc6212015-10-30 18:49:581741
1742 InitServices(true /* profile_is_supervised */);
1743
1744 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1745 supervised_user_service()->AddPermissionRequestCreator(
1746 make_scoped_ptr(creator));
1747
1748 const std::string version1("1");
1749 const std::string version2("2");
1750
1751 std::string id = InstallPermissionsTestExtension();
1752
1753 // Update to a new version with increased permissions.
1754 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
1755 UpdateRequestId(id, version2), testing::_));
1756 UpdatePermissionsTestExtension(id, version2, DISABLED);
1757
1758 // Simulate a custodian approval for re-enabling the extension coming in
1759 // through Sync, but set the old version. This can happen when there already
1760 // was a pending request for an earlier version of the extension.
1761 sync_pb::EntitySpecifics specifics;
1762 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1763 ext_specifics->set_id(id);
1764 ext_specifics->set_enabled(true);
1765 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
1766 ext_specifics->set_installed_by_custodian(true);
1767 ext_specifics->set_version(version1);
1768
1769 // Attempting to re-enable an old version should result in a permission
1770 // request for the current version.
1771 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
1772 UpdateRequestId(id, version2), testing::_));
1773
treib65f103042015-12-03 10:21:361774 SyncChangeList list =
1775 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
1776
1777 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:581778 // The re-enable should be ignored, since the version doesn't match.
1779 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
1780 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
1781 id, base::Version(version1)));
1782 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
1783 id, base::Version(version2)));
1784}
1785
1786TEST_F(ExtensionServiceTestSupervised,
1787 UpdateWithPermissionIncreaseApprovalMatchingVersion) {
treibb6af28cd2015-12-01 11:19:461788 InitNeedCustodianApprovalFieldTrial(true);
treib9afc6212015-10-30 18:49:581789
1790 InitServices(true /* profile_is_supervised */);
1791
1792 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1793 supervised_user_service()->AddPermissionRequestCreator(
1794 make_scoped_ptr(creator));
1795
1796 std::string id = InstallPermissionsTestExtension();
1797
1798 // Update to a new version with increased permissions.
1799 const std::string version2("2");
1800 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
1801 UpdateRequestId(id, version2), testing::_));
1802 UpdatePermissionsTestExtension(id, version2, DISABLED);
1803
1804 // Simulate a custodian approval for re-enabling the extension coming in
1805 // through Sync.
1806 sync_pb::EntitySpecifics specifics;
1807 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1808 ext_specifics->set_id(id);
1809 ext_specifics->set_enabled(true);
1810 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
1811 ext_specifics->set_installed_by_custodian(true);
1812 ext_specifics->set_version(version2);
1813
treib65f103042015-12-03 10:21:361814 SyncChangeList list =
1815 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
1816
1817 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:581818 // The extension should have gotten re-enabled.
1819 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1820}
1821
1822TEST_F(ExtensionServiceTestSupervised,
1823 UpdateWithPermissionIncreaseApprovalNewVersion) {
treibb6af28cd2015-12-01 11:19:461824 InitNeedCustodianApprovalFieldTrial(true);
treib9afc6212015-10-30 18:49:581825
1826 InitServices(true /* profile_is_supervised */);
1827
1828 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1829 supervised_user_service()->AddPermissionRequestCreator(
1830 make_scoped_ptr(creator));
1831
1832 std::string id = InstallPermissionsTestExtension();
1833
1834 // Update to a new version with increased permissions.
1835 const std::string version2("2");
1836 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
1837 UpdateRequestId(id, version2), testing::_));
1838 UpdatePermissionsTestExtension(id, version2, DISABLED);
1839
1840 // Simulate a custodian approval for re-enabling the extension coming in
1841 // through Sync. Set a newer version than we have installed.
1842 const std::string version3("3");
1843 sync_pb::EntitySpecifics specifics;
1844 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1845 ext_specifics->set_id(id);
1846 ext_specifics->set_enabled(true);
1847 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
1848 ext_specifics->set_installed_by_custodian(true);
1849 ext_specifics->set_version(version3);
1850
1851 // This should *not* result in a new permission request.
1852 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
1853 UpdateRequestId(id, version3), testing::_))
1854 .Times(0);
1855
treib65f103042015-12-03 10:21:361856 SyncChangeList list =
1857 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
1858
1859 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:581860 // The re-enable should be delayed until the extension is updated to the
1861 // matching version.
1862 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
1863 EXPECT_TRUE(extension_sync_service()->HasPendingReenable(
1864 id, base::Version(version3)));
1865
1866 // Update to the matching version. Now the extension should get enabled.
1867 UpdatePermissionsTestExtension(id, version3, ENABLED);
1868}
1869
1870TEST_F(ExtensionServiceSyncTest, SyncUninstallByCustodianSkipsPolicy) {
1871 InitializeEmptyExtensionService();
1872 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361873 syncer::EXTENSIONS, syncer::SyncDataList(),
1874 make_scoped_ptr(new syncer::FakeSyncChangeProcessor()),
1875 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:581876
1877 // Install two extensions.
1878 base::FilePath path1 = data_dir().AppendASCII("good.crx");
1879 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
1880 const Extension* extensions[] = {
1881 InstallCRX(path1, INSTALL_NEW),
1882 InstallCRX(path2, INSTALL_NEW, Extension::WAS_INSTALLED_BY_CUSTODIAN)
1883 };
1884
1885 // Add a policy provider that will disallow any changes.
1886 extensions::TestManagementPolicyProvider provider(
1887 extensions::TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS);
1888 ExtensionSystem::Get(
1889 browser_context())->management_policy()->RegisterProvider(&provider);
1890
1891 // Create a sync deletion for each extension.
treib65f103042015-12-03 10:21:361892 SyncChangeList list;
treib9afc6212015-10-30 18:49:581893 for (size_t i = 0; i < arraysize(extensions); i++) {
1894 const std::string& id = extensions[i]->id();
1895 sync_pb::EntitySpecifics specifics;
1896 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1897 ext_specifics->set_id(id);
1898 ext_specifics->set_version("1.0");
1899 ext_specifics->set_installed_by_custodian(
1900 extensions[i]->was_installed_by_custodian());
1901 syncer::SyncData sync_data =
1902 syncer::SyncData::CreateLocalData(id, "Name", specifics);
treib65f103042015-12-03 10:21:361903 list.push_back(SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, sync_data));
treib9afc6212015-10-30 18:49:581904 }
1905
1906 // Save the extension ids, as uninstalling destroys the Extension instance.
1907 std::string extension_ids[] = {
1908 extensions[0]->id(),
1909 extensions[1]->id()
1910 };
1911
1912 // Now apply the uninstallations.
treib65f103042015-12-03 10:21:361913 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:581914
1915 // Uninstalling the extension without installed_by_custodian should have been
1916 // blocked by policy, so it should still be there.
1917 EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_ids[0]));
1918
1919 // But installed_by_custodian should result in bypassing the policy check.
1920 EXPECT_FALSE(
1921 registry()->GenerateInstalledExtensionsSet()->Contains(extension_ids[1]));
1922}
1923
rdevlin.cronin738501d2015-11-05 21:51:361924TEST_F(ExtensionServiceSyncTest, SyncExtensionHasAllhostsWithheld) {
1925 InitializeEmptyExtensionService();
asargente48ab752016-03-12 00:59:201926 StartSyncing(syncer::EXTENSIONS);
rdevlin.cronin738501d2015-11-05 21:51:361927
1928 // Create an extension that needs all-hosts.
1929 const std::string kName("extension");
1930 scoped_refptr<const Extension> extension =
1931 extensions::ExtensionBuilder()
limasdf3d102542015-12-09 03:58:451932 .SetLocation(Manifest::INTERNAL)
dcheng794d2bd2016-02-27 03:51:321933 .SetManifest(
limasdf3d102542015-12-09 03:58:451934 extensions::DictionaryBuilder()
1935 .Set("name", kName)
1936 .Set("description", "foo")
1937 .Set("manifest_version", 2)
1938 .Set("version", "1.0")
1939 .Set("permissions",
dcheng794d2bd2016-02-27 03:51:321940 extensions::ListBuilder().Append("*://*/*").Build())
1941 .Build())
limasdf3d102542015-12-09 03:58:451942 .SetID(crx_file::id_util::GenerateId(kName))
1943 .Build();
rdevlin.cronin738501d2015-11-05 21:51:361944
1945 // Install and enable it.
1946 service()->AddExtension(extension.get());
1947 service()->GrantPermissionsAndEnableExtension(extension.get());
1948 const std::string id = extension->id();
1949 EXPECT_TRUE(registry()->enabled_extensions().GetByID(id));
1950
1951 // Simulate a sync node coming in where the extension had all-hosts withheld.
1952 // This means that it should have all-hosts withheld on this machine, too.
rdevlin.cronin738501d2015-11-05 21:51:361953 sync_pb::EntitySpecifics specifics;
1954 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1955 ext_specifics->set_id(id);
1956 ext_specifics->set_name(kName);
1957 ext_specifics->set_version("1.0");
1958 ext_specifics->set_all_urls_enabled(false);
1959 ext_specifics->set_enabled(true);
rdevlin.cronin738501d2015-11-05 21:51:361960
treib65f103042015-12-03 10:21:361961 SyncChangeList list =
1962 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
1963
1964 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
rdevlin.cronin738501d2015-11-05 21:51:361965
1966 EXPECT_TRUE(registry()->enabled_extensions().GetByID(id));
1967 EXPECT_FALSE(extensions::util::AllowedScriptingOnAllUrls(id, profile()));
1968 EXPECT_TRUE(extensions::util::HasSetAllowedScriptingOnAllUrls(id, profile()));
1969 EXPECT_FALSE(extensions::util::AllowedScriptingOnAllUrls(id, profile()));
1970}
1971
treib9afc6212015-10-30 18:49:581972#endif // defined(ENABLE_SUPERVISED_USERS)
asargente48ab752016-03-12 00:59:201973
1974// Tests sync behavior in the case of an item that starts out as an app and
1975// gets updated to become an extension.
1976TEST_F(ExtensionServiceSyncTest, AppToExtension) {
1977 InitializeEmptyExtensionService();
1978 service()->Init();
1979 ASSERT_TRUE(service()->is_ready());
1980
1981 // Install v1, which is an app.
1982 const Extension* v1 =
1983 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v1.crx"),
1984 INSTALL_NEW);
1985 EXPECT_TRUE(v1->is_app());
1986 EXPECT_FALSE(v1->is_extension());
1987 std::string id = v1->id();
1988
1989 StatefulChangeProcessor extensions_processor(syncer::ModelType::EXTENSIONS);
1990 StatefulChangeProcessor apps_processor(syncer::ModelType::APPS);
1991 extension_sync_service()->MergeDataAndStartSyncing(
1992 syncer::EXTENSIONS, syncer::SyncDataList(),
1993 extensions_processor.GetWrapped(),
1994 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
1995 extension_sync_service()->MergeDataAndStartSyncing(
1996 syncer::APPS, syncer::SyncDataList(), apps_processor.GetWrapped(),
1997 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
1998
1999 // Check the app/extension change processors to be sure the right data was
2000 // added.
2001 EXPECT_TRUE(extensions_processor.changes().empty());
2002 EXPECT_TRUE(extensions_processor.data().empty());
2003 EXPECT_EQ(1u, apps_processor.data().size());
2004 ASSERT_EQ(1u, apps_processor.changes().size());
2005 const SyncChange& app_change = apps_processor.changes()[0];
2006 EXPECT_EQ(SyncChange::ACTION_ADD, app_change.change_type());
2007 scoped_ptr<ExtensionSyncData> app_data =
2008 ExtensionSyncData::CreateFromSyncData(app_change.sync_data());
2009 EXPECT_TRUE(app_data->is_app());
2010 EXPECT_EQ(id, app_data->id());
2011 EXPECT_EQ(*v1->version(), app_data->version());
2012
2013 // Update the app to v2, which is an extension.
2014 const Extension* v2 =
2015 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v2.crx"),
2016 INSTALL_UPDATED);
2017 EXPECT_FALSE(v2->is_app());
2018 EXPECT_TRUE(v2->is_extension());
2019 EXPECT_EQ(id, v2->id());
2020
2021 // Make sure we saw an extension item added.
2022 ASSERT_EQ(1u, extensions_processor.changes().size());
2023 const SyncChange& extension_change = extensions_processor.changes()[0];
2024 EXPECT_EQ(SyncChange::ACTION_ADD, extension_change.change_type());
2025 scoped_ptr<ExtensionSyncData> extension_data =
2026 ExtensionSyncData::CreateFromSyncData(extension_change.sync_data());
2027 EXPECT_FALSE(extension_data->is_app());
2028 EXPECT_EQ(id, extension_data->id());
2029 EXPECT_EQ(*v2->version(), extension_data->version());
2030
2031 // Get the current data from the change processors to use as the input to
2032 // the following call to MergeDataAndStartSyncing. This simulates what should
2033 // happen with sync.
2034 syncer::SyncDataList extensions_data =
2035 extensions_processor.GetAllSyncData(syncer::EXTENSIONS);
2036 syncer::SyncDataList apps_data = apps_processor.GetAllSyncData(syncer::APPS);
2037
2038 // Stop syncing, then start again.
2039 extension_sync_service()->StopSyncing(syncer::EXTENSIONS);
2040 extension_sync_service()->StopSyncing(syncer::APPS);
2041 extension_sync_service()->MergeDataAndStartSyncing(
2042 syncer::EXTENSIONS, extensions_data, extensions_processor.GetWrapped(),
2043 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
2044 extension_sync_service()->MergeDataAndStartSyncing(
2045 syncer::APPS, apps_data, apps_processor.GetWrapped(),
2046 make_scoped_ptr(new syncer::SyncErrorFactoryMock()));
2047
2048 // Make sure we saw an app item deleted.
2049 bool found_delete = false;
2050 for (const auto& change : apps_processor.changes()) {
2051 if (change.change_type() == SyncChange::ACTION_DELETE) {
2052 scoped_ptr<ExtensionSyncData> data =
2053 ExtensionSyncData::CreateFromSyncChange(change);
2054 if (data->id() == id) {
2055 found_delete = true;
2056 break;
2057 }
2058 }
2059 }
2060 EXPECT_TRUE(found_delete);
2061
2062 // Make sure there is one extension, and there are no more apps.
2063 EXPECT_EQ(1u, extensions_processor.data().size());
2064 EXPECT_TRUE(apps_processor.data().empty());
2065}