blob: 20b71474ac3aa6cab2c2adbc3122a788190d9a6d [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>
dchengc963c7142016-04-08 03:55:228#include <memory>
treib9afc6212015-10-30 18:49:589#include <string>
limasdf3d102542015-12-09 03:58:4510#include <utility>
treib9afc6212015-10-30 18:49:5811
12#include "base/bind.h"
13#include "base/command_line.h"
14#include "base/files/file_util.h"
dchengc963c7142016-04-08 03:55:2215#include "base/memory/ptr_util.h"
treib9afc6212015-10-30 18:49:5816#include "base/memory/weak_ptr.h"
17#include "base/metrics/field_trial.h"
Avi Drissman5f0fb8c2018-12-25 23:20:4918#include "base/stl_util.h"
treib9afc6212015-10-30 18:49:5819#include "base/test/mock_entropy_provider.h"
asvitkineb1db8262016-11-08 09:48:2020#include "base/test/scoped_feature_list.h"
Evan Stade46d716d2017-06-02 20:50:0921#include "chrome/browser/chrome_notification_types.h"
mamirf7715a2a2016-07-04 13:05:0822#include "chrome/browser/extensions/api/webstore_private/webstore_private_api.h"
rdevlin.cronin2f1ed4c2017-06-13 16:22:1323#include "chrome/browser/extensions/chrome_test_extension_loader.h"
treib9afc6212015-10-30 18:49:5824#include "chrome/browser/extensions/component_loader.h"
25#include "chrome/browser/extensions/extension_service.h"
26#include "chrome/browser/extensions/extension_service_test_with_install.h"
27#include "chrome/browser/extensions/extension_sync_data.h"
28#include "chrome/browser/extensions/extension_sync_service.h"
29#include "chrome/browser/extensions/extension_util.h"
proberge901ecab2017-08-31 19:24:2830#include "chrome/browser/extensions/test_blacklist.h"
treib9afc6212015-10-30 18:49:5831#include "chrome/browser/extensions/updater/extension_updater.h"
treib9afc6212015-10-30 18:49:5832#include "chrome/browser/sync/profile_sync_service_factory.h"
Evan Stade46d716d2017-06-02 20:50:0933#include "chrome/browser/themes/theme_service.h"
34#include "chrome/browser/themes/theme_service_factory.h"
Scott Violet6200d332018-02-23 21:29:2335#include "chrome/common/buildflags.h"
treib9afc6212015-10-30 18:49:5836#include "chrome/common/chrome_constants.h"
Konstantin Ganenkoae1129c2017-09-15 16:28:5937#include "chrome/common/extensions/extension_test_util.h"
treib9afc6212015-10-30 18:49:5838#include "chrome/common/extensions/sync_helper.h"
treib9afc6212015-10-30 18:49:5839#include "chrome/test/base/testing_profile.h"
maxbogue26f40222016-09-16 20:22:1840#include "components/browser_sync/profile_sync_service.h"
rdevlin.cronin738501d2015-11-05 21:51:3641#include "components/crx_file/id_util.h"
skym71603842016-10-10 18:17:3142#include "components/sync/model/fake_sync_change_processor.h"
43#include "components/sync/model/sync_change_processor_wrapper_for_test.h"
44#include "components/sync/model/sync_data.h"
45#include "components/sync/model/sync_error_factory_mock.h"
treibb6af28cd2015-12-01 11:19:4646#include "components/variations/variations_associated_data.h"
mamirf7715a2a2016-07-04 13:05:0847#include "extensions/browser/api_test_utils.h"
treib9afc6212015-10-30 18:49:5848#include "extensions/browser/app_sorting.h"
Devlin Croninbffe949eb2018-01-12 03:03:4049#include "extensions/browser/disable_reason.h"
treib9afc6212015-10-30 18:49:5850#include "extensions/browser/extension_prefs.h"
51#include "extensions/browser/extension_registry.h"
52#include "extensions/browser/extension_system.h"
karandeepb810e33402017-04-05 23:41:2253#include "extensions/browser/extension_util.h"
treib9afc6212015-10-30 18:49:5854#include "extensions/browser/management_policy.h"
55#include "extensions/browser/test_management_policy.h"
rdevlin.cronin738501d2015-11-05 21:51:3656#include "extensions/common/extension_builder.h"
treib9afc6212015-10-30 18:49:5857#include "extensions/common/manifest_url_handlers.h"
58#include "extensions/common/permissions/permission_set.h"
treib9afc6212015-10-30 18:49:5859#include "testing/gtest/include/gtest/gtest.h"
60
brettw9e85ef42016-11-01 21:01:2461#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
treib9afc6212015-10-30 18:49:5862#include "chrome/browser/supervised_user/permission_request_creator.h"
63#include "chrome/browser/supervised_user/supervised_user_constants.h"
mamire9609642016-06-28 22:17:5464#include "chrome/browser/supervised_user/supervised_user_features.h"
treib9afc6212015-10-30 18:49:5865#include "chrome/browser/supervised_user/supervised_user_service.h"
66#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
mamire9609642016-06-28 22:17:5467#include "chrome/browser/supervised_user/supervised_user_settings_service.h"
68#include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
69#include "chrome/common/pref_names.h"
treib9afc6212015-10-30 18:49:5870#endif
71
mamirf7715a2a2016-07-04 13:05:0872using extensions::api_test_utils::RunFunctionAndReturnSingleResult;
treib9afc6212015-10-30 18:49:5873using extensions::AppSorting;
74using extensions::Extension;
75using extensions::ExtensionPrefs;
76using extensions::ExtensionSyncData;
77using extensions::ExtensionSystem;
78using extensions::Manifest;
79using extensions::PermissionSet;
mamirf7715a2a2016-07-04 13:05:0880using extensions::WebstorePrivateIsPendingCustodianApprovalFunction;
treib65f103042015-12-03 10:21:3681using syncer::SyncChange;
82using syncer::SyncChangeList;
mamire9609642016-06-28 22:17:5483using testing::Mock;
treib65f103042015-12-03 10:21:3684
85namespace {
treib9afc6212015-10-30 18:49:5886
mamir192d7882016-06-22 17:10:1687const char autoupdate[] = "ogjcoiohnmldgjemafoockdghcjciccf";
treib9afc6212015-10-30 18:49:5888const char good0[] = "behllobkkfkfnphdnhnkndlbkcpglgmj";
89const char good2[] = "bjafgdebaacbbbecmhlhpofkepfkgcpa";
Joshua Pawlickif2f37f32018-11-05 21:40:5690const char good2048[] = "dfhpodpjggiioolfhoimofdbfjibmedp";
treib9afc6212015-10-30 18:49:5891const char good_crx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
92const char page_action[] = "obcimlgaoabeegjmmpldobjndiealpln";
mamir192d7882016-06-22 17:10:1693const char permissions_increase[] = "pgdpcfcocojkjfbgpiianjngphoopgmo";
Joshua Pawlickif2f37f32018-11-05 21:40:5694const char theme2_crx[] = "ibcijncamhmjjdodjamgiipcgnnaeagd";
treib9afc6212015-10-30 18:49:5895
rdevlin.cronin2f1ed4c2017-06-13 16:22:1396ExtensionSyncData GetDisableSyncData(const Extension& extension,
97 int disable_reasons) {
98 bool enabled = false;
99 bool incognito_enabled = false;
100 bool remote_install = false;
101 bool installed_by_custodian = false;
rdevlin.cronin2f1ed4c2017-06-13 16:22:13102 return ExtensionSyncData(extension, enabled, disable_reasons,
Devlin Cronin56daf35132018-05-10 16:25:33103 incognito_enabled, remote_install,
rdevlin.cronin2f1ed4c2017-06-13 16:22:13104 installed_by_custodian);
105}
106
107ExtensionSyncData GetEnableSyncData(const Extension& extension) {
108 bool enabled = true;
109 bool incognito_enabled = false;
110 bool remote_install = false;
111 bool installed_by_custodian = false;
Minh X. Nguyen45479012017-08-18 21:35:36112 return ExtensionSyncData(
113 extension, enabled, extensions::disable_reason::DISABLE_NONE,
Devlin Cronin56daf35132018-05-10 16:25:33114 incognito_enabled, remote_install, installed_by_custodian);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13115}
116
treib65f103042015-12-03 10:21:36117SyncChangeList MakeSyncChangeList(const std::string& id,
118 const sync_pb::EntitySpecifics& specifics,
119 SyncChange::SyncChangeType change_type) {
120 syncer::SyncData sync_data =
121 syncer::SyncData::CreateLocalData(id, "Name", specifics);
122 return SyncChangeList(1, SyncChange(FROM_HERE, change_type, sync_data));
123}
124
asargente48ab752016-03-12 00:59:20125// This is a FakeSyncChangeProcessor specialization that maintains a store of
126// SyncData items in the superclass' data_ member variable, treating it like a
127// map keyed by the extension id from the SyncData. Each instance of this class
128// should only be used for one model type (which should be either extensions or
129// apps) to match how the real sync system handles things.
130class StatefulChangeProcessor : public syncer::FakeSyncChangeProcessor {
131 public:
132 explicit StatefulChangeProcessor(syncer::ModelType expected_type)
133 : expected_type_(expected_type) {
134 EXPECT_TRUE(expected_type == syncer::ModelType::EXTENSIONS ||
135 expected_type == syncer::ModelType::APPS);
136 }
137
138 ~StatefulChangeProcessor() override {}
139
140 // We let our parent class, FakeSyncChangeProcessor, handle saving the
141 // changes for us, but in addition we "apply" these changes by treating
142 // the FakeSyncChangeProcessor's SyncDataList as a map keyed by extension
143 // id.
144 syncer::SyncError ProcessSyncChanges(
Brett Wilsone1a70422017-09-12 05:10:09145 const base::Location& from_here,
asargente48ab752016-03-12 00:59:20146 const syncer::SyncChangeList& change_list) override {
147 syncer::FakeSyncChangeProcessor::ProcessSyncChanges(from_here, change_list);
148 for (const auto& change : change_list) {
149 syncer::SyncData sync_data = change.sync_data();
150 EXPECT_EQ(expected_type_, sync_data.GetDataType());
151
dchengc963c7142016-04-08 03:55:22152 std::unique_ptr<ExtensionSyncData> modified =
asargente48ab752016-03-12 00:59:20153 ExtensionSyncData::CreateFromSyncData(sync_data);
154
155 // Start by removing any existing entry for this extension id.
156 syncer::SyncDataList& data_list = data();
157 for (auto iter = data_list.begin(); iter != data_list.end(); ++iter) {
dchengc963c7142016-04-08 03:55:22158 std::unique_ptr<ExtensionSyncData> existing =
asargente48ab752016-03-12 00:59:20159 ExtensionSyncData::CreateFromSyncData(*iter);
160 if (existing->id() == modified->id()) {
161 data_list.erase(iter);
162 break;
163 }
164 }
165
166 // Now add in the new data for this id, if appropriate.
167 if (change.change_type() == SyncChange::ACTION_ADD ||
168 change.change_type() == SyncChange::ACTION_UPDATE) {
169 data_list.push_back(sync_data);
170 } else if (change.change_type() != SyncChange::ACTION_DELETE) {
171 ADD_FAILURE() << "Unexpected change type " << change.change_type();
172 }
173 }
174 return syncer::SyncError();
175 }
176
177 // We override this to help catch the error of trying to use a single
178 // StatefulChangeProcessor to process changes for both extensions and apps
179 // sync data.
180 syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override {
181 EXPECT_EQ(expected_type_, type);
182 return FakeSyncChangeProcessor::GetAllSyncData(type);
183 }
184
185 // This is a helper to vend a wrapped version of this object suitable for
186 // passing in to MergeDataAndStartSyncing, which takes a
dchengc963c7142016-04-08 03:55:22187 // std::unique_ptr<SyncChangeProcessor>, since in tests we typically don't
188 // want to
asargente48ab752016-03-12 00:59:20189 // give up ownership of a local change processor.
dchengc963c7142016-04-08 03:55:22190 std::unique_ptr<syncer::SyncChangeProcessor> GetWrapped() {
Jinho Bangb5216cec2018-01-17 19:43:11191 return std::make_unique<syncer::SyncChangeProcessorWrapperForTest>(this);
asargente48ab752016-03-12 00:59:20192 }
193
194 protected:
195 // The expected ModelType of changes that this processor will see.
196 syncer::ModelType expected_type_;
197
198 DISALLOW_COPY_AND_ASSIGN(StatefulChangeProcessor);
199};
200
treib65f103042015-12-03 10:21:36201} // namespace
202
treib9afc6212015-10-30 18:49:58203class ExtensionServiceSyncTest
204 : public extensions::ExtensionServiceTestWithInstall {
205 public:
206 void MockSyncStartFlare(bool* was_called,
207 syncer::ModelType* model_type_passed_in,
208 syncer::ModelType model_type) {
209 *was_called = true;
210 *model_type_passed_in = model_type;
211 }
212
asargente48ab752016-03-12 00:59:20213 // Helper to call MergeDataAndStartSyncing with no server data and dummy
214 // change processor / error factory.
215 void StartSyncing(syncer::ModelType type) {
216 ASSERT_TRUE(type == syncer::EXTENSIONS || type == syncer::APPS);
217 extension_sync_service()->MergeDataAndStartSyncing(
218 type, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11219 std::make_unique<syncer::FakeSyncChangeProcessor>(),
220 std::make_unique<syncer::SyncErrorFactoryMock>());
asargente48ab752016-03-12 00:59:20221 }
222
rdevlin.cronin2f1ed4c2017-06-13 16:22:13223 void DisableExtensionFromSync(const Extension& extension,
224 int disable_reasons) {
Minh X. Nguyen45479012017-08-18 21:35:36225 ExtensionSyncData disable_extension = GetDisableSyncData(
226 extension, extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13227 SyncChangeList list(
228 1, disable_extension.GetSyncChange(SyncChange::ACTION_UPDATE));
229 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
230 }
231
232 void EnableExtensionFromSync(const Extension& extension) {
233 ExtensionSyncData enable_extension = GetEnableSyncData(extension);
234 SyncChangeList list(
235 1, enable_extension.GetSyncChange(SyncChange::ACTION_UPDATE));
236 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
237 }
238
treib9afc6212015-10-30 18:49:58239 protected:
240 // Paths to some of the fake extensions.
241 base::FilePath good0_path() {
242 return data_dir()
243 .AppendASCII("good")
244 .AppendASCII("Extensions")
245 .AppendASCII(good0)
246 .AppendASCII("1.0.0.0");
247 }
248
249 ExtensionSyncService* extension_sync_service() {
250 return ExtensionSyncService::Get(profile());
251 }
252};
253
254TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledComponent) {
255 InitializeEmptyExtensionService();
256
257 bool flare_was_called = false;
258 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
259 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
260 extension_sync_service()->SetSyncStartFlareForTesting(
261 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
262 factory.GetWeakPtr(),
263 &flare_was_called, // Safe due to WeakPtrFactory scope.
264 &triggered_type)); // Safe due to WeakPtrFactory scope.
265
266 // Install a component extension.
267 std::string manifest;
268 ASSERT_TRUE(base::ReadFileToString(
269 good0_path().Append(extensions::kManifestFilename), &manifest));
270 service()->component_loader()->Add(manifest, good0_path());
271 ASSERT_FALSE(service()->is_ready());
272 service()->Init();
273 ASSERT_TRUE(service()->is_ready());
274
275 // Extensions added before service is_ready() don't trigger sync startup.
276 EXPECT_FALSE(flare_was_called);
277 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
278}
279
280TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledNormal) {
281 InitializeGoodInstalledExtensionService();
282
283 bool flare_was_called = false;
284 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
285 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
286 extension_sync_service()->SetSyncStartFlareForTesting(
287 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
288 factory.GetWeakPtr(),
289 &flare_was_called, // Safe due to WeakPtrFactory scope.
290 &triggered_type)); // Safe due to WeakPtrFactory scope.
291
292 ASSERT_FALSE(service()->is_ready());
293 service()->Init();
294 ASSERT_EQ(3u, loaded_.size());
295 ASSERT_TRUE(service()->is_ready());
296
297 // Extensions added before service is_ready() don't trigger sync startup.
298 EXPECT_FALSE(flare_was_called);
299 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
300}
301
302TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupOnInstall) {
303 InitializeEmptyExtensionService();
304 service()->Init();
305 ASSERT_TRUE(service()->is_ready());
306
307 bool flare_was_called = false;
308 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
309 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
310 extension_sync_service()->SetSyncStartFlareForTesting(
311 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
312 factory.GetWeakPtr(),
313 &flare_was_called, // Safe due to WeakPtrFactory scope.
314 &triggered_type)); // Safe due to WeakPtrFactory scope.
315
316 base::FilePath path = data_dir().AppendASCII("good.crx");
317 InstallCRX(path, INSTALL_NEW);
318
319 EXPECT_TRUE(flare_was_called);
320 EXPECT_EQ(syncer::EXTENSIONS, triggered_type);
321
322 // Reset.
323 flare_was_called = false;
324 triggered_type = syncer::UNSPECIFIED;
325
326 // Once sync starts, flare should no longer be invoked.
327 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36328 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11329 std::make_unique<syncer::FakeSyncChangeProcessor>(),
330 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58331 path = data_dir().AppendASCII("page_action.crx");
332 InstallCRX(path, INSTALL_NEW);
333 EXPECT_FALSE(flare_was_called);
334 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
335}
336
337TEST_F(ExtensionServiceSyncTest, DisableExtensionFromSync) {
338 // Start the extensions service with one external extension already installed.
339 base::FilePath source_install_dir =
340 data_dir().AppendASCII("good").AppendASCII("Extensions");
341 base::FilePath pref_path =
342 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
343
344 InitializeInstalledExtensionService(pref_path, source_install_dir);
345
346 // The user has enabled sync.
Marc Treib5a78e9c2019-02-19 16:47:01347 syncer::SyncService* sync_service =
treib9afc6212015-10-30 18:49:58348 ProfileSyncServiceFactory::GetForProfile(profile());
Marc Treib9948a682018-11-20 08:01:37349 sync_service->GetUserSettings()->SetFirstSetupComplete();
treib9afc6212015-10-30 18:49:58350
351 service()->Init();
352 ASSERT_TRUE(service()->is_ready());
353
354 ASSERT_EQ(3u, loaded_.size());
355
356 // We start enabled.
357 const Extension* extension = service()->GetExtensionById(good0, true);
358 ASSERT_TRUE(extension);
359 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
360
361 // Sync starts up.
362 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36363 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11364 std::make_unique<syncer::FakeSyncChangeProcessor>(),
365 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58366
367 // Then sync data arrives telling us to disable |good0|.
Minh X. Nguyen45479012017-08-18 21:35:36368 ExtensionSyncData disable_good_crx(
369 *extension, false, extensions::disable_reason::DISABLE_USER_ACTION, false,
Devlin Cronin56daf35132018-05-10 16:25:33370 false, false);
treib65f103042015-12-03 10:21:36371 SyncChangeList list(
372 1, disable_good_crx.GetSyncChange(SyncChange::ACTION_UPDATE));
treib9afc6212015-10-30 18:49:58373 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
374
375 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
376}
377
rdevlin.cronin2f1ed4c2017-06-13 16:22:13378// Test that sync can enable and disable installed extensions.
379TEST_F(ExtensionServiceSyncTest, ReenableDisabledExtensionFromSync) {
380 InitializeEmptyExtensionService();
381
382 // Enable sync.
Marc Treib5a78e9c2019-02-19 16:47:01383 syncer::SyncService* sync_service =
rdevlin.cronin2f1ed4c2017-06-13 16:22:13384 ProfileSyncServiceFactory::GetForProfile(profile());
Marc Treib9948a682018-11-20 08:01:37385 sync_service->GetUserSettings()->SetFirstSetupComplete();
rdevlin.cronin2f1ed4c2017-06-13 16:22:13386
387 service()->Init();
388
389 // Load up a simple extension.
390 extensions::ChromeTestExtensionLoader extension_loader(profile());
391 extension_loader.set_pack_extension(true);
392 scoped_refptr<const Extension> extension = extension_loader.LoadExtension(
393 data_dir().AppendASCII("simple_with_file"));
394 ASSERT_TRUE(extension);
395 const std::string kExtensionId = extension->id();
396 ASSERT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
397
398 syncer::FakeSyncChangeProcessor* processor_raw = nullptr;
399 {
Jinho Bangb5216cec2018-01-17 19:43:11400 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
rdevlin.cronin2f1ed4c2017-06-13 16:22:13401 processor_raw = processor.get();
402 extension_sync_service()->MergeDataAndStartSyncing(
403 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:11404 std::make_unique<syncer::SyncErrorFactoryMock>());
rdevlin.cronin2f1ed4c2017-06-13 16:22:13405 }
406 processor_raw->changes().clear();
407
Minh X. Nguyen45479012017-08-18 21:35:36408 DisableExtensionFromSync(*extension,
409 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13410
411 // The extension should be disabled.
412 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
Minh X. Nguyen45479012017-08-18 21:35:36413 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
rdevlin.cronin2f1ed4c2017-06-13 16:22:13414 ExtensionPrefs::Get(profile())->GetDisableReasons(kExtensionId));
415 EXPECT_TRUE(processor_raw->changes().empty());
416
417 // Enable the extension. Sync should push the new state.
418 service()->EnableExtension(kExtensionId);
419 {
420 ASSERT_EQ(1u, processor_raw->changes().size());
421 const SyncChange& change = processor_raw->changes()[0];
422 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
423 std::unique_ptr<ExtensionSyncData> data =
424 ExtensionSyncData::CreateFromSyncData(change.sync_data());
425 EXPECT_EQ(kExtensionId, data->id());
426 EXPECT_EQ(0, data->disable_reasons());
427 EXPECT_TRUE(data->enabled());
428 }
429
430 // Disable the extension again. Sync should push the new state.
431 processor_raw->changes().clear();
Minh X. Nguyen45479012017-08-18 21:35:36432 service()->DisableExtension(kExtensionId,
433 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13434 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
435 {
436 ASSERT_EQ(1u, processor_raw->changes().size());
437 const SyncChange& change = processor_raw->changes()[0];
438 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
439 std::unique_ptr<ExtensionSyncData> data =
440 ExtensionSyncData::CreateFromSyncData(change.sync_data());
441 EXPECT_EQ(kExtensionId, data->id());
Minh X. Nguyen45479012017-08-18 21:35:36442 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
443 data->disable_reasons());
rdevlin.cronin2f1ed4c2017-06-13 16:22:13444 EXPECT_FALSE(data->enabled());
445 }
446 processor_raw->changes().clear();
447
448 // Enable the extension via sync.
449 EnableExtensionFromSync(*extension);
450
451 // The extension should be enabled.
452 EXPECT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
453 EXPECT_TRUE(processor_raw->changes().empty());
454}
455
456// Tests that default-installed extensions won't be affected by incoming sync
457// data. (It's feasible to have a sync entry for an extension that could be
458// default installed, since one installation may be default-installed while
459// another may not be).
460TEST_F(ExtensionServiceSyncTest,
461 DefaultInstalledExtensionsAreNotReenabledOrDisabledBySync) {
462 InitializeEmptyExtensionService();
463
464 // Enable sync.
Marc Treib5a78e9c2019-02-19 16:47:01465 syncer::SyncService* sync_service =
rdevlin.cronin2f1ed4c2017-06-13 16:22:13466 ProfileSyncServiceFactory::GetForProfile(profile());
Marc Treib9948a682018-11-20 08:01:37467 sync_service->GetUserSettings()->SetFirstSetupComplete();
rdevlin.cronin2f1ed4c2017-06-13 16:22:13468
469 service()->Init();
470
471 // Load up an extension that's considered default installed.
472 extensions::ChromeTestExtensionLoader extension_loader(profile());
473 extension_loader.set_pack_extension(true);
474 extension_loader.add_creation_flag(Extension::WAS_INSTALLED_BY_DEFAULT);
475 scoped_refptr<const Extension> extension = extension_loader.LoadExtension(
476 data_dir().AppendASCII("simple_with_file"));
477 ASSERT_TRUE(extension);
478
479 // The extension shouldn't sync.
480 EXPECT_FALSE(extensions::util::ShouldSync(extension.get(), profile()));
481 const std::string kExtensionId = extension->id();
482 ASSERT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
483
484 syncer::FakeSyncChangeProcessor* processor_raw = nullptr;
485 {
Jinho Bangb5216cec2018-01-17 19:43:11486 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
rdevlin.cronin2f1ed4c2017-06-13 16:22:13487 processor_raw = processor.get();
488 extension_sync_service()->MergeDataAndStartSyncing(
489 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:11490 std::make_unique<syncer::SyncErrorFactoryMock>());
rdevlin.cronin2f1ed4c2017-06-13 16:22:13491 }
492 processor_raw->changes().clear();
493
494 // Sync state says the extension is disabled (e.g. on another machine).
Minh X. Nguyen45479012017-08-18 21:35:36495 DisableExtensionFromSync(*extension,
496 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13497
498 // The extension should still be enabled, since it's default-installed.
499 EXPECT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
500 EXPECT_TRUE(processor_raw->changes().empty());
501
502 // Now disable the extension locally. Sync should *not* push new state.
Minh X. Nguyen45479012017-08-18 21:35:36503 service()->DisableExtension(kExtensionId,
504 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13505 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
506 EXPECT_TRUE(processor_raw->changes().empty());
507
508 // Sync state says the extension is enabled.
509 EnableExtensionFromSync(*extension);
510
511 // As above, the extension should not have been affected by sync.
512 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
513 EXPECT_TRUE(processor_raw->changes().empty());
514
515 // And re-enabling the extension should not push new state to sync.
516 service()->EnableExtension(kExtensionId);
517 EXPECT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
518 EXPECT_TRUE(processor_raw->changes().empty());
519}
520
treib9afc6212015-10-30 18:49:58521TEST_F(ExtensionServiceSyncTest, IgnoreSyncChangesWhenLocalStateIsMoreRecent) {
522 // Start the extension service with three extensions already installed.
523 base::FilePath source_install_dir =
524 data_dir().AppendASCII("good").AppendASCII("Extensions");
525 base::FilePath pref_path =
526 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
527
528 InitializeInstalledExtensionService(pref_path, source_install_dir);
529
530 // The user has enabled sync.
Marc Treib5a78e9c2019-02-19 16:47:01531 syncer::SyncService* sync_service =
treib9afc6212015-10-30 18:49:58532 ProfileSyncServiceFactory::GetForProfile(profile());
Marc Treib9948a682018-11-20 08:01:37533 sync_service->GetUserSettings()->SetFirstSetupComplete();
treib9afc6212015-10-30 18:49:58534 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
535 extension_sync_service();
536
537 service()->Init();
538 ASSERT_TRUE(service()->is_ready());
539 ASSERT_EQ(3u, loaded_.size());
540
541 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
542 ASSERT_TRUE(service()->IsExtensionEnabled(good2));
543
544 // Disable and re-enable good0 before first sync data arrives.
Minh X. Nguyen45479012017-08-18 21:35:36545 service()->DisableExtension(good0,
546 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:58547 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
548 service()->EnableExtension(good0);
549 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
550 // Disable good2 before first sync data arrives (good1 is considered
551 // non-syncable because it has plugin permission).
Minh X. Nguyen45479012017-08-18 21:35:36552 service()->DisableExtension(good2,
553 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:58554 ASSERT_FALSE(service()->IsExtensionEnabled(good2));
555
556 const Extension* extension0 = service()->GetExtensionById(good0, true);
557 const Extension* extension2 = service()->GetExtensionById(good2, true);
558 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension0));
559 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension2));
560
561 // Now sync data comes in that says to disable good0 and enable good2.
Minh X. Nguyen45479012017-08-18 21:35:36562 ExtensionSyncData disable_good0(
563 *extension0, false, extensions::disable_reason::DISABLE_USER_ACTION,
Devlin Cronin56daf35132018-05-10 16:25:33564 false, false, false);
Devlin Cronin93beb23d2018-05-04 21:17:35565 ExtensionSyncData enable_good2(*extension2, true,
566 extensions::disable_reason::DISABLE_NONE,
Devlin Cronin56daf35132018-05-10 16:25:33567 false, false, false);
treib9afc6212015-10-30 18:49:58568 syncer::SyncDataList sync_data;
569 sync_data.push_back(disable_good0.GetSyncData());
570 sync_data.push_back(enable_good2.GetSyncData());
571 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:22572 syncer::EXTENSIONS, sync_data,
Jinho Bangb5216cec2018-01-17 19:43:11573 std::make_unique<syncer::FakeSyncChangeProcessor>(),
574 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58575
576 // Both sync changes should be ignored, since the local state was changed
577 // before sync started, and so the local state is considered more recent.
578 EXPECT_TRUE(service()->IsExtensionEnabled(good0));
579 EXPECT_FALSE(service()->IsExtensionEnabled(good2));
580}
581
treibb794dd52015-12-01 18:47:14582TEST_F(ExtensionServiceSyncTest, DontSelfNotify) {
583 // Start the extension service with three extensions already installed.
584 base::FilePath source_install_dir =
585 data_dir().AppendASCII("good").AppendASCII("Extensions");
586 base::FilePath pref_path =
587 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
588
589 InitializeInstalledExtensionService(pref_path, source_install_dir);
590
591 // The user has enabled sync.
Marc Treib9948a682018-11-20 08:01:37592 ProfileSyncServiceFactory::GetForProfile(profile())
593 ->GetUserSettings()
594 ->SetFirstSetupComplete();
treibb794dd52015-12-01 18:47:14595 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
596 extension_sync_service();
597
598 service()->Init();
599 ASSERT_TRUE(service()->is_ready());
600 ASSERT_EQ(3u, loaded_.size());
601 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
602
603 syncer::FakeSyncChangeProcessor* processor =
604 new syncer::FakeSyncChangeProcessor;
605 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:22606 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
Jinho Bangb5216cec2018-01-17 19:43:11607 std::make_unique<syncer::SyncErrorFactoryMock>());
treibb794dd52015-12-01 18:47:14608
609 processor->changes().clear();
610
611 // Simulate various incoming sync changes, and make sure they don't result in
612 // any outgoing changes.
613
614 {
615 const Extension* extension = service()->GetExtensionById(good0, true);
616 ASSERT_TRUE(extension);
617
618 // Disable the extension.
Devlin Cronin93beb23d2018-05-04 21:17:35619 ExtensionSyncData data(*extension, false,
620 extensions::disable_reason::DISABLE_USER_ACTION,
Devlin Cronin56daf35132018-05-10 16:25:33621 false, false, false);
treib65f103042015-12-03 10:21:36622 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14623
624 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
625
626 EXPECT_TRUE(processor->changes().empty());
627 }
628
629 {
630 const Extension* extension = service()->GetExtensionById(good0, true);
631 ASSERT_TRUE(extension);
632
633 // Set incognito enabled to true.
Minh X. Nguyen45479012017-08-18 21:35:36634 ExtensionSyncData data(*extension, false,
635 extensions::disable_reason::DISABLE_NONE, true,
Devlin Cronin56daf35132018-05-10 16:25:33636 false, false);
treib65f103042015-12-03 10:21:36637 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14638
639 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
640
641 EXPECT_TRUE(processor->changes().empty());
642 }
643
644 {
645 const Extension* extension = service()->GetExtensionById(good0, true);
646 ASSERT_TRUE(extension);
647
648 // Add another disable reason.
Minh X. Nguyen45479012017-08-18 21:35:36649 ExtensionSyncData data(
650 *extension, false,
651 extensions::disable_reason::DISABLE_USER_ACTION |
652 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
Devlin Cronin56daf35132018-05-10 16:25:33653 false, false, false);
treib65f103042015-12-03 10:21:36654 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14655
656 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
657
658 EXPECT_TRUE(processor->changes().empty());
659 }
660
661 {
662 const Extension* extension = service()->GetExtensionById(good0, true);
663 ASSERT_TRUE(extension);
664
665 // Uninstall the extension.
Minh X. Nguyen45479012017-08-18 21:35:36666 ExtensionSyncData data(
667 *extension, false,
668 extensions::disable_reason::DISABLE_USER_ACTION |
669 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
Devlin Cronin56daf35132018-05-10 16:25:33670 false, false, false);
treib65f103042015-12-03 10:21:36671 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_DELETE));
treibb794dd52015-12-01 18:47:14672
673 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
674
675 EXPECT_TRUE(processor->changes().empty());
676 }
677}
678
treib9afc6212015-10-30 18:49:58679TEST_F(ExtensionServiceSyncTest, GetSyncData) {
680 InitializeEmptyExtensionService();
681 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
682 const Extension* extension = service()->GetInstalledExtension(good_crx);
683 ASSERT_TRUE(extension);
684
685 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36686 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11687 std::make_unique<syncer::FakeSyncChangeProcessor>(),
688 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58689
690 syncer::SyncDataList list =
691 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
692 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22693 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58694 ExtensionSyncData::CreateFromSyncData(list[0]);
695 ASSERT_TRUE(data.get());
696 EXPECT_EQ(extension->id(), data->id());
697 EXPECT_FALSE(data->uninstalled());
698 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
699 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
700 data->incognito_enabled());
Devlin Cronin03bf2d22017-12-20 08:21:05701 EXPECT_EQ(data->version(), extension->version());
treib9afc6212015-10-30 18:49:58702 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
703 data->update_url());
704 EXPECT_EQ(extension->name(), data->name());
705}
706
treib29e1b9b12015-11-11 08:50:56707TEST_F(ExtensionServiceSyncTest, GetSyncDataDisableReasons) {
708 InitializeEmptyExtensionService();
709 const Extension* extension =
710 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
711 ASSERT_TRUE(extension);
712
treib29e1b9b12015-11-11 08:50:56713 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36714 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11715 std::make_unique<syncer::FakeSyncChangeProcessor>(),
716 std::make_unique<syncer::SyncErrorFactoryMock>());
treib29e1b9b12015-11-11 08:50:56717
718 {
719 syncer::SyncDataList list =
720 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
721 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22722 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56723 ExtensionSyncData::CreateFromSyncData(list[0]);
724 ASSERT_TRUE(data.get());
725 EXPECT_TRUE(data->enabled());
726 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36727 EXPECT_EQ(extensions::disable_reason::DISABLE_NONE,
728 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56729 }
730
731 // Syncable disable reason, should propagate to sync.
Minh X. Nguyen45479012017-08-18 21:35:36732 service()->DisableExtension(good_crx,
733 extensions::disable_reason::DISABLE_USER_ACTION);
treib29e1b9b12015-11-11 08:50:56734 {
735 syncer::SyncDataList list =
736 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
737 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22738 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56739 ExtensionSyncData::CreateFromSyncData(list[0]);
740 ASSERT_TRUE(data.get());
741 EXPECT_FALSE(data->enabled());
742 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36743 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
744 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56745 }
746 service()->EnableExtension(good_crx);
747
748 // Non-syncable disable reason. The sync data should still say "enabled".
Minh X. Nguyen45479012017-08-18 21:35:36749 service()->DisableExtension(good_crx,
750 extensions::disable_reason::DISABLE_RELOAD);
treib29e1b9b12015-11-11 08:50:56751 {
752 syncer::SyncDataList list =
753 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
754 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22755 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56756 ExtensionSyncData::CreateFromSyncData(list[0]);
757 ASSERT_TRUE(data.get());
758 EXPECT_TRUE(data->enabled());
759 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36760 EXPECT_EQ(extensions::disable_reason::DISABLE_NONE,
761 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56762 }
763 service()->EnableExtension(good_crx);
764
765 // Both a syncable and a non-syncable disable reason, only the former should
766 // propagate to sync.
Minh X. Nguyen45479012017-08-18 21:35:36767 service()->DisableExtension(good_crx,
768 extensions::disable_reason::DISABLE_USER_ACTION |
769 extensions::disable_reason::DISABLE_RELOAD);
treib29e1b9b12015-11-11 08:50:56770 {
771 syncer::SyncDataList list =
772 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
773 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22774 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56775 ExtensionSyncData::CreateFromSyncData(list[0]);
776 ASSERT_TRUE(data.get());
777 EXPECT_FALSE(data->enabled());
778 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36779 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
780 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56781 }
782 service()->EnableExtension(good_crx);
783}
784
treib9afc6212015-10-30 18:49:58785TEST_F(ExtensionServiceSyncTest, GetSyncDataTerminated) {
786 InitializeEmptyExtensionService();
787 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
788 TerminateExtension(good_crx);
789 const Extension* extension = service()->GetInstalledExtension(good_crx);
790 ASSERT_TRUE(extension);
791
treib9afc6212015-10-30 18:49:58792 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36793 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11794 std::make_unique<syncer::FakeSyncChangeProcessor>(),
795 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58796
797 syncer::SyncDataList list =
798 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
799 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22800 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58801 ExtensionSyncData::CreateFromSyncData(list[0]);
802 ASSERT_TRUE(data.get());
803 EXPECT_EQ(extension->id(), data->id());
804 EXPECT_FALSE(data->uninstalled());
805 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
806 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
807 data->incognito_enabled());
Devlin Cronin03bf2d22017-12-20 08:21:05808 EXPECT_EQ(data->version(), extension->version());
treib9afc6212015-10-30 18:49:58809 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
810 data->update_url());
811 EXPECT_EQ(extension->name(), data->name());
812}
813
814TEST_F(ExtensionServiceSyncTest, GetSyncDataFilter) {
815 InitializeEmptyExtensionService();
816 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
817 const Extension* extension = service()->GetInstalledExtension(good_crx);
818 ASSERT_TRUE(extension);
819
treib9afc6212015-10-30 18:49:58820 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36821 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11822 std::make_unique<syncer::FakeSyncChangeProcessor>(),
823 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58824
825 syncer::SyncDataList list =
826 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
827 ASSERT_EQ(list.size(), 0U);
828}
829
830TEST_F(ExtensionServiceSyncTest, GetSyncExtensionDataUserSettings) {
831 InitializeEmptyExtensionService();
832 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
833 const Extension* extension = service()->GetInstalledExtension(good_crx);
834 ASSERT_TRUE(extension);
835
treib9afc6212015-10-30 18:49:58836 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36837 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11838 std::make_unique<syncer::FakeSyncChangeProcessor>(),
839 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58840
841 {
842 syncer::SyncDataList list =
843 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
844 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22845 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58846 ExtensionSyncData::CreateFromSyncData(list[0]);
847 ASSERT_TRUE(data.get());
848 EXPECT_TRUE(data->enabled());
849 EXPECT_FALSE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58850 }
851
Minh X. Nguyen45479012017-08-18 21:35:36852 service()->DisableExtension(good_crx,
853 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:58854 {
855 syncer::SyncDataList list =
856 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
857 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22858 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58859 ExtensionSyncData::CreateFromSyncData(list[0]);
860 ASSERT_TRUE(data.get());
861 EXPECT_FALSE(data->enabled());
862 EXPECT_FALSE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58863 }
864
865 extensions::util::SetIsIncognitoEnabled(good_crx, profile(), true);
treib9afc6212015-10-30 18:49:58866 {
867 syncer::SyncDataList list =
868 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
869 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22870 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58871 ExtensionSyncData::CreateFromSyncData(list[0]);
872 ASSERT_TRUE(data.get());
873 EXPECT_FALSE(data->enabled());
874 EXPECT_TRUE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58875 }
876
877 service()->EnableExtension(good_crx);
treib9afc6212015-10-30 18:49:58878 {
879 syncer::SyncDataList list =
880 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
881 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22882 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58883 ExtensionSyncData::CreateFromSyncData(list[0]);
884 ASSERT_TRUE(data.get());
885 EXPECT_TRUE(data->enabled());
886 EXPECT_TRUE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58887 }
888}
889
890TEST_F(ExtensionServiceSyncTest, SyncForUninstalledExternalExtension) {
891 InitializeEmptyExtensionService();
catmullings22bc2372016-11-02 19:59:35892 InstallCRX(data_dir().AppendASCII("good.crx"), Manifest::EXTERNAL_PREF,
893 INSTALL_NEW, Extension::NO_FLAGS);
treib9afc6212015-10-30 18:49:58894 const Extension* extension = service()->GetInstalledExtension(good_crx);
895 ASSERT_TRUE(extension);
896
treib9afc6212015-10-30 18:49:58897 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36898 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11899 std::make_unique<syncer::FakeSyncChangeProcessor>(),
900 std::make_unique<syncer::SyncErrorFactoryMock>());
asargente48ab752016-03-12 00:59:20901 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:58902
Devlin Cronin6fd1cd62017-12-05 19:13:57903 UninstallExtension(good_crx);
treib9afc6212015-10-30 18:49:58904 EXPECT_TRUE(
905 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
906
907 sync_pb::EntitySpecifics specifics;
908 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
909 sync_pb::ExtensionSpecifics* extension_specifics =
910 app_specifics->mutable_extension();
911 extension_specifics->set_id(good_crx);
912 extension_specifics->set_version("1.0");
913 extension_specifics->set_enabled(true);
914
treib65f103042015-12-03 10:21:36915 SyncChangeList list =
916 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:58917
918 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
919 EXPECT_TRUE(
920 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
921}
922
923TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettings) {
924 InitializeEmptyExtensionService();
925 const Extension* app =
926 PackAndInstallCRX(data_dir().AppendASCII("app"), INSTALL_NEW);
927 ASSERT_TRUE(app);
928 ASSERT_TRUE(app->is_app());
929
treib9afc6212015-10-30 18:49:58930 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36931 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11932 std::make_unique<syncer::FakeSyncChangeProcessor>(),
933 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58934
935 syncer::StringOrdinal initial_ordinal =
936 syncer::StringOrdinal::CreateInitialOrdinal();
937 {
938 syncer::SyncDataList list =
939 extension_sync_service()->GetAllSyncData(syncer::APPS);
940 ASSERT_EQ(list.size(), 1U);
941
dchengc963c7142016-04-08 03:55:22942 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58943 ExtensionSyncData::CreateFromSyncData(list[0]);
944 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->app_launch_ordinal()));
945 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
946 }
947
deepak.m14ba69e62015-11-17 05:42:12948 AppSorting* sorting = ExtensionSystem::Get(profile())->app_sorting();
treib9afc6212015-10-30 18:49:58949 sorting->SetAppLaunchOrdinal(app->id(), initial_ordinal.CreateAfter());
950 {
951 syncer::SyncDataList list =
952 extension_sync_service()->GetAllSyncData(syncer::APPS);
953 ASSERT_EQ(list.size(), 1U);
954
dchengc963c7142016-04-08 03:55:22955 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58956 ExtensionSyncData::CreateFromSyncData(list[0]);
957 ASSERT_TRUE(app_sync_data.get());
958 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
959 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
960 }
961
962 sorting->SetPageOrdinal(app->id(), initial_ordinal.CreateAfter());
963 {
964 syncer::SyncDataList list =
965 extension_sync_service()->GetAllSyncData(syncer::APPS);
966 ASSERT_EQ(list.size(), 1U);
967
dchengc963c7142016-04-08 03:55:22968 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58969 ExtensionSyncData::CreateFromSyncData(list[0]);
970 ASSERT_TRUE(app_sync_data.get());
971 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
972 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->page_ordinal()));
973 }
974}
975
976// TODO (rdevlin.cronin): The OnExtensionMoved() method has been removed from
977// ExtensionService, so this test probably needs a new home. Unfortunately, it
978// relies pretty heavily on things like InitializeExtension[Sync]Service() and
979// PackAndInstallCRX(). When we clean up a bit more, this should move out.
980TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettingsOnExtensionMoved) {
981 InitializeEmptyExtensionService();
982 const size_t kAppCount = 3;
983 const Extension* apps[kAppCount];
984 apps[0] = PackAndInstallCRX(data_dir().AppendASCII("app1"), INSTALL_NEW);
985 apps[1] = PackAndInstallCRX(data_dir().AppendASCII("app2"), INSTALL_NEW);
986 apps[2] = PackAndInstallCRX(data_dir().AppendASCII("app4"), INSTALL_NEW);
987 for (size_t i = 0; i < kAppCount; ++i) {
988 ASSERT_TRUE(apps[i]);
989 ASSERT_TRUE(apps[i]->is_app());
990 }
991
treib9afc6212015-10-30 18:49:58992 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36993 syncer::APPS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22994 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
995 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58996
deepak.m14ba69e62015-11-17 05:42:12997 ExtensionSystem::Get(service()->GetBrowserContext())
treib9afc6212015-10-30 18:49:58998 ->app_sorting()
999 ->OnExtensionMoved(apps[0]->id(), apps[1]->id(), apps[2]->id());
1000 {
1001 syncer::SyncDataList list =
1002 extension_sync_service()->GetAllSyncData(syncer::APPS);
1003 ASSERT_EQ(list.size(), 3U);
1004
dchengc963c7142016-04-08 03:55:221005 std::unique_ptr<ExtensionSyncData> data[kAppCount];
treib9afc6212015-10-30 18:49:581006 for (size_t i = 0; i < kAppCount; ++i) {
1007 data[i] = ExtensionSyncData::CreateFromSyncData(list[i]);
1008 ASSERT_TRUE(data[i].get());
1009 }
1010
1011 // The sync data is not always in the same order our apps were installed in,
1012 // so we do that sorting here so we can make sure the values are changed as
1013 // expected.
1014 syncer::StringOrdinal app_launch_ordinals[kAppCount];
1015 for (size_t i = 0; i < kAppCount; ++i) {
1016 for (size_t j = 0; j < kAppCount; ++j) {
1017 if (apps[i]->id() == data[j]->id())
1018 app_launch_ordinals[i] = data[j]->app_launch_ordinal();
1019 }
1020 }
1021
1022 EXPECT_TRUE(app_launch_ordinals[1].LessThan(app_launch_ordinals[0]));
1023 EXPECT_TRUE(app_launch_ordinals[0].LessThan(app_launch_ordinals[2]));
1024 }
1025}
1026
1027TEST_F(ExtensionServiceSyncTest, GetSyncDataList) {
1028 InitializeEmptyExtensionService();
1029 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1030 InstallCRX(data_dir().AppendASCII("page_action.crx"), INSTALL_NEW);
1031 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
1032 InstallCRX(data_dir().AppendASCII("theme2.crx"), INSTALL_NEW);
1033
treib9afc6212015-10-30 18:49:581034 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361035 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111036 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1037 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581038 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361039 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111040 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1041 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581042
Minh X. Nguyen45479012017-08-18 21:35:361043 service()->DisableExtension(page_action,
1044 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:581045 TerminateExtension(theme2_crx);
1046
1047 EXPECT_EQ(0u, extension_sync_service()->GetAllSyncData(syncer::APPS).size());
1048 EXPECT_EQ(
1049 2u, extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS).size());
1050}
1051
1052TEST_F(ExtensionServiceSyncTest, ProcessSyncDataUninstall) {
1053 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581054 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361055 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111056 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1057 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581058
1059 sync_pb::EntitySpecifics specifics;
1060 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1061 ext_specifics->set_id(good_crx);
1062 ext_specifics->set_version("1.0");
treib65f103042015-12-03 10:21:361063
1064 SyncChangeList list =
1065 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:581066
1067 // Should do nothing.
1068 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1069 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
1070
1071 // Install the extension.
1072 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
1073 InstallCRX(extension_path, INSTALL_NEW);
1074 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
1075
1076 // Should uninstall the extension.
1077 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1078 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
1079
1080 // Should again do nothing.
1081 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1082 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
1083}
1084
1085TEST_F(ExtensionServiceSyncTest, ProcessSyncDataWrongType) {
1086 InitializeEmptyExtensionService();
asargente48ab752016-03-12 00:59:201087 StartSyncing(syncer::EXTENSIONS);
1088 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:581089
1090 // Install the extension.
1091 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
1092 InstallCRX(extension_path, INSTALL_NEW);
1093 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
1094
1095 sync_pb::EntitySpecifics specifics;
1096 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
1097 sync_pb::ExtensionSpecifics* extension_specifics =
1098 app_specifics->mutable_extension();
1099 extension_specifics->set_id(good_crx);
1100 extension_specifics->set_version(
Devlin Cronin03bf2d22017-12-20 08:21:051101 service()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581102
1103 {
1104 extension_specifics->set_enabled(true);
treib65f103042015-12-03 10:21:361105
1106 SyncChangeList list =
1107 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:581108
1109 // Should do nothing
1110 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1111 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
1112 }
1113
1114 {
1115 extension_specifics->set_enabled(false);
treib65f103042015-12-03 10:21:361116
1117 SyncChangeList list =
1118 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581119
1120 // Should again do nothing.
1121 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1122 EXPECT_TRUE(service()->GetExtensionById(good_crx, false));
1123 }
1124}
1125
1126TEST_F(ExtensionServiceSyncTest, ProcessSyncDataSettings) {
1127 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581128 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361129 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111130 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1131 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581132
1133 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1134 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1135 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
treib9afc6212015-10-30 18:49:581136
1137 sync_pb::EntitySpecifics specifics;
1138 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1139 ext_specifics->set_id(good_crx);
1140 ext_specifics->set_version(
Devlin Cronin03bf2d22017-12-20 08:21:051141 service()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581142 ext_specifics->set_enabled(false);
1143
1144 {
treib65f103042015-12-03 10:21:361145 SyncChangeList list =
1146 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1147
treib9afc6212015-10-30 18:49:581148 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1149 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1150 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
treib9afc6212015-10-30 18:49:581151 }
1152
1153 {
1154 ext_specifics->set_enabled(true);
1155 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361156
1157 SyncChangeList list =
1158 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1159
treib9afc6212015-10-30 18:49:581160 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1161 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1162 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1163 }
1164
1165 {
1166 ext_specifics->set_enabled(false);
1167 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361168
1169 SyncChangeList list =
1170 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1171
treib9afc6212015-10-30 18:49:581172 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1173 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1174 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1175 }
1176
1177 {
1178 ext_specifics->set_enabled(true);
treib65f103042015-12-03 10:21:361179
1180 SyncChangeList list =
1181 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1182
treib9afc6212015-10-30 18:49:581183 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1184 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
treib9afc6212015-10-30 18:49:581185 }
1186
1187 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1188}
1189
1190TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNewExtension) {
1191 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581192 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361193 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111194 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1195 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581196
1197 const base::FilePath path = data_dir().AppendASCII("good.crx");
1198 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1199
1200 struct TestCase {
1201 const char* name; // For failure output only.
1202 bool sync_enabled; // The "enabled" flag coming in from Sync.
1203 // The disable reason(s) coming in from Sync, or -1 for "not set".
1204 int sync_disable_reasons;
1205 // The disable reason(s) that should be set on the installed extension.
1206 // This will usually be the same as |sync_disable_reasons|, but see the
1207 // "Legacy" case.
1208 int expect_disable_reasons;
1209 // Whether the extension's permissions should be auto-granted during
1210 // installation.
1211 bool expect_permissions_granted;
1212 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361213 // Standard case: Extension comes in enabled; permissions should be
1214 // granted
1215 // during installation.
1216 {"Standard", true, 0, 0, true},
1217 // If the extension comes in disabled, its permissions should still be
1218 // granted (the user already approved them on another machine).
1219 {"Disabled", false, extensions::disable_reason::DISABLE_USER_ACTION,
1220 extensions::disable_reason::DISABLE_USER_ACTION, true},
1221 // Legacy case (<M45): No disable reasons come in from Sync (see
1222 // crbug.com/484214). After installation, the reason should be set to
1223 // DISABLE_USER_ACTION (default assumption).
1224 {"Legacy", false, -1, extensions::disable_reason::DISABLE_USER_ACTION,
1225 true},
1226 // If the extension came in disabled due to a permissions increase, then
1227 // the
1228 // user has *not* approved the permissions, and they shouldn't be granted.
1229 // crbug.com/484214
1230 {"PermissionsIncrease", false,
1231 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
1232 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
treib9afc6212015-10-30 18:49:581233 };
1234
1235 for (const TestCase& test_case : test_cases) {
1236 SCOPED_TRACE(test_case.name);
1237
1238 sync_pb::EntitySpecifics specifics;
1239 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1240 ext_specifics->set_id(good_crx);
1241 ext_specifics->set_version(base::Version("1").GetString());
1242 ext_specifics->set_enabled(test_case.sync_enabled);
1243 if (test_case.sync_disable_reasons != -1)
1244 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1245
treib65f103042015-12-03 10:21:361246 SyncChangeList list =
1247 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1248
treib9afc6212015-10-30 18:49:581249 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1250
1251 ASSERT_TRUE(service()->pending_extension_manager()->IsIdPending(good_crx));
1252 UpdateExtension(good_crx, path, test_case.sync_enabled ? ENABLED
1253 : DISABLED);
1254 EXPECT_EQ(test_case.expect_disable_reasons,
1255 prefs->GetDisableReasons(good_crx));
dchengc963c7142016-04-08 03:55:221256 std::unique_ptr<const PermissionSet> permissions =
treib9afc6212015-10-30 18:49:581257 prefs->GetGrantedPermissions(good_crx);
1258 EXPECT_EQ(test_case.expect_permissions_granted, !permissions->IsEmpty());
1259 ASSERT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
Devlin Cronin7b193412017-12-14 03:46:031260 if (test_case.sync_enabled)
1261 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
1262 else
1263 EXPECT_TRUE(registry()->disabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581264
1265 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031266 UninstallExtension(good_crx);
treib9afc6212015-10-30 18:49:581267 }
1268}
1269
1270TEST_F(ExtensionServiceSyncTest, ProcessSyncDataTerminatedExtension) {
1271 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581272 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361273 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111274 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1275 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581276
1277 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1278 TerminateExtension(good_crx);
1279 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1280 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1281
1282 sync_pb::EntitySpecifics specifics;
1283 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1284 ext_specifics->set_id(good_crx);
1285 ext_specifics->set_version(
Devlin Cronin03bf2d22017-12-20 08:21:051286 service()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581287 ext_specifics->set_enabled(false);
1288 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361289
1290 SyncChangeList list =
1291 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581292
1293 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1294 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1295 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1296
1297 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1298}
1299
1300TEST_F(ExtensionServiceSyncTest, ProcessSyncDataVersionCheck) {
1301 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581302 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361303 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111304 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1305 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581306
1307 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1308 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1309 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1310
1311 sync_pb::EntitySpecifics specifics;
1312 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1313 ext_specifics->set_id(good_crx);
1314 ext_specifics->set_enabled(true);
1315
1316 const base::Version installed_version =
Devlin Cronin03bf2d22017-12-20 08:21:051317 service()->GetInstalledExtension(good_crx)->version();
treib9afc6212015-10-30 18:49:581318
1319 {
1320 ext_specifics->set_version(installed_version.GetString());
treib65f103042015-12-03 10:21:361321
1322 SyncChangeList list =
1323 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581324
1325 // Should do nothing if extension version == sync version.
1326 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1327 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1328 // Make sure the version we'll send back to sync didn't change.
1329 syncer::SyncDataList data =
1330 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1331 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221332 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581333 ExtensionSyncData::CreateFromSyncData(data[0]);
1334 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001335 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581336 }
1337
1338 // Should do nothing if extension version > sync version.
1339 {
1340 ext_specifics->set_version("0.0.0.0");
treib65f103042015-12-03 10:21:361341
1342 SyncChangeList list =
1343 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581344
1345 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1346 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1347 // Make sure the version we'll send back to sync didn't change.
1348 syncer::SyncDataList data =
1349 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1350 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221351 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581352 ExtensionSyncData::CreateFromSyncData(data[0]);
1353 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001354 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581355 }
1356
1357 // Should kick off an update if extension version < sync version.
1358 {
1359 const base::Version new_version("9.9.9.9");
1360 ext_specifics->set_version(new_version.GetString());
treib65f103042015-12-03 10:21:361361
1362 SyncChangeList list =
1363 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581364
1365 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1366 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1367 // Make sure that we'll send the NEW version back to sync, even though we
1368 // haven't actually updated yet. This is to prevent the data in sync from
1369 // flip-flopping back and forth until all clients are up to date.
1370 syncer::SyncDataList data =
1371 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1372 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221373 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581374 ExtensionSyncData::CreateFromSyncData(data[0]);
1375 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001376 EXPECT_EQ(new_version, extension_data->version());
treib9afc6212015-10-30 18:49:581377 }
1378
1379 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1380}
1381
1382TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNotInstalled) {
1383 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581384 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361385 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111386 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1387 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581388
1389 sync_pb::EntitySpecifics specifics;
1390 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1391 ext_specifics->set_id(good_crx);
1392 ext_specifics->set_enabled(false);
1393 ext_specifics->set_incognito_enabled(true);
1394 ext_specifics->set_update_url("http://www.google.com/");
1395 ext_specifics->set_version("1.2.3.4");
treib65f103042015-12-03 10:21:361396
1397 SyncChangeList list =
1398 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581399
1400 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1401 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1402 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1403 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1404 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1405 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1406
1407 const extensions::PendingExtensionInfo* info;
1408 EXPECT_TRUE(
1409 (info = service()->pending_extension_manager()->GetById(good_crx)));
1410 EXPECT_EQ(ext_specifics->update_url(), info->update_url().spec());
1411 EXPECT_TRUE(info->is_from_sync());
1412 EXPECT_EQ(Manifest::INTERNAL, info->install_source());
1413 // TODO(akalin): Figure out a way to test |info.ShouldAllowInstall()|.
1414}
1415
1416TEST_F(ExtensionServiceSyncTest, ProcessSyncDataEnableDisable) {
1417 InitializeEmptyExtensionService();
1418 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361419 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111420 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1421 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581422
1423 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1424
1425 struct TestCase {
1426 const char* name; // For failure output only.
1427 // Set of disable reasons before any Sync data comes in. If this is != 0,
1428 // the extension is disabled.
1429 int previous_disable_reasons;
1430 bool sync_enable; // The enabled flag coming in from Sync.
1431 // The disable reason(s) coming in from Sync, or -1 for "not set".
1432 int sync_disable_reasons;
1433 // The expected set of disable reasons after processing the Sync update. The
1434 // extension should be disabled iff this is != 0.
1435 int expect_disable_reasons;
1436 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361437 {"NopEnable", 0, true, 0, 0},
1438 {"NopDisable", extensions::disable_reason::DISABLE_USER_ACTION, false,
1439 extensions::disable_reason::DISABLE_USER_ACTION,
1440 extensions::disable_reason::DISABLE_USER_ACTION},
1441 {"Enable", extensions::disable_reason::DISABLE_USER_ACTION, true, 0, 0},
1442 {"Disable", 0, false, extensions::disable_reason::DISABLE_USER_ACTION,
1443 extensions::disable_reason::DISABLE_USER_ACTION},
1444 {"AddDisableReason", extensions::disable_reason::DISABLE_REMOTE_INSTALL,
1445 false,
1446 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1447 extensions::disable_reason::DISABLE_USER_ACTION,
1448 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1449 extensions::disable_reason::DISABLE_USER_ACTION},
1450 {"RemoveDisableReason",
1451 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1452 extensions::disable_reason::DISABLE_USER_ACTION,
1453 false, extensions::disable_reason::DISABLE_USER_ACTION,
1454 extensions::disable_reason::DISABLE_USER_ACTION},
1455 {"PreserveLocalDisableReason", extensions::disable_reason::DISABLE_RELOAD,
1456 true, 0, extensions::disable_reason::DISABLE_RELOAD},
1457 {"PreserveOnlyLocalDisableReason",
1458 extensions::disable_reason::DISABLE_USER_ACTION |
1459 extensions::disable_reason::DISABLE_RELOAD,
1460 true, 0, extensions::disable_reason::DISABLE_RELOAD},
treib29e1b9b12015-11-11 08:50:561461
Minh X. Nguyen45479012017-08-18 21:35:361462 // Interaction with Chrome clients <=M44, which don't sync disable_reasons
1463 // at all (any existing reasons are preserved).
1464 {"M44Enable", extensions::disable_reason::DISABLE_USER_ACTION, true, -1,
1465 0},
1466 // An M44 client enables an extension that had been disabled on a new
1467 // client. The disable reasons are still be there, but should be ignored.
1468 {"M44ReEnable", extensions::disable_reason::DISABLE_USER_ACTION, true,
1469 extensions::disable_reason::DISABLE_USER_ACTION, 0},
1470 {"M44Disable", 0, false, -1,
1471 extensions::disable_reason::DISABLE_USER_ACTION},
1472 {"M44ReDisable", 0, false, 0,
1473 extensions::disable_reason::DISABLE_USER_ACTION},
1474 {"M44AlreadyDisabledByUser",
1475 extensions::disable_reason::DISABLE_USER_ACTION, false, -1,
1476 extensions::disable_reason::DISABLE_USER_ACTION},
1477 {"M44AlreadyDisabledWithOtherReason",
1478 extensions::disable_reason::DISABLE_REMOTE_INSTALL, false, -1,
1479 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1480 extensions::disable_reason::DISABLE_USER_ACTION},
treib9afc6212015-10-30 18:49:581481 };
1482
1483 for (const TestCase& test_case : test_cases) {
1484 SCOPED_TRACE(test_case.name);
1485
1486 std::string id;
1487 std::string version;
1488 // Don't keep |extension| around longer than necessary.
1489 {
1490 const Extension* extension =
1491 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1492 // The extension should now be installed and enabled.
1493 ASSERT_TRUE(extension);
1494 id = extension->id();
1495 version = extension->VersionString();
1496 }
1497 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1498
1499 // Disable it if the test case says so.
1500 if (test_case.previous_disable_reasons) {
1501 service()->DisableExtension(id, test_case.previous_disable_reasons);
1502 ASSERT_TRUE(registry()->disabled_extensions().Contains(id));
1503 }
1504
1505 // Now a sync update comes in.
1506 sync_pb::EntitySpecifics specifics;
1507 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1508 ext_specifics->set_id(id);
1509 ext_specifics->set_enabled(test_case.sync_enable);
1510 ext_specifics->set_version(version);
1511 if (test_case.sync_disable_reasons != -1)
1512 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1513
treib65f103042015-12-03 10:21:361514 SyncChangeList list =
1515 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1516
treib9afc6212015-10-30 18:49:581517 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1518
1519 // Check expectations.
1520 const bool expect_enabled = !test_case.expect_disable_reasons;
1521 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1522 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
1523
1524 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031525 UninstallExtension(id);
treib9afc6212015-10-30 18:49:581526 }
1527}
1528
Konstantin Ganenkoae1129c2017-09-15 16:28:591529class ExtensionServiceSyncCustomGalleryTest : public ExtensionServiceSyncTest {
1530 public:
1531 void SetUp() override {
1532 ExtensionServiceSyncTest::SetUp();
rdevlin.cronin2f1ed4c2017-06-13 16:22:131533
Konstantin Ganenkoae1129c2017-09-15 16:28:591534 // This is the update URL specified in the permissions test extension.
1535 // Setting it here is necessary to make the extension considered syncable.
1536 extension_test_util::SetGalleryUpdateURL(
1537 GURL("http://localhost/autoupdate/updates.xml"));
1538 }
1539};
1540
1541TEST_F(ExtensionServiceSyncCustomGalleryTest, ProcessSyncDataDeferredEnable) {
treib9afc6212015-10-30 18:49:581542 InitializeEmptyExtensionService();
1543 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361544 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111545 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1546 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581547
1548 base::FilePath base_path = data_dir().AppendASCII("permissions_increase");
1549 base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1550
1551 base::FilePath path = base_path.AppendASCII("v1");
1552 const Extension* extension = PackAndInstallCRX(path, pem_path, INSTALL_NEW);
1553 // The extension must now be installed and enabled.
1554 ASSERT_TRUE(extension);
1555 ASSERT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
1556
1557 // Save the id, as the extension object will be destroyed during updating.
1558 std::string id = extension->id();
1559
1560 // Update to a new version with increased permissions.
1561 path = base_path.AppendASCII("v2");
1562 PackCRXAndUpdateExtension(id, path, pem_path, DISABLED);
1563
1564 // Now a sync update comes in, telling us to re-enable a *newer* version.
1565 sync_pb::EntitySpecifics specifics;
1566 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1567 ext_specifics->set_id(id);
1568 ext_specifics->set_version("3");
1569 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:361570 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:581571
treib65f103042015-12-03 10:21:361572 SyncChangeList list =
1573 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1574
treib9afc6212015-10-30 18:49:581575 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1576
1577 // Since the version didn't match, the extension should still be disabled.
1578 EXPECT_TRUE(registry()->disabled_extensions().Contains(id));
1579
1580 // After we update to the matching version, the extension should get enabled.
1581 path = base_path.AppendASCII("v3");
1582 PackCRXAndUpdateExtension(id, path, pem_path, ENABLED);
1583}
1584
atuchin2eb18eb2017-03-02 07:22:151585TEST_F(ExtensionServiceSyncCustomGalleryTest,
1586 ProcessSyncDataPermissionApproval) {
treib9afc6212015-10-30 18:49:581587 InitializeEmptyExtensionService();
1588 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361589 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111590 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1591 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581592
1593 const base::FilePath base_path =
1594 data_dir().AppendASCII("permissions_increase");
1595 const base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1596 const base::FilePath path_v1 = base_path.AppendASCII("v1");
1597 const base::FilePath path_v2 = base_path.AppendASCII("v2");
1598
1599 base::ScopedTempDir crx_dir;
1600 ASSERT_TRUE(crx_dir.CreateUniqueTempDir());
vabr9142fe22016-09-08 13:19:221601 const base::FilePath crx_path_v1 = crx_dir.GetPath().AppendASCII("temp1.crx");
treib9afc6212015-10-30 18:49:581602 PackCRX(path_v1, pem_path, crx_path_v1);
vabr9142fe22016-09-08 13:19:221603 const base::FilePath crx_path_v2 = crx_dir.GetPath().AppendASCII("temp2.crx");
treib9afc6212015-10-30 18:49:581604 PackCRX(path_v2, pem_path, crx_path_v2);
1605
1606 const std::string v1("1");
1607 const std::string v2("2");
1608
1609 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1610
1611 struct TestCase {
1612 const char* name; // For failure output only.
1613 const std::string& sync_version; // The version coming in from Sync.
1614 // The disable reason(s) coming in from Sync, or -1 for "not set".
1615 int sync_disable_reasons;
1616 // The expected set of disable reasons after processing the Sync update. The
1617 // extension should be enabled iff this is 0.
1618 int expect_disable_reasons;
1619 // Whether the extension's permissions should be auto-granted.
1620 bool expect_permissions_granted;
1621 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361622 // Sync tells us to re-enable an older version. No permissions should be
1623 // granted, since we can't be sure if the user actually approved the right
1624 // set of permissions.
1625 {"OldVersion", v1, 0,
1626 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
1627 // Legacy case: Sync tells us to re-enable the extension, but doesn't
1628 // specify disable reasons. No permissions should be granted.
1629 {"Legacy", v2, -1,
1630 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
1631 // Sync tells us to re-enable the extension and explicitly removes the
1632 // disable reasons. Now the extension should have its permissions granted.
1633 {"GrantPermissions", v2, 0, extensions::disable_reason::DISABLE_NONE,
1634 true},
treib9afc6212015-10-30 18:49:581635 };
1636
1637 for (const TestCase& test_case : test_cases) {
1638 SCOPED_TRACE(test_case.name);
1639
1640 std::string id;
1641 // Don't keep |extension| around longer than necessary (it'll be destroyed
1642 // during updating).
1643 {
1644 const Extension* extension = InstallCRX(crx_path_v1, INSTALL_NEW);
1645 // The extension should now be installed and enabled.
1646 ASSERT_TRUE(extension);
1647 ASSERT_EQ(v1, extension->VersionString());
1648 id = extension->id();
1649 }
1650 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1651
dchengc963c7142016-04-08 03:55:221652 std::unique_ptr<const PermissionSet> granted_permissions_v1 =
treib9afc6212015-10-30 18:49:581653 prefs->GetGrantedPermissions(id);
1654
1655 // Update to a new version with increased permissions.
1656 UpdateExtension(id, crx_path_v2, DISABLED);
1657
1658 // Now the extension should be disabled due to a permissions increase.
1659 {
1660 const Extension* extension =
1661 registry()->disabled_extensions().GetByID(id);
1662 ASSERT_TRUE(extension);
1663 ASSERT_EQ(v2, extension->VersionString());
1664 }
1665 ASSERT_TRUE(prefs->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:361666 id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE));
treib9afc6212015-10-30 18:49:581667
1668 // No new permissions should have been granted.
dchengc963c7142016-04-08 03:55:221669 std::unique_ptr<const PermissionSet> granted_permissions_v2 =
treib9afc6212015-10-30 18:49:581670 prefs->GetGrantedPermissions(id);
1671 ASSERT_EQ(*granted_permissions_v1, *granted_permissions_v2);
1672
1673 // Now a sync update comes in.
1674 sync_pb::EntitySpecifics specifics;
1675 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1676 ext_specifics->set_id(id);
1677 ext_specifics->set_enabled(true);
1678 ext_specifics->set_version(test_case.sync_version);
1679 if (test_case.sync_disable_reasons != -1)
1680 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1681
treib65f103042015-12-03 10:21:361682 SyncChangeList list =
1683 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1684
treib9afc6212015-10-30 18:49:581685 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1686
1687 // Check expectations.
1688 const bool expect_enabled = !test_case.expect_disable_reasons;
1689 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1690 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
dchengc963c7142016-04-08 03:55:221691 std::unique_ptr<const PermissionSet> granted_permissions =
treib9afc6212015-10-30 18:49:581692 prefs->GetGrantedPermissions(id);
1693 if (test_case.expect_permissions_granted) {
dchengc963c7142016-04-08 03:55:221694 std::unique_ptr<const PermissionSet> active_permissions =
treib9afc6212015-10-30 18:49:581695 prefs->GetActivePermissions(id);
1696 EXPECT_EQ(*granted_permissions, *active_permissions);
1697 } else {
1698 EXPECT_EQ(*granted_permissions, *granted_permissions_v1);
1699 }
1700
1701 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031702 UninstallExtension(id);
treib9afc6212015-10-30 18:49:581703 }
1704}
1705
treib227b2582015-12-09 09:28:261706// Regression test for crbug.com/558299
1707TEST_F(ExtensionServiceSyncTest, DontSyncThemes) {
1708 InitializeEmptyExtensionService();
1709
1710 // The user has enabled sync.
Marc Treib9948a682018-11-20 08:01:371711 ProfileSyncServiceFactory::GetForProfile(profile())
1712 ->GetUserSettings()
1713 ->SetFirstSetupComplete();
treib227b2582015-12-09 09:28:261714 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
1715 extension_sync_service();
1716
1717 service()->Init();
1718 ASSERT_TRUE(service()->is_ready());
1719
1720 syncer::FakeSyncChangeProcessor* processor =
1721 new syncer::FakeSyncChangeProcessor;
1722 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:221723 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
1724 base::WrapUnique(new syncer::SyncErrorFactoryMock));
treib227b2582015-12-09 09:28:261725
1726 processor->changes().clear();
1727
1728 // Sanity check: Installing an extension should result in a sync change.
1729 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1730 EXPECT_EQ(1u, processor->changes().size());
1731
1732 processor->changes().clear();
1733
1734 // Installing a theme should not result in a sync change (themes are handled
1735 // separately by ThemeSyncableService).
1736 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
Evan Stade46d716d2017-06-02 20:50:091737 content::WindowedNotificationObserver theme_change_observer(
1738 chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
1739 content::Source<ThemeService>(
1740 ThemeServiceFactory::GetForProfile(profile())));
1741 theme_change_observer.Wait();
treib227b2582015-12-09 09:28:261742 EXPECT_TRUE(processor->changes().empty());
1743}
1744
brettw9e85ef42016-11-01 21:01:241745#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
treib9afc6212015-10-30 18:49:581746
atuchin2eb18eb2017-03-02 07:22:151747class ExtensionServiceTestSupervised
1748 : public ExtensionServiceSyncCustomGalleryTest,
1749 public SupervisedUserService::Delegate {
treib9afc6212015-10-30 18:49:581750 public:
treibb6af28cd2015-12-01 11:19:461751 ExtensionServiceTestSupervised()
Jinho Bangb5216cec2018-01-17 19:43:111752 : field_trial_list_(std::make_unique<base::MockEntropyProvider>()) {}
treibb6af28cd2015-12-01 11:19:461753
treib9afc6212015-10-30 18:49:581754 void TearDown() override {
1755 supervised_user_service()->SetDelegate(nullptr);
1756
atuchin2eb18eb2017-03-02 07:22:151757 ExtensionServiceSyncCustomGalleryTest::TearDown();
treib9afc6212015-10-30 18:49:581758 }
1759
1760 protected:
mamire9609642016-06-28 22:17:541761 void InitSupervisedUserInitiatedExtensionInstallFeature(bool enabled) {
mamire9609642016-06-28 22:17:541762 if (enabled) {
asvitkineb1db8262016-11-08 09:48:201763 scoped_feature_list_.InitAndEnableFeature(
1764 supervised_users::kSupervisedUserInitiatedExtensionInstall);
mamire9609642016-06-28 22:17:541765 }
mamire9609642016-06-28 22:17:541766 }
1767
mamirf7715a2a2016-07-04 13:05:081768 bool IsPendingCustodianApproval(const std::string& extension_id) {
kylechar1e0dd6b2017-10-03 16:07:511769 auto function = base::MakeRefCounted<
1770 WebstorePrivateIsPendingCustodianApprovalFunction>();
mamirf7715a2a2016-07-04 13:05:081771
1772 std::unique_ptr<base::Value> result(RunFunctionAndReturnSingleResult(
1773 function.get(), "[\"" + extension_id + "\"]", browser_context()));
1774
1775 bool copy_bool_result = false;
1776 EXPECT_TRUE(result->GetAsBoolean(&copy_bool_result));
1777 return copy_bool_result;
1778 }
1779
treib9afc6212015-10-30 18:49:581780 void InitServices(bool profile_is_supervised) {
1781 ExtensionServiceInitParams params = CreateDefaultInitParams();
1782 params.profile_is_supervised = profile_is_supervised;
mamire9609642016-06-28 22:17:541783 // If profile is supervised, don't pass a pref file such that the testing
1784 // profile creates a pref service that uses SupervisedUserPrefStore.
1785 if (profile_is_supervised) {
1786 params.pref_file = base::FilePath();
1787 }
treib9afc6212015-10-30 18:49:581788 InitializeExtensionService(params);
asargente48ab752016-03-12 00:59:201789 StartSyncing(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581790
1791 supervised_user_service()->SetDelegate(this);
1792 supervised_user_service()->Init();
1793 }
1794
mamire9609642016-06-28 22:17:541795 std::string InstallPermissionsTestExtension(bool by_custodian) {
1796 return InstallTestExtension(permissions_increase, dir_path("1"), pem_path(),
1797 by_custodian);
treib9afc6212015-10-30 18:49:581798 }
1799
1800 void UpdatePermissionsTestExtension(const std::string& id,
1801 const std::string& version,
1802 UpdateState expected_state) {
mamire9609642016-06-28 22:17:541803 UpdateTestExtension(dir_path(version), pem_path(), id, version,
1804 expected_state);
1805 }
1806
1807 std::string InstallNoPermissionsTestExtension(bool by_custodian) {
1808 base::FilePath base_path = data_dir().AppendASCII("autoupdate");
1809 base::FilePath pem_path = base_path.AppendASCII("key.pem");
1810 base::FilePath dir_path = base_path.AppendASCII("v1");
1811
1812 return InstallTestExtension(autoupdate, dir_path, pem_path, by_custodian);
1813 }
1814
1815 void UpdateNoPermissionsTestExtension(const std::string& id,
1816 const std::string& version,
1817 UpdateState expected_state) {
1818 base::FilePath base_path = data_dir().AppendASCII("autoupdate");
1819 base::FilePath pem_path = base_path.AppendASCII("key.pem");
1820 base::FilePath dir_path = base_path.AppendASCII("v" + version);
1821
1822 UpdateTestExtension(dir_path, pem_path, id, version, expected_state);
1823 }
1824
1825 std::string InstallTestExtension(const std::string& id,
1826 const base::FilePath& dir_path,
1827 const base::FilePath& pem_path,
1828 bool by_custodian) {
1829 InstallState expected_state = INSTALL_WITHOUT_LOAD;
1830 if (by_custodian) {
1831 extensions::util::SetWasInstalledByCustodian(id, profile(), true);
1832 expected_state = INSTALL_NEW;
1833 }
1834 const Extension* extension =
1835 PackAndInstallCRX(dir_path, pem_path, expected_state);
1836 // The extension must now be installed.
1837 EXPECT_TRUE(extension);
1838 EXPECT_EQ(extension->id(), id);
1839 if (by_custodian) {
1840 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1841 } else {
1842 CheckDisabledForCustodianApproval(id);
1843 }
1844
Devlin Cronin03bf2d22017-12-20 08:21:051845 EXPECT_EQ(base::Version("1"), extension->version());
mamire9609642016-06-28 22:17:541846
1847 return id;
1848 }
1849
1850 void UpdateTestExtension(const base::FilePath& dir_path,
1851 const base::FilePath& pem_path,
1852 const std::string& id,
1853 const std::string& version,
1854 const UpdateState& expected_state) {
1855 PackCRXAndUpdateExtension(id, dir_path, pem_path, expected_state);
treib9afc6212015-10-30 18:49:581856 const Extension* extension = registry()->GetInstalledExtension(id);
1857 ASSERT_TRUE(extension);
1858 // The version should have been updated.
Devlin Cronin03bf2d22017-12-20 08:21:051859 EXPECT_EQ(base::Version(version), extension->version());
mamire9609642016-06-28 22:17:541860 }
1861
1862 // Simulate a custodian approval for enabling the extension coming in
1863 // through Sync by adding the approved version to the map of approved
1864 // extensions. It doesn't simulate a change in the disable reasons.
1865 void SimulateCustodianApprovalChangeViaSync(const std::string& extension_id,
1866 const std::string& version,
1867 SyncChange::SyncChangeType type) {
1868 std::string key = SupervisedUserSettingsService::MakeSplitSettingKey(
1869 supervised_users::kApprovedExtensions, extension_id);
1870 syncer::SyncData sync_data =
1871 SupervisedUserSettingsService::CreateSyncDataForSetting(
jdoerrie122c4da2017-03-06 11:12:041872 key, base::Value(version));
mamire9609642016-06-28 22:17:541873
1874 SyncChangeList list(1, SyncChange(FROM_HERE, type, sync_data));
1875
1876 SupervisedUserSettingsService* supervised_user_settings_service =
1877 SupervisedUserSettingsServiceFactory::GetForProfile(profile());
1878 supervised_user_settings_service->ProcessSyncChanges(FROM_HERE, list);
1879 }
1880
1881 void CheckDisabledForCustodianApproval(const std::string& extension_id) {
1882 EXPECT_TRUE(registry()->disabled_extensions().Contains(extension_id));
1883 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile());
1884 EXPECT_TRUE(extension_prefs->HasDisableReason(
1885 extension_id,
Minh X. Nguyen45479012017-08-18 21:35:361886 extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
treib9afc6212015-10-30 18:49:581887 }
1888
1889 SupervisedUserService* supervised_user_service() {
1890 return SupervisedUserServiceFactory::GetForProfile(profile());
1891 }
1892
mamire9609642016-06-28 22:17:541893 static std::string RequestId(const std::string& extension_id,
1894 const std::string& version) {
1895 return SupervisedUserService::GetExtensionRequestId(
treib9afc6212015-10-30 18:49:581896 extension_id, base::Version(version));
1897 }
1898
1899 private:
1900 // This prevents the legacy supervised user init code from running.
1901 bool SetActive(bool active) override { return true; }
1902
1903 base::FilePath base_path() const {
1904 return data_dir().AppendASCII("permissions_increase");
1905 }
1906 base::FilePath dir_path(const std::string& version) const {
1907 return base_path().AppendASCII("v" + version);
1908 }
1909 base::FilePath pem_path() const {
1910 return base_path().AppendASCII("permissions.pem");
1911 }
treibb6af28cd2015-12-01 11:19:461912
1913 base::FieldTrialList field_trial_list_;
asvitkineb1db8262016-11-08 09:48:201914 base::test::ScopedFeatureList scoped_feature_list_;
treib9afc6212015-10-30 18:49:581915};
1916
1917class MockPermissionRequestCreator : public PermissionRequestCreator {
1918 public:
1919 MockPermissionRequestCreator() {}
1920 ~MockPermissionRequestCreator() override {}
1921
1922 bool IsEnabled() const override { return true; }
1923
1924 void CreateURLAccessRequest(const GURL& url_requested,
Carlos IL6b784a62018-03-20 00:26:491925 SuccessCallback callback) override {
treib9afc6212015-10-30 18:49:581926 FAIL();
1927 }
1928
Carlos IL6b784a62018-03-20 00:26:491929 void CreateExtensionInstallRequest(
1930 const std::string& id,
1931 SupervisedUserService::SuccessCallback callback) override {
1932 CreateExtensionInstallRequestInternal(id);
1933 }
mamire9609642016-06-28 22:17:541934
Carlos IL6b784a62018-03-20 00:26:491935 void CreateExtensionUpdateRequest(
1936 const std::string& id,
1937 SupervisedUserService::SuccessCallback callback) override {
1938 CreateExtensionUpdateRequestInternal(id);
1939 }
1940
1941 // TODO(crbug.com/729950): These two mock methods can be set to direct calls
1942 // once gtest supports move-only objects, since SuccessCallback is move only.
1943 MOCK_METHOD1(CreateExtensionInstallRequestInternal,
1944 void(const std::string& id));
1945
1946 MOCK_METHOD1(CreateExtensionUpdateRequestInternal,
1947 void(const std::string& id));
treib9afc6212015-10-30 18:49:581948
1949 private:
1950 DISALLOW_COPY_AND_ASSIGN(MockPermissionRequestCreator);
1951};
1952
1953TEST_F(ExtensionServiceTestSupervised, InstallOnlyAllowedByCustodian) {
mamire9609642016-06-28 22:17:541954 InitSupervisedUserInitiatedExtensionInstallFeature(false);
treib9afc6212015-10-30 18:49:581955
Mikel Astiza68eea52018-10-05 07:59:141956 InitServices(true /* profile_is_supervised */);
1957
mamir192d7882016-06-22 17:10:161958 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
1959
treib9afc6212015-10-30 18:49:581960 base::FilePath path1 = data_dir().AppendASCII("good.crx");
1961 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
1962 const Extension* extensions[] = {
1963 InstallCRX(path1, INSTALL_FAILED),
mamir192d7882016-06-22 17:10:161964 InstallCRX(path2, INSTALL_NEW)
treib9afc6212015-10-30 18:49:581965 };
1966
1967 // Only the extension with the "installed by custodian" flag should have been
1968 // installed and enabled.
1969 EXPECT_FALSE(extensions[0]);
1970 ASSERT_TRUE(extensions[1]);
1971 EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id()));
mamirf7715a2a2016-07-04 13:05:081972 EXPECT_FALSE(IsPendingCustodianApproval(extensions[1]->id()));
treib9afc6212015-10-30 18:49:581973}
1974
mamir192d7882016-06-22 17:10:161975TEST_F(ExtensionServiceTestSupervised,
1976 DelegatedAndPreinstalledExtensionIsSUFirst) {
mamire9609642016-06-28 22:17:541977 InitSupervisedUserInitiatedExtensionInstallFeature(false);
mamir192d7882016-06-22 17:10:161978
Mikel Astiza68eea52018-10-05 07:59:141979 InitServices(false /* profile_is_supervised */);
1980
mamir192d7882016-06-22 17:10:161981 // Install an extension.
1982 base::FilePath path = data_dir().AppendASCII("good.crx");
1983 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1984 std::string id = extension->id();
1985 const std::string version("1.0.0.0");
1986 // It should be enabled.
1987 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1988
1989 // Now make the profile supervised.
1990 profile()->AsTestingProfile()->SetSupervisedUserId(
1991 supervised_users::kChildAccountSUID);
1992
1993 // It should not be enabled now (it is not loaded at all actually).
1994 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
1995
1996 // Simulate data sync with the "was_installed_by_custodian" flag set to 1.
1997 sync_pb::EntitySpecifics specifics;
1998 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1999 ext_specifics->set_id(id);
2000 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:362001 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
mamir192d7882016-06-22 17:10:162002 ext_specifics->set_installed_by_custodian(true);
2003 ext_specifics->set_version(version);
2004
2005 SyncChangeList list =
2006 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2007
2008 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
2009
2010 // The extension should be enabled again.
2011 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2012 EXPECT_TRUE(extensions::util::WasInstalledByCustodian(id, profile()));
2013}
2014
2015TEST_F(ExtensionServiceTestSupervised,
2016 DelegatedAndPreinstalledExtensionSyncFirst) {
mamire9609642016-06-28 22:17:542017 InitSupervisedUserInitiatedExtensionInstallFeature(false);
mamir192d7882016-06-22 17:10:162018
Mikel Astiza68eea52018-10-05 07:59:142019 InitServices(false /* profile_is_supervised */);
2020
mamir192d7882016-06-22 17:10:162021 // Install an extension.
2022 base::FilePath path = data_dir().AppendASCII("good.crx");
2023 const Extension* extension = InstallCRX(path, INSTALL_NEW);
2024 std::string id = extension->id();
2025 const std::string version("1.0.0.0");
2026
2027 // It should be enabled.
2028 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2029
2030 // Simulate data sync with the "was_installed_by_custodian" flag set to 1.
2031 sync_pb::EntitySpecifics specifics;
2032 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2033 ext_specifics->set_id(id);
2034 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:362035 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
mamir192d7882016-06-22 17:10:162036 ext_specifics->set_installed_by_custodian(true);
2037 ext_specifics->set_version(version);
2038
2039 SyncChangeList list =
2040 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2041
2042 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
mamir192d7882016-06-22 17:10:162043 // The extension should be enabled.
2044 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2045 EXPECT_TRUE(extensions::util::WasInstalledByCustodian(id, profile()));
2046}
2047
mamire9609642016-06-28 22:17:542048TEST_F(ExtensionServiceTestSupervised,
2049 InstallAllowedByCustodianAndSupervisedUser) {
mamire9609642016-06-28 22:17:542050 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2051
Mikel Astiza68eea52018-10-05 07:59:142052 InitServices(true /* profile_is_supervised */);
2053
mamire9609642016-06-28 22:17:542054 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
2055
2056 base::FilePath path1 = data_dir().AppendASCII("good.crx");
2057 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
2058 const Extension* extensions[] = {
2059 InstallCRX(path1, INSTALL_WITHOUT_LOAD),
2060 InstallCRX(path2, INSTALL_NEW)
2061 };
2062
2063 // Only the extension with the "installed by custodian" flag should have been
2064 // installed and enabled.
2065 // The extension missing the "installed by custodian" flag is a
2066 // supervised user initiated install and hence not enabled.
2067 ASSERT_TRUE(extensions[0]);
2068 ASSERT_TRUE(extensions[1]);
2069 EXPECT_TRUE(registry()->disabled_extensions().Contains(extensions[0]->id()));
mamirf7715a2a2016-07-04 13:05:082070 EXPECT_TRUE(IsPendingCustodianApproval(extensions[0]->id()));
mamire9609642016-06-28 22:17:542071 EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id()));
mamirf7715a2a2016-07-04 13:05:082072 EXPECT_FALSE(IsPendingCustodianApproval(extensions[1]->id()));
mamire9609642016-06-28 22:17:542073}
2074
2075TEST_F(ExtensionServiceTestSupervised,
2076 PreinstalledExtensionWithSUInitiatedInstalls) {
mamire9609642016-06-28 22:17:542077 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2078
Mikel Astiza68eea52018-10-05 07:59:142079 InitServices(false /* profile_is_supervised */);
2080
mamire9609642016-06-28 22:17:542081 // Install an extension.
2082 base::FilePath path = data_dir().AppendASCII("good.crx");
2083 const Extension* extension = InstallCRX(path, INSTALL_NEW);
2084 std::string id = extension->id();
2085 // Make sure it's enabled.
2086 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2087
2088 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2089 supervised_user_service()->AddPermissionRequestCreator(
2090 base::WrapUnique(creator));
2091 const std::string version("1.0.0.0");
2092
Carlos IL6b784a62018-03-20 00:26:492093 EXPECT_CALL(*creator, CreateExtensionInstallRequestInternal(
2094 RequestId(good_crx, version)));
mamire9609642016-06-28 22:17:542095
2096 // Now make the profile supervised.
2097 profile()->AsTestingProfile()->SetSupervisedUserId(
2098 supervised_users::kChildAccountSUID);
2099
2100 Mock::VerifyAndClearExpectations(creator);
2101
2102 // The extension should not be enabled anymore.
2103 CheckDisabledForCustodianApproval(id);
mamirf7715a2a2016-07-04 13:05:082104 EXPECT_TRUE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542105}
2106
2107TEST_F(ExtensionServiceTestSupervised,
2108 PreinstalledExtensionWithoutSUInitiatedInstalls) {
mamire9609642016-06-28 22:17:542109 InitSupervisedUserInitiatedExtensionInstallFeature(false);
2110
Mikel Astiza68eea52018-10-05 07:59:142111 InitServices(false /* profile_is_supervised */);
2112
mamire9609642016-06-28 22:17:542113 // Install an extension.
2114 base::FilePath path = data_dir().AppendASCII("good.crx");
2115 const Extension* extension = InstallCRX(path, INSTALL_NEW);
2116 std::string id = extension->id();
2117
2118 // Make sure it's enabled.
2119 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2120
2121 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2122 supervised_user_service()->AddPermissionRequestCreator(
2123 base::WrapUnique(creator));
2124 const std::string version("1.0.0.0");
2125
2126 // No request should be sent because supervised user initiated installs
2127 // are disabled.
Carlos IL6b784a62018-03-20 00:26:492128 EXPECT_CALL(*creator, CreateExtensionInstallRequestInternal(testing::_))
mamire9609642016-06-28 22:17:542129 .Times(0);
2130
2131 // Now make the profile supervised.
2132 profile()->AsTestingProfile()->SetSupervisedUserId(
2133 supervised_users::kChildAccountSUID);
2134
Karan Bhatia2a117232017-08-23 00:24:562135 // The extension should now be disabled.
2136 EXPECT_TRUE(registry()->disabled_extensions().Contains(id));
2137 EXPECT_EQ(extensions::disable_reason::DISABLE_BLOCKED_BY_POLICY,
2138 ExtensionPrefs::Get(profile())->GetDisableReasons(id));
mamire9609642016-06-28 22:17:542139}
2140
2141TEST_F(ExtensionServiceTestSupervised, ExtensionApprovalBeforeInstallation) {
2142 // This tests the case when the sync entity flagging the extension as approved
2143 // arrives before the extension itself is installed.
mamire9609642016-06-28 22:17:542144 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2145
Mikel Astiza68eea52018-10-05 07:59:142146 InitServices(true /* profile_is_supervised */);
2147
mamire9609642016-06-28 22:17:542148 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2149 supervised_user_service()->AddPermissionRequestCreator(
2150 base::WrapUnique(creator));
2151
2152 std::string id = good_crx;
2153 std::string version("1.0.0.0");
2154
2155 SimulateCustodianApprovalChangeViaSync(id, version, SyncChange::ACTION_ADD);
2156
2157 // Now install an extension.
2158 base::FilePath path = data_dir().AppendASCII("good.crx");
2159 InstallCRX(path, INSTALL_NEW);
2160
2161 // No approval request should be sent.
Carlos IL6b784a62018-03-20 00:26:492162 EXPECT_CALL(*creator, CreateExtensionInstallRequestInternal(testing::_))
mamire9609642016-06-28 22:17:542163 .Times(0);
2164
2165 // Make sure it's enabled.
2166 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082167 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542168}
2169
treib9afc6212015-10-30 18:49:582170TEST_F(ExtensionServiceTestSupervised, UpdateWithoutPermissionIncrease) {
2171 InitServices(true /* profile_is_supervised */);
2172
treib9afc6212015-10-30 18:49:582173 // Save the id, as the extension object will be destroyed during updating.
mamire9609642016-06-28 22:17:542174 std::string id = InstallNoPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582175
2176 // Update to a new version.
mamire9609642016-06-28 22:17:542177 std::string version2("2");
2178 UpdateNoPermissionsTestExtension(id, version2, ENABLED);
treib9afc6212015-10-30 18:49:582179
2180 // The extension should still be there and enabled.
mamire9609642016-06-28 22:17:542181 const Extension* extension = registry()->enabled_extensions().GetByID(id);
treib9afc6212015-10-30 18:49:582182 ASSERT_TRUE(extension);
2183 // The version should have changed.
Devlin Cronin03bf2d22017-12-20 08:21:052184 EXPECT_EQ(base::Version(version2), extension->version());
mamirf7715a2a2016-07-04 13:05:082185 EXPECT_FALSE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582186}
2187
treib9afc6212015-10-30 18:49:582188TEST_F(ExtensionServiceTestSupervised,
2189 UpdateWithPermissionIncreaseApprovalOldVersion) {
treib9afc6212015-10-30 18:49:582190 InitServices(true /* profile_is_supervised */);
2191
2192 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2193 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222194 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582195
2196 const std::string version1("1");
2197 const std::string version2("2");
2198
mamire9609642016-06-28 22:17:542199 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582200
2201 // Update to a new version with increased permissions.
Carlos IL6b784a62018-03-20 00:26:492202 EXPECT_CALL(*creator,
2203 CreateExtensionUpdateRequestInternal(RequestId(id, version2)));
treib9afc6212015-10-30 18:49:582204 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542205 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082206 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582207
2208 // Simulate a custodian approval for re-enabling the extension coming in
2209 // through Sync, but set the old version. This can happen when there already
2210 // was a pending request for an earlier version of the extension.
2211 sync_pb::EntitySpecifics specifics;
2212 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2213 ext_specifics->set_id(id);
2214 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:362215 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:582216 ext_specifics->set_installed_by_custodian(true);
2217 ext_specifics->set_version(version1);
2218
2219 // Attempting to re-enable an old version should result in a permission
2220 // request for the current version.
Carlos IL6b784a62018-03-20 00:26:492221 EXPECT_CALL(*creator,
2222 CreateExtensionUpdateRequestInternal(RequestId(id, version2)));
treib9afc6212015-10-30 18:49:582223
treib65f103042015-12-03 10:21:362224 SyncChangeList list =
2225 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2226
2227 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582228 // The re-enable should be ignored, since the version doesn't match.
2229 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2230 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
2231 id, base::Version(version1)));
2232 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
2233 id, base::Version(version2)));
mamire9609642016-06-28 22:17:542234 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082235 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582236}
2237
2238TEST_F(ExtensionServiceTestSupervised,
2239 UpdateWithPermissionIncreaseApprovalMatchingVersion) {
treib9afc6212015-10-30 18:49:582240 InitServices(true /* profile_is_supervised */);
2241
2242 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2243 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222244 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582245
mamire9609642016-06-28 22:17:542246 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582247
2248 // Update to a new version with increased permissions.
2249 const std::string version2("2");
Carlos IL6b784a62018-03-20 00:26:492250 EXPECT_CALL(*creator,
2251 CreateExtensionUpdateRequestInternal(RequestId(id, version2)));
treib9afc6212015-10-30 18:49:582252 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542253 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082254 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582255
2256 // Simulate a custodian approval for re-enabling the extension coming in
2257 // through Sync.
2258 sync_pb::EntitySpecifics specifics;
2259 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2260 ext_specifics->set_id(id);
2261 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:362262 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:582263 ext_specifics->set_installed_by_custodian(true);
2264 ext_specifics->set_version(version2);
2265
treib65f103042015-12-03 10:21:362266 SyncChangeList list =
2267 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2268
2269 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582270 // The extension should have gotten re-enabled.
2271 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082272 EXPECT_FALSE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582273}
2274
2275TEST_F(ExtensionServiceTestSupervised,
2276 UpdateWithPermissionIncreaseApprovalNewVersion) {
treib9afc6212015-10-30 18:49:582277 InitServices(true /* profile_is_supervised */);
2278
2279 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2280 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222281 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582282
mamire9609642016-06-28 22:17:542283 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582284
2285 // Update to a new version with increased permissions.
2286 const std::string version2("2");
Carlos IL6b784a62018-03-20 00:26:492287 EXPECT_CALL(*creator,
2288 CreateExtensionUpdateRequestInternal(RequestId(id, version2)));
treib9afc6212015-10-30 18:49:582289 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542290 Mock::VerifyAndClearExpectations(creator);
treib9afc6212015-10-30 18:49:582291
2292 // Simulate a custodian approval for re-enabling the extension coming in
2293 // through Sync. Set a newer version than we have installed.
2294 const std::string version3("3");
2295 sync_pb::EntitySpecifics specifics;
2296 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2297 ext_specifics->set_id(id);
2298 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:362299 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:582300 ext_specifics->set_installed_by_custodian(true);
2301 ext_specifics->set_version(version3);
2302
2303 // This should *not* result in a new permission request.
Carlos IL6b784a62018-03-20 00:26:492304 EXPECT_CALL(*creator,
2305 CreateExtensionUpdateRequestInternal(RequestId(id, version3)))
treib9afc6212015-10-30 18:49:582306 .Times(0);
2307
treib65f103042015-12-03 10:21:362308 SyncChangeList list =
2309 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2310
2311 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582312 // The re-enable should be delayed until the extension is updated to the
2313 // matching version.
2314 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2315 EXPECT_TRUE(extension_sync_service()->HasPendingReenable(
2316 id, base::Version(version3)));
2317
2318 // Update to the matching version. Now the extension should get enabled.
2319 UpdatePermissionsTestExtension(id, version3, ENABLED);
2320}
2321
mamire9609642016-06-28 22:17:542322TEST_F(ExtensionServiceTestSupervised, SupervisedUserInitiatedInstalls) {
mamire9609642016-06-28 22:17:542323 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2324
2325 InitServices(true /* profile_is_supervised */);
2326
2327 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2328 supervised_user_service()->AddPermissionRequestCreator(
2329 base::WrapUnique(creator));
2330
2331 base::FilePath path = data_dir().AppendASCII("good.crx");
2332 std::string version("1.0.0.0");
2333
Carlos IL6b784a62018-03-20 00:26:492334 EXPECT_CALL(*creator, CreateExtensionInstallRequestInternal(
2335 RequestId(good_crx, version)));
mamire9609642016-06-28 22:17:542336
2337 // Should be installed but disabled, a request for approval should be sent.
2338 const Extension* extension = InstallCRX(path, INSTALL_WITHOUT_LOAD);
2339 ASSERT_TRUE(extension);
2340 ASSERT_EQ(extension->id(), good_crx);
2341 EXPECT_TRUE(registry()->disabled_extensions().Contains(good_crx));
2342 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082343 EXPECT_TRUE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542344
2345 SimulateCustodianApprovalChangeViaSync(good_crx, version,
2346 SyncChange::ACTION_ADD);
2347
2348 // The extension should be enabled now.
2349 EXPECT_TRUE(registry()->enabled_extensions().Contains(good_crx));
mamirf7715a2a2016-07-04 13:05:082350 EXPECT_FALSE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542351
2352 // Simulate approval removal coming via Sync.
2353 SimulateCustodianApprovalChangeViaSync(good_crx, version,
2354 SyncChange::ACTION_DELETE);
2355
2356 // The extension should be disabled now.
2357 EXPECT_TRUE(registry()->disabled_extensions().Contains(good_crx));
mamirf7715a2a2016-07-04 13:05:082358 EXPECT_TRUE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542359}
2360
2361TEST_F(ExtensionServiceTestSupervised,
2362 UpdateSUInitiatedInstallWithoutPermissionIncrease) {
mamire9609642016-06-28 22:17:542363 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2364
2365 InitServices(true /* profile_is_supervised */);
2366
2367 std::string id = InstallNoPermissionsTestExtension(false /* by_custodian */);
2368 std::string version1("1");
2369
2370 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2371
2372 // The extension should be enabled now.
2373 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2374
2375 std::string version2("2");
2376
2377 // Update to a new version.
2378 UpdateNoPermissionsTestExtension(id, version2, ENABLED);
2379
2380 // The extension should still be there and enabled.
2381 const Extension* extension = registry()->enabled_extensions().GetByID(id);
2382 ASSERT_TRUE(extension);
2383 // The version should have increased.
Devlin Cronin03bf2d22017-12-20 08:21:052384 EXPECT_EQ(1, extension->version().CompareTo(base::Version(version1)));
mamire9609642016-06-28 22:17:542385
2386 // Check that the approved version has been updated in the prefs as well.
2387 // Prefs are updated via Sync. If the prefs are updated, then the new
2388 // approved version has been pushed to Sync as well.
2389 std::string approved_version;
2390 PrefService* pref_service = profile()->GetPrefs();
2391 const base::DictionaryValue* approved_extensions =
2392 pref_service->GetDictionary(prefs::kSupervisedUserApprovedExtensions);
2393 approved_extensions->GetStringWithoutPathExpansion(id, &approved_version);
2394
Devlin Cronin03bf2d22017-12-20 08:21:052395 EXPECT_EQ(base::Version(approved_version), extension->version());
mamirf7715a2a2016-07-04 13:05:082396 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542397}
2398
2399TEST_F(ExtensionServiceTestSupervised,
2400 UpdateSUInitiatedInstallWithPermissionIncrease) {
mamire9609642016-06-28 22:17:542401 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2402
2403 InitServices(true /* profile_is_supervised */);
2404
2405 std::string id = InstallPermissionsTestExtension(false /* by_custodian */);
2406 std::string version1("1");
2407
2408 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2409
2410 // The extension should be enabled now.
2411 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2412
2413 std::string version3("3");
2414
2415 UpdatePermissionsTestExtension(id, version3, DISABLED);
2416
2417 // The extension should be disabled.
2418 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2419 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:362420 id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE));
mamire9609642016-06-28 22:17:542421
2422 std::string version2("2");
2423 // Approve an older version
2424 SimulateCustodianApprovalChangeViaSync(id, version2,
2425 SyncChange::ACTION_UPDATE);
2426
2427 // The extension should remain disabled.
2428 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2429 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:362430 id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE));
mamire9609642016-06-28 22:17:542431 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:362432 id, extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
mamire9609642016-06-28 22:17:542433
mamirf7715a2a2016-07-04 13:05:082434 EXPECT_TRUE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542435 // Approve the latest version
2436 SimulateCustodianApprovalChangeViaSync(id, version3,
2437 SyncChange::ACTION_UPDATE);
2438
2439 // The extension should be enabled again.
2440 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082441 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542442}
2443
2444TEST_F(ExtensionServiceTestSupervised,
2445 UpdateSUInitiatedInstallWithPermissionIncreaseApprovalArrivesFirst) {
mamire9609642016-06-28 22:17:542446 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2447
2448 InitServices(true /* profile_is_supervised */);
2449
2450 std::string id = InstallPermissionsTestExtension(false /* by_custodian */);
2451
2452 std::string version1("1");
2453 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2454
2455 // The extension should be enabled now.
2456 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2457
2458 std::string version2("2");
2459 // Approve a newer version
2460 SimulateCustodianApprovalChangeViaSync(id, version2,
2461 SyncChange::ACTION_UPDATE);
2462
2463 // The extension should be disabled.
2464 CheckDisabledForCustodianApproval(id);
2465
2466 // Now update the extension to the same version that was approved.
2467 UpdatePermissionsTestExtension(id, version2, ENABLED);
2468 // The extension should be enabled again.
2469 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082470 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542471}
2472
treib9afc6212015-10-30 18:49:582473TEST_F(ExtensionServiceSyncTest, SyncUninstallByCustodianSkipsPolicy) {
2474 InitializeEmptyExtensionService();
2475 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:362476 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:112477 std::make_unique<syncer::FakeSyncChangeProcessor>(),
2478 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:582479
mamir192d7882016-06-22 17:10:162480 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
treib9afc6212015-10-30 18:49:582481 // Install two extensions.
2482 base::FilePath path1 = data_dir().AppendASCII("good.crx");
2483 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
2484 const Extension* extensions[] = {
2485 InstallCRX(path1, INSTALL_NEW),
mamir192d7882016-06-22 17:10:162486 InstallCRX(path2, INSTALL_NEW)
treib9afc6212015-10-30 18:49:582487 };
2488
2489 // Add a policy provider that will disallow any changes.
2490 extensions::TestManagementPolicyProvider provider(
2491 extensions::TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS);
2492 ExtensionSystem::Get(
2493 browser_context())->management_policy()->RegisterProvider(&provider);
2494
2495 // Create a sync deletion for each extension.
treib65f103042015-12-03 10:21:362496 SyncChangeList list;
Avi Drissman5f0fb8c2018-12-25 23:20:492497 for (size_t i = 0; i < base::size(extensions); i++) {
treib9afc6212015-10-30 18:49:582498 const std::string& id = extensions[i]->id();
2499 sync_pb::EntitySpecifics specifics;
2500 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2501 ext_specifics->set_id(id);
2502 ext_specifics->set_version("1.0");
2503 ext_specifics->set_installed_by_custodian(
mamir192d7882016-06-22 17:10:162504 extensions::util::WasInstalledByCustodian(id, profile()));
2505
treib9afc6212015-10-30 18:49:582506 syncer::SyncData sync_data =
2507 syncer::SyncData::CreateLocalData(id, "Name", specifics);
treib65f103042015-12-03 10:21:362508 list.push_back(SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, sync_data));
treib9afc6212015-10-30 18:49:582509 }
2510
2511 // Save the extension ids, as uninstalling destroys the Extension instance.
2512 std::string extension_ids[] = {
2513 extensions[0]->id(),
2514 extensions[1]->id()
2515 };
2516
2517 // Now apply the uninstallations.
treib65f103042015-12-03 10:21:362518 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582519
2520 // Uninstalling the extension without installed_by_custodian should have been
2521 // blocked by policy, so it should still be there.
2522 EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_ids[0]));
2523
2524 // But installed_by_custodian should result in bypassing the policy check.
2525 EXPECT_FALSE(
2526 registry()->GenerateInstalledExtensionsSet()->Contains(extension_ids[1]));
2527}
2528
brettw9e85ef42016-11-01 21:01:242529#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
asargente48ab752016-03-12 00:59:202530
2531// Tests sync behavior in the case of an item that starts out as an app and
2532// gets updated to become an extension.
2533TEST_F(ExtensionServiceSyncTest, AppToExtension) {
2534 InitializeEmptyExtensionService();
2535 service()->Init();
2536 ASSERT_TRUE(service()->is_ready());
2537
2538 // Install v1, which is an app.
2539 const Extension* v1 =
2540 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v1.crx"),
2541 INSTALL_NEW);
2542 EXPECT_TRUE(v1->is_app());
2543 EXPECT_FALSE(v1->is_extension());
2544 std::string id = v1->id();
2545
2546 StatefulChangeProcessor extensions_processor(syncer::ModelType::EXTENSIONS);
2547 StatefulChangeProcessor apps_processor(syncer::ModelType::APPS);
2548 extension_sync_service()->MergeDataAndStartSyncing(
2549 syncer::EXTENSIONS, syncer::SyncDataList(),
2550 extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222551 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202552 extension_sync_service()->MergeDataAndStartSyncing(
2553 syncer::APPS, syncer::SyncDataList(), apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222554 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202555
2556 // Check the app/extension change processors to be sure the right data was
2557 // added.
2558 EXPECT_TRUE(extensions_processor.changes().empty());
2559 EXPECT_TRUE(extensions_processor.data().empty());
2560 EXPECT_EQ(1u, apps_processor.data().size());
2561 ASSERT_EQ(1u, apps_processor.changes().size());
2562 const SyncChange& app_change = apps_processor.changes()[0];
2563 EXPECT_EQ(SyncChange::ACTION_ADD, app_change.change_type());
dchengc963c7142016-04-08 03:55:222564 std::unique_ptr<ExtensionSyncData> app_data =
asargente48ab752016-03-12 00:59:202565 ExtensionSyncData::CreateFromSyncData(app_change.sync_data());
2566 EXPECT_TRUE(app_data->is_app());
2567 EXPECT_EQ(id, app_data->id());
Devlin Cronin03bf2d22017-12-20 08:21:052568 EXPECT_EQ(v1->version(), app_data->version());
asargente48ab752016-03-12 00:59:202569
2570 // Update the app to v2, which is an extension.
2571 const Extension* v2 =
2572 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v2.crx"),
2573 INSTALL_UPDATED);
2574 EXPECT_FALSE(v2->is_app());
2575 EXPECT_TRUE(v2->is_extension());
2576 EXPECT_EQ(id, v2->id());
2577
2578 // Make sure we saw an extension item added.
2579 ASSERT_EQ(1u, extensions_processor.changes().size());
2580 const SyncChange& extension_change = extensions_processor.changes()[0];
2581 EXPECT_EQ(SyncChange::ACTION_ADD, extension_change.change_type());
dchengc963c7142016-04-08 03:55:222582 std::unique_ptr<ExtensionSyncData> extension_data =
asargente48ab752016-03-12 00:59:202583 ExtensionSyncData::CreateFromSyncData(extension_change.sync_data());
2584 EXPECT_FALSE(extension_data->is_app());
2585 EXPECT_EQ(id, extension_data->id());
Devlin Cronin03bf2d22017-12-20 08:21:052586 EXPECT_EQ(v2->version(), extension_data->version());
asargente48ab752016-03-12 00:59:202587
2588 // Get the current data from the change processors to use as the input to
2589 // the following call to MergeDataAndStartSyncing. This simulates what should
2590 // happen with sync.
2591 syncer::SyncDataList extensions_data =
2592 extensions_processor.GetAllSyncData(syncer::EXTENSIONS);
2593 syncer::SyncDataList apps_data = apps_processor.GetAllSyncData(syncer::APPS);
2594
2595 // Stop syncing, then start again.
2596 extension_sync_service()->StopSyncing(syncer::EXTENSIONS);
2597 extension_sync_service()->StopSyncing(syncer::APPS);
2598 extension_sync_service()->MergeDataAndStartSyncing(
2599 syncer::EXTENSIONS, extensions_data, extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222600 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202601 extension_sync_service()->MergeDataAndStartSyncing(
2602 syncer::APPS, apps_data, apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222603 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202604
2605 // Make sure we saw an app item deleted.
2606 bool found_delete = false;
2607 for (const auto& change : apps_processor.changes()) {
2608 if (change.change_type() == SyncChange::ACTION_DELETE) {
dchengc963c7142016-04-08 03:55:222609 std::unique_ptr<ExtensionSyncData> data =
asargente48ab752016-03-12 00:59:202610 ExtensionSyncData::CreateFromSyncChange(change);
2611 if (data->id() == id) {
2612 found_delete = true;
2613 break;
2614 }
2615 }
2616 }
2617 EXPECT_TRUE(found_delete);
2618
2619 // Make sure there is one extension, and there are no more apps.
2620 EXPECT_EQ(1u, extensions_processor.data().size());
2621 EXPECT_TRUE(apps_processor.data().empty());
2622}
proberge901ecab2017-08-31 19:24:282623
2624class BlacklistedExtensionSyncServiceTest : public ExtensionServiceSyncTest {
2625 public:
2626 BlacklistedExtensionSyncServiceTest() {}
2627
2628 void SetUp() override {
2629 ExtensionServiceSyncTest::SetUp();
2630
2631 InitializeEmptyExtensionService();
2632
2633 // Enable sync.
Marc Treib5a78e9c2019-02-19 16:47:012634 syncer::SyncService* sync_service =
proberge901ecab2017-08-31 19:24:282635 ProfileSyncServiceFactory::GetForProfile(profile());
Marc Treib9948a682018-11-20 08:01:372636 sync_service->GetUserSettings()->SetFirstSetupComplete();
proberge901ecab2017-08-31 19:24:282637
2638 test_blacklist_.Attach(service()->blacklist_);
2639 service()->Init();
2640
2641 // Load up a simple extension.
2642 extensions::ChromeTestExtensionLoader extension_loader(profile());
2643 extension_loader.set_pack_extension(true);
2644 extension_ = extension_loader.LoadExtension(
2645 data_dir().AppendASCII("simple_with_file"));
2646 ASSERT_TRUE(extension_);
2647 extension_id_ = extension_->id();
2648 ASSERT_TRUE(registry()->enabled_extensions().GetByID(extension_id_));
2649
2650 {
Jinho Bangb5216cec2018-01-17 19:43:112651 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
proberge901ecab2017-08-31 19:24:282652 processor_raw_ = processor.get();
2653 extension_sync_service()->MergeDataAndStartSyncing(
2654 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:112655 std::make_unique<syncer::SyncErrorFactoryMock>());
proberge901ecab2017-08-31 19:24:282656 }
2657 processor_raw_->changes().clear();
2658 }
2659
2660 void ForceBlacklistUpdate() {
2661 service()->OnBlacklistUpdated();
Gabriel Charette01507a22017-09-27 21:30:082662 content::RunAllTasksUntilIdle();
proberge901ecab2017-08-31 19:24:282663 }
2664
2665 syncer::FakeSyncChangeProcessor* processor() { return processor_raw_; }
2666
2667 const Extension* extension() { return extension_.get(); }
2668
2669 std::string& extension_id() { return extension_id_; }
2670
2671 extensions::TestBlacklist& test_blacklist() { return test_blacklist_; }
2672
2673 private:
2674 syncer::FakeSyncChangeProcessor* processor_raw_;
2675 scoped_refptr<const Extension> extension_;
2676 std::string extension_id_;
2677 extensions::TestBlacklist test_blacklist_;
2678
2679 DISALLOW_COPY_AND_ASSIGN(BlacklistedExtensionSyncServiceTest);
2680};
2681
2682// Test that sync cannot enable blacklisted extensions.
2683TEST_F(BlacklistedExtensionSyncServiceTest, SyncBlacklistedExtension) {
2684 std::string& extension_id = this->extension_id();
2685
2686 // Blacklist the extension.
2687 test_blacklist().SetBlacklistState(extension_id,
2688 extensions::BLACKLISTED_MALWARE, true);
2689 ForceBlacklistUpdate();
2690
2691 // Try enabling the extension via sync.
2692 EnableExtensionFromSync(*extension());
2693
2694 // The extension should not be enabled.
2695 EXPECT_FALSE(registry()->enabled_extensions().GetByID(extension_id));
2696 EXPECT_TRUE(processor()->changes().empty());
2697}
2698
2699// Test that some greylisted extensions can be enabled through sync.
2700TEST_F(BlacklistedExtensionSyncServiceTest, SyncAllowedGreylistedExtension) {
2701 std::string& extension_id = this->extension_id();
2702
2703 // Greylist the extension.
2704 test_blacklist().SetBlacklistState(
2705 extension_id, extensions::BLACKLISTED_POTENTIALLY_UNWANTED, true);
2706 ForceBlacklistUpdate();
2707
2708 EXPECT_FALSE(registry()->enabled_extensions().GetByID(extension_id));
2709 {
2710 ASSERT_EQ(1u, processor()->changes().size());
2711 const SyncChange& change = processor()->changes()[0];
2712 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
2713 std::unique_ptr<ExtensionSyncData> data =
2714 ExtensionSyncData::CreateFromSyncData(change.sync_data());
2715 EXPECT_EQ(extension_id, data->id());
2716 EXPECT_EQ(extensions::disable_reason::DISABLE_GREYLIST,
2717 data->disable_reasons());
2718 EXPECT_FALSE(data->enabled());
2719 }
2720 processor()->changes().clear();
2721
2722 // Manually re-enabling the extension should work.
2723 service()->EnableExtension(extension_id);
2724 EXPECT_TRUE(registry()->enabled_extensions().GetByID(extension_id));
2725 {
2726 ASSERT_EQ(1u, processor()->changes().size());
2727 const SyncChange& change = processor()->changes()[0];
2728 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
2729 std::unique_ptr<ExtensionSyncData> data =
2730 ExtensionSyncData::CreateFromSyncData(change.sync_data());
2731 EXPECT_EQ(extension_id, data->id());
2732 EXPECT_EQ(0, data->disable_reasons());
2733 EXPECT_TRUE(data->enabled());
2734 }
2735 processor()->changes().clear();
2736}