blob: 5028d676f53ee53a40a4674708952640ed21a7b2 [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"
avia2f4804a2015-12-24 23:11:1315#include "base/macros.h"
dchengc963c7142016-04-08 03:55:2216#include "base/memory/ptr_util.h"
treib9afc6212015-10-30 18:49:5817#include "base/memory/weak_ptr.h"
18#include "base/metrics/field_trial.h"
19#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.
maxbogue0a379452016-09-22 21:35:05347 browser_sync::ProfileSyncService* sync_service =
treib9afc6212015-10-30 18:49:58348 ProfileSyncServiceFactory::GetForProfile(profile());
maxboguefe00952a2016-01-19 19:02:01349 sync_service->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.
383 browser_sync::ProfileSyncService* sync_service =
384 ProfileSyncServiceFactory::GetForProfile(profile());
385 sync_service->SetFirstSetupComplete();
386
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.
465 browser_sync::ProfileSyncService* sync_service =
466 ProfileSyncServiceFactory::GetForProfile(profile());
467 sync_service->SetFirstSetupComplete();
468
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.
maxbogue0a379452016-09-22 21:35:05531 browser_sync::ProfileSyncService* sync_service =
treib9afc6212015-10-30 18:49:58532 ProfileSyncServiceFactory::GetForProfile(profile());
maxboguefe00952a2016-01-19 19:02:01533 sync_service->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.
maxboguefe00952a2016-01-19 19:02:01592 ProfileSyncServiceFactory::GetForProfile(profile())->SetFirstSetupComplete();
treibb794dd52015-12-01 18:47:14593 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
594 extension_sync_service();
595
596 service()->Init();
597 ASSERT_TRUE(service()->is_ready());
598 ASSERT_EQ(3u, loaded_.size());
599 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
600
601 syncer::FakeSyncChangeProcessor* processor =
602 new syncer::FakeSyncChangeProcessor;
603 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:22604 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
Jinho Bangb5216cec2018-01-17 19:43:11605 std::make_unique<syncer::SyncErrorFactoryMock>());
treibb794dd52015-12-01 18:47:14606
607 processor->changes().clear();
608
609 // Simulate various incoming sync changes, and make sure they don't result in
610 // any outgoing changes.
611
612 {
613 const Extension* extension = service()->GetExtensionById(good0, true);
614 ASSERT_TRUE(extension);
615
616 // Disable the extension.
Devlin Cronin93beb23d2018-05-04 21:17:35617 ExtensionSyncData data(*extension, false,
618 extensions::disable_reason::DISABLE_USER_ACTION,
Devlin Cronin56daf35132018-05-10 16:25:33619 false, false, false);
treib65f103042015-12-03 10:21:36620 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14621
622 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
623
624 EXPECT_TRUE(processor->changes().empty());
625 }
626
627 {
628 const Extension* extension = service()->GetExtensionById(good0, true);
629 ASSERT_TRUE(extension);
630
631 // Set incognito enabled to true.
Minh X. Nguyen45479012017-08-18 21:35:36632 ExtensionSyncData data(*extension, false,
633 extensions::disable_reason::DISABLE_NONE, true,
Devlin Cronin56daf35132018-05-10 16:25:33634 false, false);
treib65f103042015-12-03 10:21:36635 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14636
637 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
638
639 EXPECT_TRUE(processor->changes().empty());
640 }
641
642 {
643 const Extension* extension = service()->GetExtensionById(good0, true);
644 ASSERT_TRUE(extension);
645
646 // Add another disable reason.
Minh X. Nguyen45479012017-08-18 21:35:36647 ExtensionSyncData data(
648 *extension, false,
649 extensions::disable_reason::DISABLE_USER_ACTION |
650 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
Devlin Cronin56daf35132018-05-10 16:25:33651 false, false, false);
treib65f103042015-12-03 10:21:36652 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14653
654 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
655
656 EXPECT_TRUE(processor->changes().empty());
657 }
658
659 {
660 const Extension* extension = service()->GetExtensionById(good0, true);
661 ASSERT_TRUE(extension);
662
663 // Uninstall the extension.
Minh X. Nguyen45479012017-08-18 21:35:36664 ExtensionSyncData data(
665 *extension, false,
666 extensions::disable_reason::DISABLE_USER_ACTION |
667 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
Devlin Cronin56daf35132018-05-10 16:25:33668 false, false, false);
treib65f103042015-12-03 10:21:36669 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_DELETE));
treibb794dd52015-12-01 18:47:14670
671 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
672
673 EXPECT_TRUE(processor->changes().empty());
674 }
675}
676
treib9afc6212015-10-30 18:49:58677TEST_F(ExtensionServiceSyncTest, GetSyncData) {
678 InitializeEmptyExtensionService();
679 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
680 const Extension* extension = service()->GetInstalledExtension(good_crx);
681 ASSERT_TRUE(extension);
682
683 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36684 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11685 std::make_unique<syncer::FakeSyncChangeProcessor>(),
686 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58687
688 syncer::SyncDataList list =
689 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
690 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22691 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58692 ExtensionSyncData::CreateFromSyncData(list[0]);
693 ASSERT_TRUE(data.get());
694 EXPECT_EQ(extension->id(), data->id());
695 EXPECT_FALSE(data->uninstalled());
696 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
697 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
698 data->incognito_enabled());
Devlin Cronin03bf2d22017-12-20 08:21:05699 EXPECT_EQ(data->version(), extension->version());
treib9afc6212015-10-30 18:49:58700 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
701 data->update_url());
702 EXPECT_EQ(extension->name(), data->name());
703}
704
treib29e1b9b12015-11-11 08:50:56705TEST_F(ExtensionServiceSyncTest, GetSyncDataDisableReasons) {
706 InitializeEmptyExtensionService();
707 const Extension* extension =
708 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
709 ASSERT_TRUE(extension);
710
treib29e1b9b12015-11-11 08:50:56711 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36712 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11713 std::make_unique<syncer::FakeSyncChangeProcessor>(),
714 std::make_unique<syncer::SyncErrorFactoryMock>());
treib29e1b9b12015-11-11 08:50:56715
716 {
717 syncer::SyncDataList list =
718 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
719 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22720 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56721 ExtensionSyncData::CreateFromSyncData(list[0]);
722 ASSERT_TRUE(data.get());
723 EXPECT_TRUE(data->enabled());
724 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36725 EXPECT_EQ(extensions::disable_reason::DISABLE_NONE,
726 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56727 }
728
729 // Syncable disable reason, should propagate to sync.
Minh X. Nguyen45479012017-08-18 21:35:36730 service()->DisableExtension(good_crx,
731 extensions::disable_reason::DISABLE_USER_ACTION);
treib29e1b9b12015-11-11 08:50:56732 {
733 syncer::SyncDataList list =
734 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
735 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22736 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56737 ExtensionSyncData::CreateFromSyncData(list[0]);
738 ASSERT_TRUE(data.get());
739 EXPECT_FALSE(data->enabled());
740 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36741 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
742 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56743 }
744 service()->EnableExtension(good_crx);
745
746 // Non-syncable disable reason. The sync data should still say "enabled".
Minh X. Nguyen45479012017-08-18 21:35:36747 service()->DisableExtension(good_crx,
748 extensions::disable_reason::DISABLE_RELOAD);
treib29e1b9b12015-11-11 08:50:56749 {
750 syncer::SyncDataList list =
751 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
752 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22753 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56754 ExtensionSyncData::CreateFromSyncData(list[0]);
755 ASSERT_TRUE(data.get());
756 EXPECT_TRUE(data->enabled());
757 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36758 EXPECT_EQ(extensions::disable_reason::DISABLE_NONE,
759 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56760 }
761 service()->EnableExtension(good_crx);
762
763 // Both a syncable and a non-syncable disable reason, only the former should
764 // propagate to sync.
Minh X. Nguyen45479012017-08-18 21:35:36765 service()->DisableExtension(good_crx,
766 extensions::disable_reason::DISABLE_USER_ACTION |
767 extensions::disable_reason::DISABLE_RELOAD);
treib29e1b9b12015-11-11 08:50:56768 {
769 syncer::SyncDataList list =
770 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
771 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22772 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56773 ExtensionSyncData::CreateFromSyncData(list[0]);
774 ASSERT_TRUE(data.get());
775 EXPECT_FALSE(data->enabled());
776 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36777 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
778 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56779 }
780 service()->EnableExtension(good_crx);
781}
782
treib9afc6212015-10-30 18:49:58783TEST_F(ExtensionServiceSyncTest, GetSyncDataTerminated) {
784 InitializeEmptyExtensionService();
785 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
786 TerminateExtension(good_crx);
787 const Extension* extension = service()->GetInstalledExtension(good_crx);
788 ASSERT_TRUE(extension);
789
treib9afc6212015-10-30 18:49:58790 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36791 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11792 std::make_unique<syncer::FakeSyncChangeProcessor>(),
793 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58794
795 syncer::SyncDataList list =
796 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
797 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22798 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58799 ExtensionSyncData::CreateFromSyncData(list[0]);
800 ASSERT_TRUE(data.get());
801 EXPECT_EQ(extension->id(), data->id());
802 EXPECT_FALSE(data->uninstalled());
803 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
804 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
805 data->incognito_enabled());
Devlin Cronin03bf2d22017-12-20 08:21:05806 EXPECT_EQ(data->version(), extension->version());
treib9afc6212015-10-30 18:49:58807 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
808 data->update_url());
809 EXPECT_EQ(extension->name(), data->name());
810}
811
812TEST_F(ExtensionServiceSyncTest, GetSyncDataFilter) {
813 InitializeEmptyExtensionService();
814 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
815 const Extension* extension = service()->GetInstalledExtension(good_crx);
816 ASSERT_TRUE(extension);
817
treib9afc6212015-10-30 18:49:58818 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36819 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11820 std::make_unique<syncer::FakeSyncChangeProcessor>(),
821 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58822
823 syncer::SyncDataList list =
824 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
825 ASSERT_EQ(list.size(), 0U);
826}
827
828TEST_F(ExtensionServiceSyncTest, GetSyncExtensionDataUserSettings) {
829 InitializeEmptyExtensionService();
830 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
831 const Extension* extension = service()->GetInstalledExtension(good_crx);
832 ASSERT_TRUE(extension);
833
treib9afc6212015-10-30 18:49:58834 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36835 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11836 std::make_unique<syncer::FakeSyncChangeProcessor>(),
837 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58838
839 {
840 syncer::SyncDataList list =
841 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
842 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22843 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58844 ExtensionSyncData::CreateFromSyncData(list[0]);
845 ASSERT_TRUE(data.get());
846 EXPECT_TRUE(data->enabled());
847 EXPECT_FALSE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58848 }
849
Minh X. Nguyen45479012017-08-18 21:35:36850 service()->DisableExtension(good_crx,
851 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:58852 {
853 syncer::SyncDataList list =
854 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
855 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22856 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58857 ExtensionSyncData::CreateFromSyncData(list[0]);
858 ASSERT_TRUE(data.get());
859 EXPECT_FALSE(data->enabled());
860 EXPECT_FALSE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58861 }
862
863 extensions::util::SetIsIncognitoEnabled(good_crx, profile(), true);
treib9afc6212015-10-30 18:49:58864 {
865 syncer::SyncDataList list =
866 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
867 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22868 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58869 ExtensionSyncData::CreateFromSyncData(list[0]);
870 ASSERT_TRUE(data.get());
871 EXPECT_FALSE(data->enabled());
872 EXPECT_TRUE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58873 }
874
875 service()->EnableExtension(good_crx);
treib9afc6212015-10-30 18:49:58876 {
877 syncer::SyncDataList list =
878 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
879 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22880 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58881 ExtensionSyncData::CreateFromSyncData(list[0]);
882 ASSERT_TRUE(data.get());
883 EXPECT_TRUE(data->enabled());
884 EXPECT_TRUE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58885 }
886}
887
888TEST_F(ExtensionServiceSyncTest, SyncForUninstalledExternalExtension) {
889 InitializeEmptyExtensionService();
catmullings22bc2372016-11-02 19:59:35890 InstallCRX(data_dir().AppendASCII("good.crx"), Manifest::EXTERNAL_PREF,
891 INSTALL_NEW, Extension::NO_FLAGS);
treib9afc6212015-10-30 18:49:58892 const Extension* extension = service()->GetInstalledExtension(good_crx);
893 ASSERT_TRUE(extension);
894
treib9afc6212015-10-30 18:49:58895 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36896 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11897 std::make_unique<syncer::FakeSyncChangeProcessor>(),
898 std::make_unique<syncer::SyncErrorFactoryMock>());
asargente48ab752016-03-12 00:59:20899 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:58900
Devlin Cronin6fd1cd62017-12-05 19:13:57901 UninstallExtension(good_crx);
treib9afc6212015-10-30 18:49:58902 EXPECT_TRUE(
903 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
904
905 sync_pb::EntitySpecifics specifics;
906 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
907 sync_pb::ExtensionSpecifics* extension_specifics =
908 app_specifics->mutable_extension();
909 extension_specifics->set_id(good_crx);
910 extension_specifics->set_version("1.0");
911 extension_specifics->set_enabled(true);
912
treib65f103042015-12-03 10:21:36913 SyncChangeList list =
914 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:58915
916 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
917 EXPECT_TRUE(
918 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
919}
920
921TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettings) {
922 InitializeEmptyExtensionService();
923 const Extension* app =
924 PackAndInstallCRX(data_dir().AppendASCII("app"), INSTALL_NEW);
925 ASSERT_TRUE(app);
926 ASSERT_TRUE(app->is_app());
927
treib9afc6212015-10-30 18:49:58928 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36929 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11930 std::make_unique<syncer::FakeSyncChangeProcessor>(),
931 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58932
933 syncer::StringOrdinal initial_ordinal =
934 syncer::StringOrdinal::CreateInitialOrdinal();
935 {
936 syncer::SyncDataList list =
937 extension_sync_service()->GetAllSyncData(syncer::APPS);
938 ASSERT_EQ(list.size(), 1U);
939
dchengc963c7142016-04-08 03:55:22940 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58941 ExtensionSyncData::CreateFromSyncData(list[0]);
942 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->app_launch_ordinal()));
943 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
944 }
945
deepak.m14ba69e62015-11-17 05:42:12946 AppSorting* sorting = ExtensionSystem::Get(profile())->app_sorting();
treib9afc6212015-10-30 18:49:58947 sorting->SetAppLaunchOrdinal(app->id(), initial_ordinal.CreateAfter());
948 {
949 syncer::SyncDataList list =
950 extension_sync_service()->GetAllSyncData(syncer::APPS);
951 ASSERT_EQ(list.size(), 1U);
952
dchengc963c7142016-04-08 03:55:22953 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58954 ExtensionSyncData::CreateFromSyncData(list[0]);
955 ASSERT_TRUE(app_sync_data.get());
956 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
957 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
958 }
959
960 sorting->SetPageOrdinal(app->id(), initial_ordinal.CreateAfter());
961 {
962 syncer::SyncDataList list =
963 extension_sync_service()->GetAllSyncData(syncer::APPS);
964 ASSERT_EQ(list.size(), 1U);
965
dchengc963c7142016-04-08 03:55:22966 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58967 ExtensionSyncData::CreateFromSyncData(list[0]);
968 ASSERT_TRUE(app_sync_data.get());
969 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
970 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->page_ordinal()));
971 }
972}
973
974// TODO (rdevlin.cronin): The OnExtensionMoved() method has been removed from
975// ExtensionService, so this test probably needs a new home. Unfortunately, it
976// relies pretty heavily on things like InitializeExtension[Sync]Service() and
977// PackAndInstallCRX(). When we clean up a bit more, this should move out.
978TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettingsOnExtensionMoved) {
979 InitializeEmptyExtensionService();
980 const size_t kAppCount = 3;
981 const Extension* apps[kAppCount];
982 apps[0] = PackAndInstallCRX(data_dir().AppendASCII("app1"), INSTALL_NEW);
983 apps[1] = PackAndInstallCRX(data_dir().AppendASCII("app2"), INSTALL_NEW);
984 apps[2] = PackAndInstallCRX(data_dir().AppendASCII("app4"), INSTALL_NEW);
985 for (size_t i = 0; i < kAppCount; ++i) {
986 ASSERT_TRUE(apps[i]);
987 ASSERT_TRUE(apps[i]->is_app());
988 }
989
treib9afc6212015-10-30 18:49:58990 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36991 syncer::APPS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22992 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
993 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58994
deepak.m14ba69e62015-11-17 05:42:12995 ExtensionSystem::Get(service()->GetBrowserContext())
treib9afc6212015-10-30 18:49:58996 ->app_sorting()
997 ->OnExtensionMoved(apps[0]->id(), apps[1]->id(), apps[2]->id());
998 {
999 syncer::SyncDataList list =
1000 extension_sync_service()->GetAllSyncData(syncer::APPS);
1001 ASSERT_EQ(list.size(), 3U);
1002
dchengc963c7142016-04-08 03:55:221003 std::unique_ptr<ExtensionSyncData> data[kAppCount];
treib9afc6212015-10-30 18:49:581004 for (size_t i = 0; i < kAppCount; ++i) {
1005 data[i] = ExtensionSyncData::CreateFromSyncData(list[i]);
1006 ASSERT_TRUE(data[i].get());
1007 }
1008
1009 // The sync data is not always in the same order our apps were installed in,
1010 // so we do that sorting here so we can make sure the values are changed as
1011 // expected.
1012 syncer::StringOrdinal app_launch_ordinals[kAppCount];
1013 for (size_t i = 0; i < kAppCount; ++i) {
1014 for (size_t j = 0; j < kAppCount; ++j) {
1015 if (apps[i]->id() == data[j]->id())
1016 app_launch_ordinals[i] = data[j]->app_launch_ordinal();
1017 }
1018 }
1019
1020 EXPECT_TRUE(app_launch_ordinals[1].LessThan(app_launch_ordinals[0]));
1021 EXPECT_TRUE(app_launch_ordinals[0].LessThan(app_launch_ordinals[2]));
1022 }
1023}
1024
1025TEST_F(ExtensionServiceSyncTest, GetSyncDataList) {
1026 InitializeEmptyExtensionService();
1027 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1028 InstallCRX(data_dir().AppendASCII("page_action.crx"), INSTALL_NEW);
1029 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
1030 InstallCRX(data_dir().AppendASCII("theme2.crx"), INSTALL_NEW);
1031
treib9afc6212015-10-30 18:49:581032 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361033 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111034 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1035 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581036 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361037 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111038 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1039 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581040
Minh X. Nguyen45479012017-08-18 21:35:361041 service()->DisableExtension(page_action,
1042 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:581043 TerminateExtension(theme2_crx);
1044
1045 EXPECT_EQ(0u, extension_sync_service()->GetAllSyncData(syncer::APPS).size());
1046 EXPECT_EQ(
1047 2u, extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS).size());
1048}
1049
1050TEST_F(ExtensionServiceSyncTest, ProcessSyncDataUninstall) {
1051 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581052 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361053 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111054 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1055 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581056
1057 sync_pb::EntitySpecifics specifics;
1058 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1059 ext_specifics->set_id(good_crx);
1060 ext_specifics->set_version("1.0");
treib65f103042015-12-03 10:21:361061
1062 SyncChangeList list =
1063 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:581064
1065 // Should do nothing.
1066 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1067 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
1068
1069 // Install the extension.
1070 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
1071 InstallCRX(extension_path, INSTALL_NEW);
1072 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
1073
1074 // Should uninstall the extension.
1075 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1076 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
1077
1078 // Should again do nothing.
1079 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1080 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
1081}
1082
1083TEST_F(ExtensionServiceSyncTest, ProcessSyncDataWrongType) {
1084 InitializeEmptyExtensionService();
asargente48ab752016-03-12 00:59:201085 StartSyncing(syncer::EXTENSIONS);
1086 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:581087
1088 // Install the extension.
1089 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
1090 InstallCRX(extension_path, INSTALL_NEW);
1091 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
1092
1093 sync_pb::EntitySpecifics specifics;
1094 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
1095 sync_pb::ExtensionSpecifics* extension_specifics =
1096 app_specifics->mutable_extension();
1097 extension_specifics->set_id(good_crx);
1098 extension_specifics->set_version(
Devlin Cronin03bf2d22017-12-20 08:21:051099 service()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581100
1101 {
1102 extension_specifics->set_enabled(true);
treib65f103042015-12-03 10:21:361103
1104 SyncChangeList list =
1105 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:581106
1107 // Should do nothing
1108 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1109 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
1110 }
1111
1112 {
1113 extension_specifics->set_enabled(false);
treib65f103042015-12-03 10:21:361114
1115 SyncChangeList list =
1116 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581117
1118 // Should again do nothing.
1119 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1120 EXPECT_TRUE(service()->GetExtensionById(good_crx, false));
1121 }
1122}
1123
1124TEST_F(ExtensionServiceSyncTest, ProcessSyncDataSettings) {
1125 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581126 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361127 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111128 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1129 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581130
1131 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1132 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1133 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
treib9afc6212015-10-30 18:49:581134
1135 sync_pb::EntitySpecifics specifics;
1136 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1137 ext_specifics->set_id(good_crx);
1138 ext_specifics->set_version(
Devlin Cronin03bf2d22017-12-20 08:21:051139 service()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581140 ext_specifics->set_enabled(false);
1141
1142 {
treib65f103042015-12-03 10:21:361143 SyncChangeList list =
1144 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1145
treib9afc6212015-10-30 18:49:581146 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1147 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1148 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
treib9afc6212015-10-30 18:49:581149 }
1150
1151 {
1152 ext_specifics->set_enabled(true);
1153 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361154
1155 SyncChangeList list =
1156 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1157
treib9afc6212015-10-30 18:49:581158 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1159 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1160 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1161 }
1162
1163 {
1164 ext_specifics->set_enabled(false);
1165 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361166
1167 SyncChangeList list =
1168 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1169
treib9afc6212015-10-30 18:49:581170 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1171 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1172 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1173 }
1174
1175 {
1176 ext_specifics->set_enabled(true);
treib65f103042015-12-03 10:21:361177
1178 SyncChangeList list =
1179 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1180
treib9afc6212015-10-30 18:49:581181 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1182 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
treib9afc6212015-10-30 18:49:581183 }
1184
1185 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1186}
1187
1188TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNewExtension) {
1189 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581190 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361191 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111192 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1193 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581194
1195 const base::FilePath path = data_dir().AppendASCII("good.crx");
1196 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1197
1198 struct TestCase {
1199 const char* name; // For failure output only.
1200 bool sync_enabled; // The "enabled" flag coming in from Sync.
1201 // The disable reason(s) coming in from Sync, or -1 for "not set".
1202 int sync_disable_reasons;
1203 // The disable reason(s) that should be set on the installed extension.
1204 // This will usually be the same as |sync_disable_reasons|, but see the
1205 // "Legacy" case.
1206 int expect_disable_reasons;
1207 // Whether the extension's permissions should be auto-granted during
1208 // installation.
1209 bool expect_permissions_granted;
1210 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361211 // Standard case: Extension comes in enabled; permissions should be
1212 // granted
1213 // during installation.
1214 {"Standard", true, 0, 0, true},
1215 // If the extension comes in disabled, its permissions should still be
1216 // granted (the user already approved them on another machine).
1217 {"Disabled", false, extensions::disable_reason::DISABLE_USER_ACTION,
1218 extensions::disable_reason::DISABLE_USER_ACTION, true},
1219 // Legacy case (<M45): No disable reasons come in from Sync (see
1220 // crbug.com/484214). After installation, the reason should be set to
1221 // DISABLE_USER_ACTION (default assumption).
1222 {"Legacy", false, -1, extensions::disable_reason::DISABLE_USER_ACTION,
1223 true},
1224 // If the extension came in disabled due to a permissions increase, then
1225 // the
1226 // user has *not* approved the permissions, and they shouldn't be granted.
1227 // crbug.com/484214
1228 {"PermissionsIncrease", false,
1229 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
1230 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
treib9afc6212015-10-30 18:49:581231 };
1232
1233 for (const TestCase& test_case : test_cases) {
1234 SCOPED_TRACE(test_case.name);
1235
1236 sync_pb::EntitySpecifics specifics;
1237 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1238 ext_specifics->set_id(good_crx);
1239 ext_specifics->set_version(base::Version("1").GetString());
1240 ext_specifics->set_enabled(test_case.sync_enabled);
1241 if (test_case.sync_disable_reasons != -1)
1242 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1243
treib65f103042015-12-03 10:21:361244 SyncChangeList list =
1245 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1246
treib9afc6212015-10-30 18:49:581247 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1248
1249 ASSERT_TRUE(service()->pending_extension_manager()->IsIdPending(good_crx));
1250 UpdateExtension(good_crx, path, test_case.sync_enabled ? ENABLED
1251 : DISABLED);
1252 EXPECT_EQ(test_case.expect_disable_reasons,
1253 prefs->GetDisableReasons(good_crx));
dchengc963c7142016-04-08 03:55:221254 std::unique_ptr<const PermissionSet> permissions =
treib9afc6212015-10-30 18:49:581255 prefs->GetGrantedPermissions(good_crx);
1256 EXPECT_EQ(test_case.expect_permissions_granted, !permissions->IsEmpty());
1257 ASSERT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
Devlin Cronin7b193412017-12-14 03:46:031258 if (test_case.sync_enabled)
1259 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
1260 else
1261 EXPECT_TRUE(registry()->disabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581262
1263 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031264 UninstallExtension(good_crx);
treib9afc6212015-10-30 18:49:581265 }
1266}
1267
1268TEST_F(ExtensionServiceSyncTest, ProcessSyncDataTerminatedExtension) {
1269 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581270 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361271 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111272 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1273 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581274
1275 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1276 TerminateExtension(good_crx);
1277 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1278 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1279
1280 sync_pb::EntitySpecifics specifics;
1281 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1282 ext_specifics->set_id(good_crx);
1283 ext_specifics->set_version(
Devlin Cronin03bf2d22017-12-20 08:21:051284 service()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581285 ext_specifics->set_enabled(false);
1286 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361287
1288 SyncChangeList list =
1289 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581290
1291 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1292 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1293 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1294
1295 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1296}
1297
1298TEST_F(ExtensionServiceSyncTest, ProcessSyncDataVersionCheck) {
1299 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581300 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361301 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111302 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1303 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581304
1305 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1306 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1307 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1308
1309 sync_pb::EntitySpecifics specifics;
1310 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1311 ext_specifics->set_id(good_crx);
1312 ext_specifics->set_enabled(true);
1313
1314 const base::Version installed_version =
Devlin Cronin03bf2d22017-12-20 08:21:051315 service()->GetInstalledExtension(good_crx)->version();
treib9afc6212015-10-30 18:49:581316
1317 {
1318 ext_specifics->set_version(installed_version.GetString());
treib65f103042015-12-03 10:21:361319
1320 SyncChangeList list =
1321 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581322
1323 // Should do nothing if extension version == sync version.
1324 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1325 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1326 // Make sure the version we'll send back to sync didn't change.
1327 syncer::SyncDataList data =
1328 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1329 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221330 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581331 ExtensionSyncData::CreateFromSyncData(data[0]);
1332 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001333 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581334 }
1335
1336 // Should do nothing if extension version > sync version.
1337 {
1338 ext_specifics->set_version("0.0.0.0");
treib65f103042015-12-03 10:21:361339
1340 SyncChangeList list =
1341 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581342
1343 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1344 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1345 // Make sure the version we'll send back to sync didn't change.
1346 syncer::SyncDataList data =
1347 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1348 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221349 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581350 ExtensionSyncData::CreateFromSyncData(data[0]);
1351 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001352 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581353 }
1354
1355 // Should kick off an update if extension version < sync version.
1356 {
1357 const base::Version new_version("9.9.9.9");
1358 ext_specifics->set_version(new_version.GetString());
treib65f103042015-12-03 10:21:361359
1360 SyncChangeList list =
1361 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581362
1363 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1364 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1365 // Make sure that we'll send the NEW version back to sync, even though we
1366 // haven't actually updated yet. This is to prevent the data in sync from
1367 // flip-flopping back and forth until all clients are up to date.
1368 syncer::SyncDataList data =
1369 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1370 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221371 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581372 ExtensionSyncData::CreateFromSyncData(data[0]);
1373 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001374 EXPECT_EQ(new_version, extension_data->version());
treib9afc6212015-10-30 18:49:581375 }
1376
1377 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1378}
1379
1380TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNotInstalled) {
1381 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581382 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361383 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111384 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1385 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581386
1387 sync_pb::EntitySpecifics specifics;
1388 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1389 ext_specifics->set_id(good_crx);
1390 ext_specifics->set_enabled(false);
1391 ext_specifics->set_incognito_enabled(true);
1392 ext_specifics->set_update_url("http://www.google.com/");
1393 ext_specifics->set_version("1.2.3.4");
treib65f103042015-12-03 10:21:361394
1395 SyncChangeList list =
1396 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581397
1398 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1399 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1400 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1401 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1402 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1403 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1404
1405 const extensions::PendingExtensionInfo* info;
1406 EXPECT_TRUE(
1407 (info = service()->pending_extension_manager()->GetById(good_crx)));
1408 EXPECT_EQ(ext_specifics->update_url(), info->update_url().spec());
1409 EXPECT_TRUE(info->is_from_sync());
1410 EXPECT_EQ(Manifest::INTERNAL, info->install_source());
1411 // TODO(akalin): Figure out a way to test |info.ShouldAllowInstall()|.
1412}
1413
1414TEST_F(ExtensionServiceSyncTest, ProcessSyncDataEnableDisable) {
1415 InitializeEmptyExtensionService();
1416 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361417 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111418 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1419 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581420
1421 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1422
1423 struct TestCase {
1424 const char* name; // For failure output only.
1425 // Set of disable reasons before any Sync data comes in. If this is != 0,
1426 // the extension is disabled.
1427 int previous_disable_reasons;
1428 bool sync_enable; // The enabled flag coming in from Sync.
1429 // The disable reason(s) coming in from Sync, or -1 for "not set".
1430 int sync_disable_reasons;
1431 // The expected set of disable reasons after processing the Sync update. The
1432 // extension should be disabled iff this is != 0.
1433 int expect_disable_reasons;
1434 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361435 {"NopEnable", 0, true, 0, 0},
1436 {"NopDisable", extensions::disable_reason::DISABLE_USER_ACTION, false,
1437 extensions::disable_reason::DISABLE_USER_ACTION,
1438 extensions::disable_reason::DISABLE_USER_ACTION},
1439 {"Enable", extensions::disable_reason::DISABLE_USER_ACTION, true, 0, 0},
1440 {"Disable", 0, false, extensions::disable_reason::DISABLE_USER_ACTION,
1441 extensions::disable_reason::DISABLE_USER_ACTION},
1442 {"AddDisableReason", extensions::disable_reason::DISABLE_REMOTE_INSTALL,
1443 false,
1444 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1445 extensions::disable_reason::DISABLE_USER_ACTION,
1446 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1447 extensions::disable_reason::DISABLE_USER_ACTION},
1448 {"RemoveDisableReason",
1449 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1450 extensions::disable_reason::DISABLE_USER_ACTION,
1451 false, extensions::disable_reason::DISABLE_USER_ACTION,
1452 extensions::disable_reason::DISABLE_USER_ACTION},
1453 {"PreserveLocalDisableReason", extensions::disable_reason::DISABLE_RELOAD,
1454 true, 0, extensions::disable_reason::DISABLE_RELOAD},
1455 {"PreserveOnlyLocalDisableReason",
1456 extensions::disable_reason::DISABLE_USER_ACTION |
1457 extensions::disable_reason::DISABLE_RELOAD,
1458 true, 0, extensions::disable_reason::DISABLE_RELOAD},
treib29e1b9b12015-11-11 08:50:561459
Minh X. Nguyen45479012017-08-18 21:35:361460 // Interaction with Chrome clients <=M44, which don't sync disable_reasons
1461 // at all (any existing reasons are preserved).
1462 {"M44Enable", extensions::disable_reason::DISABLE_USER_ACTION, true, -1,
1463 0},
1464 // An M44 client enables an extension that had been disabled on a new
1465 // client. The disable reasons are still be there, but should be ignored.
1466 {"M44ReEnable", extensions::disable_reason::DISABLE_USER_ACTION, true,
1467 extensions::disable_reason::DISABLE_USER_ACTION, 0},
1468 {"M44Disable", 0, false, -1,
1469 extensions::disable_reason::DISABLE_USER_ACTION},
1470 {"M44ReDisable", 0, false, 0,
1471 extensions::disable_reason::DISABLE_USER_ACTION},
1472 {"M44AlreadyDisabledByUser",
1473 extensions::disable_reason::DISABLE_USER_ACTION, false, -1,
1474 extensions::disable_reason::DISABLE_USER_ACTION},
1475 {"M44AlreadyDisabledWithOtherReason",
1476 extensions::disable_reason::DISABLE_REMOTE_INSTALL, false, -1,
1477 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1478 extensions::disable_reason::DISABLE_USER_ACTION},
treib9afc6212015-10-30 18:49:581479 };
1480
1481 for (const TestCase& test_case : test_cases) {
1482 SCOPED_TRACE(test_case.name);
1483
1484 std::string id;
1485 std::string version;
1486 // Don't keep |extension| around longer than necessary.
1487 {
1488 const Extension* extension =
1489 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1490 // The extension should now be installed and enabled.
1491 ASSERT_TRUE(extension);
1492 id = extension->id();
1493 version = extension->VersionString();
1494 }
1495 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1496
1497 // Disable it if the test case says so.
1498 if (test_case.previous_disable_reasons) {
1499 service()->DisableExtension(id, test_case.previous_disable_reasons);
1500 ASSERT_TRUE(registry()->disabled_extensions().Contains(id));
1501 }
1502
1503 // Now a sync update comes in.
1504 sync_pb::EntitySpecifics specifics;
1505 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1506 ext_specifics->set_id(id);
1507 ext_specifics->set_enabled(test_case.sync_enable);
1508 ext_specifics->set_version(version);
1509 if (test_case.sync_disable_reasons != -1)
1510 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1511
treib65f103042015-12-03 10:21:361512 SyncChangeList list =
1513 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1514
treib9afc6212015-10-30 18:49:581515 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1516
1517 // Check expectations.
1518 const bool expect_enabled = !test_case.expect_disable_reasons;
1519 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1520 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
1521
1522 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031523 UninstallExtension(id);
treib9afc6212015-10-30 18:49:581524 }
1525}
1526
Konstantin Ganenkoae1129c2017-09-15 16:28:591527class ExtensionServiceSyncCustomGalleryTest : public ExtensionServiceSyncTest {
1528 public:
1529 void SetUp() override {
1530 ExtensionServiceSyncTest::SetUp();
rdevlin.cronin2f1ed4c2017-06-13 16:22:131531
Konstantin Ganenkoae1129c2017-09-15 16:28:591532 // This is the update URL specified in the permissions test extension.
1533 // Setting it here is necessary to make the extension considered syncable.
1534 extension_test_util::SetGalleryUpdateURL(
1535 GURL("http://localhost/autoupdate/updates.xml"));
1536 }
1537};
1538
1539TEST_F(ExtensionServiceSyncCustomGalleryTest, ProcessSyncDataDeferredEnable) {
treib9afc6212015-10-30 18:49:581540 InitializeEmptyExtensionService();
1541 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361542 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111543 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1544 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581545
1546 base::FilePath base_path = data_dir().AppendASCII("permissions_increase");
1547 base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1548
1549 base::FilePath path = base_path.AppendASCII("v1");
1550 const Extension* extension = PackAndInstallCRX(path, pem_path, INSTALL_NEW);
1551 // The extension must now be installed and enabled.
1552 ASSERT_TRUE(extension);
1553 ASSERT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
1554
1555 // Save the id, as the extension object will be destroyed during updating.
1556 std::string id = extension->id();
1557
1558 // Update to a new version with increased permissions.
1559 path = base_path.AppendASCII("v2");
1560 PackCRXAndUpdateExtension(id, path, pem_path, DISABLED);
1561
1562 // Now a sync update comes in, telling us to re-enable a *newer* version.
1563 sync_pb::EntitySpecifics specifics;
1564 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1565 ext_specifics->set_id(id);
1566 ext_specifics->set_version("3");
1567 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:361568 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:581569
treib65f103042015-12-03 10:21:361570 SyncChangeList list =
1571 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1572
treib9afc6212015-10-30 18:49:581573 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1574
1575 // Since the version didn't match, the extension should still be disabled.
1576 EXPECT_TRUE(registry()->disabled_extensions().Contains(id));
1577
1578 // After we update to the matching version, the extension should get enabled.
1579 path = base_path.AppendASCII("v3");
1580 PackCRXAndUpdateExtension(id, path, pem_path, ENABLED);
1581}
1582
atuchin2eb18eb2017-03-02 07:22:151583TEST_F(ExtensionServiceSyncCustomGalleryTest,
1584 ProcessSyncDataPermissionApproval) {
treib9afc6212015-10-30 18:49:581585 InitializeEmptyExtensionService();
1586 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361587 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111588 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1589 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581590
1591 const base::FilePath base_path =
1592 data_dir().AppendASCII("permissions_increase");
1593 const base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1594 const base::FilePath path_v1 = base_path.AppendASCII("v1");
1595 const base::FilePath path_v2 = base_path.AppendASCII("v2");
1596
1597 base::ScopedTempDir crx_dir;
1598 ASSERT_TRUE(crx_dir.CreateUniqueTempDir());
vabr9142fe22016-09-08 13:19:221599 const base::FilePath crx_path_v1 = crx_dir.GetPath().AppendASCII("temp1.crx");
treib9afc6212015-10-30 18:49:581600 PackCRX(path_v1, pem_path, crx_path_v1);
vabr9142fe22016-09-08 13:19:221601 const base::FilePath crx_path_v2 = crx_dir.GetPath().AppendASCII("temp2.crx");
treib9afc6212015-10-30 18:49:581602 PackCRX(path_v2, pem_path, crx_path_v2);
1603
1604 const std::string v1("1");
1605 const std::string v2("2");
1606
1607 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1608
1609 struct TestCase {
1610 const char* name; // For failure output only.
1611 const std::string& sync_version; // The version coming in from Sync.
1612 // The disable reason(s) coming in from Sync, or -1 for "not set".
1613 int sync_disable_reasons;
1614 // The expected set of disable reasons after processing the Sync update. The
1615 // extension should be enabled iff this is 0.
1616 int expect_disable_reasons;
1617 // Whether the extension's permissions should be auto-granted.
1618 bool expect_permissions_granted;
1619 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361620 // Sync tells us to re-enable an older version. No permissions should be
1621 // granted, since we can't be sure if the user actually approved the right
1622 // set of permissions.
1623 {"OldVersion", v1, 0,
1624 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
1625 // Legacy case: Sync tells us to re-enable the extension, but doesn't
1626 // specify disable reasons. No permissions should be granted.
1627 {"Legacy", v2, -1,
1628 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
1629 // Sync tells us to re-enable the extension and explicitly removes the
1630 // disable reasons. Now the extension should have its permissions granted.
1631 {"GrantPermissions", v2, 0, extensions::disable_reason::DISABLE_NONE,
1632 true},
treib9afc6212015-10-30 18:49:581633 };
1634
1635 for (const TestCase& test_case : test_cases) {
1636 SCOPED_TRACE(test_case.name);
1637
1638 std::string id;
1639 // Don't keep |extension| around longer than necessary (it'll be destroyed
1640 // during updating).
1641 {
1642 const Extension* extension = InstallCRX(crx_path_v1, INSTALL_NEW);
1643 // The extension should now be installed and enabled.
1644 ASSERT_TRUE(extension);
1645 ASSERT_EQ(v1, extension->VersionString());
1646 id = extension->id();
1647 }
1648 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1649
dchengc963c7142016-04-08 03:55:221650 std::unique_ptr<const PermissionSet> granted_permissions_v1 =
treib9afc6212015-10-30 18:49:581651 prefs->GetGrantedPermissions(id);
1652
1653 // Update to a new version with increased permissions.
1654 UpdateExtension(id, crx_path_v2, DISABLED);
1655
1656 // Now the extension should be disabled due to a permissions increase.
1657 {
1658 const Extension* extension =
1659 registry()->disabled_extensions().GetByID(id);
1660 ASSERT_TRUE(extension);
1661 ASSERT_EQ(v2, extension->VersionString());
1662 }
1663 ASSERT_TRUE(prefs->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:361664 id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE));
treib9afc6212015-10-30 18:49:581665
1666 // No new permissions should have been granted.
dchengc963c7142016-04-08 03:55:221667 std::unique_ptr<const PermissionSet> granted_permissions_v2 =
treib9afc6212015-10-30 18:49:581668 prefs->GetGrantedPermissions(id);
1669 ASSERT_EQ(*granted_permissions_v1, *granted_permissions_v2);
1670
1671 // Now a sync update comes in.
1672 sync_pb::EntitySpecifics specifics;
1673 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1674 ext_specifics->set_id(id);
1675 ext_specifics->set_enabled(true);
1676 ext_specifics->set_version(test_case.sync_version);
1677 if (test_case.sync_disable_reasons != -1)
1678 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1679
treib65f103042015-12-03 10:21:361680 SyncChangeList list =
1681 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1682
treib9afc6212015-10-30 18:49:581683 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1684
1685 // Check expectations.
1686 const bool expect_enabled = !test_case.expect_disable_reasons;
1687 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1688 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
dchengc963c7142016-04-08 03:55:221689 std::unique_ptr<const PermissionSet> granted_permissions =
treib9afc6212015-10-30 18:49:581690 prefs->GetGrantedPermissions(id);
1691 if (test_case.expect_permissions_granted) {
dchengc963c7142016-04-08 03:55:221692 std::unique_ptr<const PermissionSet> active_permissions =
treib9afc6212015-10-30 18:49:581693 prefs->GetActivePermissions(id);
1694 EXPECT_EQ(*granted_permissions, *active_permissions);
1695 } else {
1696 EXPECT_EQ(*granted_permissions, *granted_permissions_v1);
1697 }
1698
1699 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031700 UninstallExtension(id);
treib9afc6212015-10-30 18:49:581701 }
1702}
1703
treib227b2582015-12-09 09:28:261704// Regression test for crbug.com/558299
1705TEST_F(ExtensionServiceSyncTest, DontSyncThemes) {
1706 InitializeEmptyExtensionService();
1707
1708 // The user has enabled sync.
maxboguefe00952a2016-01-19 19:02:011709 ProfileSyncServiceFactory::GetForProfile(profile())->SetFirstSetupComplete();
treib227b2582015-12-09 09:28:261710 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
1711 extension_sync_service();
1712
1713 service()->Init();
1714 ASSERT_TRUE(service()->is_ready());
1715
1716 syncer::FakeSyncChangeProcessor* processor =
1717 new syncer::FakeSyncChangeProcessor;
1718 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:221719 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
1720 base::WrapUnique(new syncer::SyncErrorFactoryMock));
treib227b2582015-12-09 09:28:261721
1722 processor->changes().clear();
1723
1724 // Sanity check: Installing an extension should result in a sync change.
1725 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1726 EXPECT_EQ(1u, processor->changes().size());
1727
1728 processor->changes().clear();
1729
1730 // Installing a theme should not result in a sync change (themes are handled
1731 // separately by ThemeSyncableService).
1732 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
Evan Stade46d716d2017-06-02 20:50:091733 content::WindowedNotificationObserver theme_change_observer(
1734 chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
1735 content::Source<ThemeService>(
1736 ThemeServiceFactory::GetForProfile(profile())));
1737 theme_change_observer.Wait();
treib227b2582015-12-09 09:28:261738 EXPECT_TRUE(processor->changes().empty());
1739}
1740
brettw9e85ef42016-11-01 21:01:241741#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
treib9afc6212015-10-30 18:49:581742
atuchin2eb18eb2017-03-02 07:22:151743class ExtensionServiceTestSupervised
1744 : public ExtensionServiceSyncCustomGalleryTest,
1745 public SupervisedUserService::Delegate {
treib9afc6212015-10-30 18:49:581746 public:
treibb6af28cd2015-12-01 11:19:461747 ExtensionServiceTestSupervised()
Jinho Bangb5216cec2018-01-17 19:43:111748 : field_trial_list_(std::make_unique<base::MockEntropyProvider>()) {}
treibb6af28cd2015-12-01 11:19:461749
treib9afc6212015-10-30 18:49:581750 void TearDown() override {
1751 supervised_user_service()->SetDelegate(nullptr);
1752
atuchin2eb18eb2017-03-02 07:22:151753 ExtensionServiceSyncCustomGalleryTest::TearDown();
treib9afc6212015-10-30 18:49:581754 }
1755
1756 protected:
mamire9609642016-06-28 22:17:541757 void InitSupervisedUserInitiatedExtensionInstallFeature(bool enabled) {
mamire9609642016-06-28 22:17:541758 if (enabled) {
asvitkineb1db8262016-11-08 09:48:201759 scoped_feature_list_.InitAndEnableFeature(
1760 supervised_users::kSupervisedUserInitiatedExtensionInstall);
mamire9609642016-06-28 22:17:541761 }
mamire9609642016-06-28 22:17:541762 }
1763
mamirf7715a2a2016-07-04 13:05:081764 bool IsPendingCustodianApproval(const std::string& extension_id) {
kylechar1e0dd6b2017-10-03 16:07:511765 auto function = base::MakeRefCounted<
1766 WebstorePrivateIsPendingCustodianApprovalFunction>();
mamirf7715a2a2016-07-04 13:05:081767
1768 std::unique_ptr<base::Value> result(RunFunctionAndReturnSingleResult(
1769 function.get(), "[\"" + extension_id + "\"]", browser_context()));
1770
1771 bool copy_bool_result = false;
1772 EXPECT_TRUE(result->GetAsBoolean(&copy_bool_result));
1773 return copy_bool_result;
1774 }
1775
treib9afc6212015-10-30 18:49:581776 void InitServices(bool profile_is_supervised) {
1777 ExtensionServiceInitParams params = CreateDefaultInitParams();
1778 params.profile_is_supervised = profile_is_supervised;
mamire9609642016-06-28 22:17:541779 // If profile is supervised, don't pass a pref file such that the testing
1780 // profile creates a pref service that uses SupervisedUserPrefStore.
1781 if (profile_is_supervised) {
1782 params.pref_file = base::FilePath();
1783 }
treib9afc6212015-10-30 18:49:581784 InitializeExtensionService(params);
asargente48ab752016-03-12 00:59:201785 StartSyncing(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581786
1787 supervised_user_service()->SetDelegate(this);
1788 supervised_user_service()->Init();
1789 }
1790
mamire9609642016-06-28 22:17:541791 std::string InstallPermissionsTestExtension(bool by_custodian) {
1792 return InstallTestExtension(permissions_increase, dir_path("1"), pem_path(),
1793 by_custodian);
treib9afc6212015-10-30 18:49:581794 }
1795
1796 void UpdatePermissionsTestExtension(const std::string& id,
1797 const std::string& version,
1798 UpdateState expected_state) {
mamire9609642016-06-28 22:17:541799 UpdateTestExtension(dir_path(version), pem_path(), id, version,
1800 expected_state);
1801 }
1802
1803 std::string InstallNoPermissionsTestExtension(bool by_custodian) {
1804 base::FilePath base_path = data_dir().AppendASCII("autoupdate");
1805 base::FilePath pem_path = base_path.AppendASCII("key.pem");
1806 base::FilePath dir_path = base_path.AppendASCII("v1");
1807
1808 return InstallTestExtension(autoupdate, dir_path, pem_path, by_custodian);
1809 }
1810
1811 void UpdateNoPermissionsTestExtension(const std::string& id,
1812 const std::string& version,
1813 UpdateState expected_state) {
1814 base::FilePath base_path = data_dir().AppendASCII("autoupdate");
1815 base::FilePath pem_path = base_path.AppendASCII("key.pem");
1816 base::FilePath dir_path = base_path.AppendASCII("v" + version);
1817
1818 UpdateTestExtension(dir_path, pem_path, id, version, expected_state);
1819 }
1820
1821 std::string InstallTestExtension(const std::string& id,
1822 const base::FilePath& dir_path,
1823 const base::FilePath& pem_path,
1824 bool by_custodian) {
1825 InstallState expected_state = INSTALL_WITHOUT_LOAD;
1826 if (by_custodian) {
1827 extensions::util::SetWasInstalledByCustodian(id, profile(), true);
1828 expected_state = INSTALL_NEW;
1829 }
1830 const Extension* extension =
1831 PackAndInstallCRX(dir_path, pem_path, expected_state);
1832 // The extension must now be installed.
1833 EXPECT_TRUE(extension);
1834 EXPECT_EQ(extension->id(), id);
1835 if (by_custodian) {
1836 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1837 } else {
1838 CheckDisabledForCustodianApproval(id);
1839 }
1840
Devlin Cronin03bf2d22017-12-20 08:21:051841 EXPECT_EQ(base::Version("1"), extension->version());
mamire9609642016-06-28 22:17:541842
1843 return id;
1844 }
1845
1846 void UpdateTestExtension(const base::FilePath& dir_path,
1847 const base::FilePath& pem_path,
1848 const std::string& id,
1849 const std::string& version,
1850 const UpdateState& expected_state) {
1851 PackCRXAndUpdateExtension(id, dir_path, pem_path, expected_state);
treib9afc6212015-10-30 18:49:581852 const Extension* extension = registry()->GetInstalledExtension(id);
1853 ASSERT_TRUE(extension);
1854 // The version should have been updated.
Devlin Cronin03bf2d22017-12-20 08:21:051855 EXPECT_EQ(base::Version(version), extension->version());
mamire9609642016-06-28 22:17:541856 }
1857
1858 // Simulate a custodian approval for enabling the extension coming in
1859 // through Sync by adding the approved version to the map of approved
1860 // extensions. It doesn't simulate a change in the disable reasons.
1861 void SimulateCustodianApprovalChangeViaSync(const std::string& extension_id,
1862 const std::string& version,
1863 SyncChange::SyncChangeType type) {
1864 std::string key = SupervisedUserSettingsService::MakeSplitSettingKey(
1865 supervised_users::kApprovedExtensions, extension_id);
1866 syncer::SyncData sync_data =
1867 SupervisedUserSettingsService::CreateSyncDataForSetting(
jdoerrie122c4da2017-03-06 11:12:041868 key, base::Value(version));
mamire9609642016-06-28 22:17:541869
1870 SyncChangeList list(1, SyncChange(FROM_HERE, type, sync_data));
1871
1872 SupervisedUserSettingsService* supervised_user_settings_service =
1873 SupervisedUserSettingsServiceFactory::GetForProfile(profile());
1874 supervised_user_settings_service->ProcessSyncChanges(FROM_HERE, list);
1875 }
1876
1877 void CheckDisabledForCustodianApproval(const std::string& extension_id) {
1878 EXPECT_TRUE(registry()->disabled_extensions().Contains(extension_id));
1879 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile());
1880 EXPECT_TRUE(extension_prefs->HasDisableReason(
1881 extension_id,
Minh X. Nguyen45479012017-08-18 21:35:361882 extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
treib9afc6212015-10-30 18:49:581883 }
1884
1885 SupervisedUserService* supervised_user_service() {
1886 return SupervisedUserServiceFactory::GetForProfile(profile());
1887 }
1888
mamire9609642016-06-28 22:17:541889 static std::string RequestId(const std::string& extension_id,
1890 const std::string& version) {
1891 return SupervisedUserService::GetExtensionRequestId(
treib9afc6212015-10-30 18:49:581892 extension_id, base::Version(version));
1893 }
1894
1895 private:
1896 // This prevents the legacy supervised user init code from running.
1897 bool SetActive(bool active) override { return true; }
1898
1899 base::FilePath base_path() const {
1900 return data_dir().AppendASCII("permissions_increase");
1901 }
1902 base::FilePath dir_path(const std::string& version) const {
1903 return base_path().AppendASCII("v" + version);
1904 }
1905 base::FilePath pem_path() const {
1906 return base_path().AppendASCII("permissions.pem");
1907 }
treibb6af28cd2015-12-01 11:19:461908
1909 base::FieldTrialList field_trial_list_;
asvitkineb1db8262016-11-08 09:48:201910 base::test::ScopedFeatureList scoped_feature_list_;
treib9afc6212015-10-30 18:49:581911};
1912
1913class MockPermissionRequestCreator : public PermissionRequestCreator {
1914 public:
1915 MockPermissionRequestCreator() {}
1916 ~MockPermissionRequestCreator() override {}
1917
1918 bool IsEnabled() const override { return true; }
1919
1920 void CreateURLAccessRequest(const GURL& url_requested,
Carlos IL6b784a62018-03-20 00:26:491921 SuccessCallback callback) override {
treib9afc6212015-10-30 18:49:581922 FAIL();
1923 }
1924
Carlos IL6b784a62018-03-20 00:26:491925 void CreateExtensionInstallRequest(
1926 const std::string& id,
1927 SupervisedUserService::SuccessCallback callback) override {
1928 CreateExtensionInstallRequestInternal(id);
1929 }
mamire9609642016-06-28 22:17:541930
Carlos IL6b784a62018-03-20 00:26:491931 void CreateExtensionUpdateRequest(
1932 const std::string& id,
1933 SupervisedUserService::SuccessCallback callback) override {
1934 CreateExtensionUpdateRequestInternal(id);
1935 }
1936
1937 // TODO(crbug.com/729950): These two mock methods can be set to direct calls
1938 // once gtest supports move-only objects, since SuccessCallback is move only.
1939 MOCK_METHOD1(CreateExtensionInstallRequestInternal,
1940 void(const std::string& id));
1941
1942 MOCK_METHOD1(CreateExtensionUpdateRequestInternal,
1943 void(const std::string& id));
treib9afc6212015-10-30 18:49:581944
1945 private:
1946 DISALLOW_COPY_AND_ASSIGN(MockPermissionRequestCreator);
1947};
1948
1949TEST_F(ExtensionServiceTestSupervised, InstallOnlyAllowedByCustodian) {
mamire9609642016-06-28 22:17:541950 InitSupervisedUserInitiatedExtensionInstallFeature(false);
treib9afc6212015-10-30 18:49:581951
Mikel Astiza68eea52018-10-05 07:59:141952 InitServices(true /* profile_is_supervised */);
1953
mamir192d7882016-06-22 17:10:161954 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
1955
treib9afc6212015-10-30 18:49:581956 base::FilePath path1 = data_dir().AppendASCII("good.crx");
1957 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
1958 const Extension* extensions[] = {
1959 InstallCRX(path1, INSTALL_FAILED),
mamir192d7882016-06-22 17:10:161960 InstallCRX(path2, INSTALL_NEW)
treib9afc6212015-10-30 18:49:581961 };
1962
1963 // Only the extension with the "installed by custodian" flag should have been
1964 // installed and enabled.
1965 EXPECT_FALSE(extensions[0]);
1966 ASSERT_TRUE(extensions[1]);
1967 EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id()));
mamirf7715a2a2016-07-04 13:05:081968 EXPECT_FALSE(IsPendingCustodianApproval(extensions[1]->id()));
treib9afc6212015-10-30 18:49:581969}
1970
mamir192d7882016-06-22 17:10:161971TEST_F(ExtensionServiceTestSupervised,
1972 DelegatedAndPreinstalledExtensionIsSUFirst) {
mamire9609642016-06-28 22:17:541973 InitSupervisedUserInitiatedExtensionInstallFeature(false);
mamir192d7882016-06-22 17:10:161974
Mikel Astiza68eea52018-10-05 07:59:141975 InitServices(false /* profile_is_supervised */);
1976
mamir192d7882016-06-22 17:10:161977 // Install an extension.
1978 base::FilePath path = data_dir().AppendASCII("good.crx");
1979 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1980 std::string id = extension->id();
1981 const std::string version("1.0.0.0");
1982 // It should be enabled.
1983 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1984
1985 // Now make the profile supervised.
1986 profile()->AsTestingProfile()->SetSupervisedUserId(
1987 supervised_users::kChildAccountSUID);
1988
1989 // It should not be enabled now (it is not loaded at all actually).
1990 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
1991
1992 // Simulate data sync with the "was_installed_by_custodian" flag set to 1.
1993 sync_pb::EntitySpecifics specifics;
1994 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1995 ext_specifics->set_id(id);
1996 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:361997 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
mamir192d7882016-06-22 17:10:161998 ext_specifics->set_installed_by_custodian(true);
1999 ext_specifics->set_version(version);
2000
2001 SyncChangeList list =
2002 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2003
2004 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
2005
2006 // The extension should be enabled again.
2007 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2008 EXPECT_TRUE(extensions::util::WasInstalledByCustodian(id, profile()));
2009}
2010
2011TEST_F(ExtensionServiceTestSupervised,
2012 DelegatedAndPreinstalledExtensionSyncFirst) {
mamire9609642016-06-28 22:17:542013 InitSupervisedUserInitiatedExtensionInstallFeature(false);
mamir192d7882016-06-22 17:10:162014
Mikel Astiza68eea52018-10-05 07:59:142015 InitServices(false /* profile_is_supervised */);
2016
mamir192d7882016-06-22 17:10:162017 // Install an extension.
2018 base::FilePath path = data_dir().AppendASCII("good.crx");
2019 const Extension* extension = InstallCRX(path, INSTALL_NEW);
2020 std::string id = extension->id();
2021 const std::string version("1.0.0.0");
2022
2023 // It should be enabled.
2024 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2025
2026 // Simulate data sync with the "was_installed_by_custodian" flag set to 1.
2027 sync_pb::EntitySpecifics specifics;
2028 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2029 ext_specifics->set_id(id);
2030 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:362031 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
mamir192d7882016-06-22 17:10:162032 ext_specifics->set_installed_by_custodian(true);
2033 ext_specifics->set_version(version);
2034
2035 SyncChangeList list =
2036 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2037
2038 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
mamir192d7882016-06-22 17:10:162039 // The extension should be enabled.
2040 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2041 EXPECT_TRUE(extensions::util::WasInstalledByCustodian(id, profile()));
2042}
2043
mamire9609642016-06-28 22:17:542044TEST_F(ExtensionServiceTestSupervised,
2045 InstallAllowedByCustodianAndSupervisedUser) {
mamire9609642016-06-28 22:17:542046 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2047
Mikel Astiza68eea52018-10-05 07:59:142048 InitServices(true /* profile_is_supervised */);
2049
mamire9609642016-06-28 22:17:542050 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
2051
2052 base::FilePath path1 = data_dir().AppendASCII("good.crx");
2053 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
2054 const Extension* extensions[] = {
2055 InstallCRX(path1, INSTALL_WITHOUT_LOAD),
2056 InstallCRX(path2, INSTALL_NEW)
2057 };
2058
2059 // Only the extension with the "installed by custodian" flag should have been
2060 // installed and enabled.
2061 // The extension missing the "installed by custodian" flag is a
2062 // supervised user initiated install and hence not enabled.
2063 ASSERT_TRUE(extensions[0]);
2064 ASSERT_TRUE(extensions[1]);
2065 EXPECT_TRUE(registry()->disabled_extensions().Contains(extensions[0]->id()));
mamirf7715a2a2016-07-04 13:05:082066 EXPECT_TRUE(IsPendingCustodianApproval(extensions[0]->id()));
mamire9609642016-06-28 22:17:542067 EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id()));
mamirf7715a2a2016-07-04 13:05:082068 EXPECT_FALSE(IsPendingCustodianApproval(extensions[1]->id()));
mamire9609642016-06-28 22:17:542069}
2070
2071TEST_F(ExtensionServiceTestSupervised,
2072 PreinstalledExtensionWithSUInitiatedInstalls) {
mamire9609642016-06-28 22:17:542073 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2074
Mikel Astiza68eea52018-10-05 07:59:142075 InitServices(false /* profile_is_supervised */);
2076
mamire9609642016-06-28 22:17:542077 // Install an extension.
2078 base::FilePath path = data_dir().AppendASCII("good.crx");
2079 const Extension* extension = InstallCRX(path, INSTALL_NEW);
2080 std::string id = extension->id();
2081 // Make sure it's enabled.
2082 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2083
2084 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2085 supervised_user_service()->AddPermissionRequestCreator(
2086 base::WrapUnique(creator));
2087 const std::string version("1.0.0.0");
2088
Carlos IL6b784a62018-03-20 00:26:492089 EXPECT_CALL(*creator, CreateExtensionInstallRequestInternal(
2090 RequestId(good_crx, version)));
mamire9609642016-06-28 22:17:542091
2092 // Now make the profile supervised.
2093 profile()->AsTestingProfile()->SetSupervisedUserId(
2094 supervised_users::kChildAccountSUID);
2095
2096 Mock::VerifyAndClearExpectations(creator);
2097
2098 // The extension should not be enabled anymore.
2099 CheckDisabledForCustodianApproval(id);
mamirf7715a2a2016-07-04 13:05:082100 EXPECT_TRUE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542101}
2102
2103TEST_F(ExtensionServiceTestSupervised,
2104 PreinstalledExtensionWithoutSUInitiatedInstalls) {
mamire9609642016-06-28 22:17:542105 InitSupervisedUserInitiatedExtensionInstallFeature(false);
2106
Mikel Astiza68eea52018-10-05 07:59:142107 InitServices(false /* profile_is_supervised */);
2108
mamire9609642016-06-28 22:17:542109 // Install an extension.
2110 base::FilePath path = data_dir().AppendASCII("good.crx");
2111 const Extension* extension = InstallCRX(path, INSTALL_NEW);
2112 std::string id = extension->id();
2113
2114 // Make sure it's enabled.
2115 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2116
2117 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2118 supervised_user_service()->AddPermissionRequestCreator(
2119 base::WrapUnique(creator));
2120 const std::string version("1.0.0.0");
2121
2122 // No request should be sent because supervised user initiated installs
2123 // are disabled.
Carlos IL6b784a62018-03-20 00:26:492124 EXPECT_CALL(*creator, CreateExtensionInstallRequestInternal(testing::_))
mamire9609642016-06-28 22:17:542125 .Times(0);
2126
2127 // Now make the profile supervised.
2128 profile()->AsTestingProfile()->SetSupervisedUserId(
2129 supervised_users::kChildAccountSUID);
2130
Karan Bhatia2a117232017-08-23 00:24:562131 // The extension should now be disabled.
2132 EXPECT_TRUE(registry()->disabled_extensions().Contains(id));
2133 EXPECT_EQ(extensions::disable_reason::DISABLE_BLOCKED_BY_POLICY,
2134 ExtensionPrefs::Get(profile())->GetDisableReasons(id));
mamire9609642016-06-28 22:17:542135}
2136
2137TEST_F(ExtensionServiceTestSupervised, ExtensionApprovalBeforeInstallation) {
2138 // This tests the case when the sync entity flagging the extension as approved
2139 // arrives before the extension itself is installed.
mamire9609642016-06-28 22:17:542140 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2141
Mikel Astiza68eea52018-10-05 07:59:142142 InitServices(true /* profile_is_supervised */);
2143
mamire9609642016-06-28 22:17:542144 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2145 supervised_user_service()->AddPermissionRequestCreator(
2146 base::WrapUnique(creator));
2147
2148 std::string id = good_crx;
2149 std::string version("1.0.0.0");
2150
2151 SimulateCustodianApprovalChangeViaSync(id, version, SyncChange::ACTION_ADD);
2152
2153 // Now install an extension.
2154 base::FilePath path = data_dir().AppendASCII("good.crx");
2155 InstallCRX(path, INSTALL_NEW);
2156
2157 // No approval request should be sent.
Carlos IL6b784a62018-03-20 00:26:492158 EXPECT_CALL(*creator, CreateExtensionInstallRequestInternal(testing::_))
mamire9609642016-06-28 22:17:542159 .Times(0);
2160
2161 // Make sure it's enabled.
2162 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082163 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542164}
2165
treib9afc6212015-10-30 18:49:582166TEST_F(ExtensionServiceTestSupervised, UpdateWithoutPermissionIncrease) {
2167 InitServices(true /* profile_is_supervised */);
2168
treib9afc6212015-10-30 18:49:582169 // Save the id, as the extension object will be destroyed during updating.
mamire9609642016-06-28 22:17:542170 std::string id = InstallNoPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582171
2172 // Update to a new version.
mamire9609642016-06-28 22:17:542173 std::string version2("2");
2174 UpdateNoPermissionsTestExtension(id, version2, ENABLED);
treib9afc6212015-10-30 18:49:582175
2176 // The extension should still be there and enabled.
mamire9609642016-06-28 22:17:542177 const Extension* extension = registry()->enabled_extensions().GetByID(id);
treib9afc6212015-10-30 18:49:582178 ASSERT_TRUE(extension);
2179 // The version should have changed.
Devlin Cronin03bf2d22017-12-20 08:21:052180 EXPECT_EQ(base::Version(version2), extension->version());
mamirf7715a2a2016-07-04 13:05:082181 EXPECT_FALSE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582182}
2183
treib9afc6212015-10-30 18:49:582184TEST_F(ExtensionServiceTestSupervised,
2185 UpdateWithPermissionIncreaseApprovalOldVersion) {
treib9afc6212015-10-30 18:49:582186 InitServices(true /* profile_is_supervised */);
2187
2188 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2189 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222190 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582191
2192 const std::string version1("1");
2193 const std::string version2("2");
2194
mamire9609642016-06-28 22:17:542195 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582196
2197 // Update to a new version with increased permissions.
Carlos IL6b784a62018-03-20 00:26:492198 EXPECT_CALL(*creator,
2199 CreateExtensionUpdateRequestInternal(RequestId(id, version2)));
treib9afc6212015-10-30 18:49:582200 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542201 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082202 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582203
2204 // Simulate a custodian approval for re-enabling the extension coming in
2205 // through Sync, but set the old version. This can happen when there already
2206 // was a pending request for an earlier version of the extension.
2207 sync_pb::EntitySpecifics specifics;
2208 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2209 ext_specifics->set_id(id);
2210 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:362211 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:582212 ext_specifics->set_installed_by_custodian(true);
2213 ext_specifics->set_version(version1);
2214
2215 // Attempting to re-enable an old version should result in a permission
2216 // request for the current version.
Carlos IL6b784a62018-03-20 00:26:492217 EXPECT_CALL(*creator,
2218 CreateExtensionUpdateRequestInternal(RequestId(id, version2)));
treib9afc6212015-10-30 18:49:582219
treib65f103042015-12-03 10:21:362220 SyncChangeList list =
2221 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2222
2223 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582224 // The re-enable should be ignored, since the version doesn't match.
2225 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2226 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
2227 id, base::Version(version1)));
2228 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
2229 id, base::Version(version2)));
mamire9609642016-06-28 22:17:542230 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082231 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582232}
2233
2234TEST_F(ExtensionServiceTestSupervised,
2235 UpdateWithPermissionIncreaseApprovalMatchingVersion) {
treib9afc6212015-10-30 18:49:582236 InitServices(true /* profile_is_supervised */);
2237
2238 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2239 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222240 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582241
mamire9609642016-06-28 22:17:542242 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582243
2244 // Update to a new version with increased permissions.
2245 const std::string version2("2");
Carlos IL6b784a62018-03-20 00:26:492246 EXPECT_CALL(*creator,
2247 CreateExtensionUpdateRequestInternal(RequestId(id, version2)));
treib9afc6212015-10-30 18:49:582248 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542249 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082250 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582251
2252 // Simulate a custodian approval for re-enabling the extension coming in
2253 // through Sync.
2254 sync_pb::EntitySpecifics specifics;
2255 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2256 ext_specifics->set_id(id);
2257 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:362258 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:582259 ext_specifics->set_installed_by_custodian(true);
2260 ext_specifics->set_version(version2);
2261
treib65f103042015-12-03 10:21:362262 SyncChangeList list =
2263 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2264
2265 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582266 // The extension should have gotten re-enabled.
2267 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082268 EXPECT_FALSE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582269}
2270
2271TEST_F(ExtensionServiceTestSupervised,
2272 UpdateWithPermissionIncreaseApprovalNewVersion) {
treib9afc6212015-10-30 18:49:582273 InitServices(true /* profile_is_supervised */);
2274
2275 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2276 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222277 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582278
mamire9609642016-06-28 22:17:542279 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582280
2281 // Update to a new version with increased permissions.
2282 const std::string version2("2");
Carlos IL6b784a62018-03-20 00:26:492283 EXPECT_CALL(*creator,
2284 CreateExtensionUpdateRequestInternal(RequestId(id, version2)));
treib9afc6212015-10-30 18:49:582285 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542286 Mock::VerifyAndClearExpectations(creator);
treib9afc6212015-10-30 18:49:582287
2288 // Simulate a custodian approval for re-enabling the extension coming in
2289 // through Sync. Set a newer version than we have installed.
2290 const std::string version3("3");
2291 sync_pb::EntitySpecifics specifics;
2292 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2293 ext_specifics->set_id(id);
2294 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:362295 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:582296 ext_specifics->set_installed_by_custodian(true);
2297 ext_specifics->set_version(version3);
2298
2299 // This should *not* result in a new permission request.
Carlos IL6b784a62018-03-20 00:26:492300 EXPECT_CALL(*creator,
2301 CreateExtensionUpdateRequestInternal(RequestId(id, version3)))
treib9afc6212015-10-30 18:49:582302 .Times(0);
2303
treib65f103042015-12-03 10:21:362304 SyncChangeList list =
2305 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2306
2307 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582308 // The re-enable should be delayed until the extension is updated to the
2309 // matching version.
2310 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2311 EXPECT_TRUE(extension_sync_service()->HasPendingReenable(
2312 id, base::Version(version3)));
2313
2314 // Update to the matching version. Now the extension should get enabled.
2315 UpdatePermissionsTestExtension(id, version3, ENABLED);
2316}
2317
mamire9609642016-06-28 22:17:542318TEST_F(ExtensionServiceTestSupervised, SupervisedUserInitiatedInstalls) {
mamire9609642016-06-28 22:17:542319 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2320
2321 InitServices(true /* profile_is_supervised */);
2322
2323 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2324 supervised_user_service()->AddPermissionRequestCreator(
2325 base::WrapUnique(creator));
2326
2327 base::FilePath path = data_dir().AppendASCII("good.crx");
2328 std::string version("1.0.0.0");
2329
Carlos IL6b784a62018-03-20 00:26:492330 EXPECT_CALL(*creator, CreateExtensionInstallRequestInternal(
2331 RequestId(good_crx, version)));
mamire9609642016-06-28 22:17:542332
2333 // Should be installed but disabled, a request for approval should be sent.
2334 const Extension* extension = InstallCRX(path, INSTALL_WITHOUT_LOAD);
2335 ASSERT_TRUE(extension);
2336 ASSERT_EQ(extension->id(), good_crx);
2337 EXPECT_TRUE(registry()->disabled_extensions().Contains(good_crx));
2338 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082339 EXPECT_TRUE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542340
2341 SimulateCustodianApprovalChangeViaSync(good_crx, version,
2342 SyncChange::ACTION_ADD);
2343
2344 // The extension should be enabled now.
2345 EXPECT_TRUE(registry()->enabled_extensions().Contains(good_crx));
mamirf7715a2a2016-07-04 13:05:082346 EXPECT_FALSE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542347
2348 // Simulate approval removal coming via Sync.
2349 SimulateCustodianApprovalChangeViaSync(good_crx, version,
2350 SyncChange::ACTION_DELETE);
2351
2352 // The extension should be disabled now.
2353 EXPECT_TRUE(registry()->disabled_extensions().Contains(good_crx));
mamirf7715a2a2016-07-04 13:05:082354 EXPECT_TRUE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542355}
2356
2357TEST_F(ExtensionServiceTestSupervised,
2358 UpdateSUInitiatedInstallWithoutPermissionIncrease) {
mamire9609642016-06-28 22:17:542359 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2360
2361 InitServices(true /* profile_is_supervised */);
2362
2363 std::string id = InstallNoPermissionsTestExtension(false /* by_custodian */);
2364 std::string version1("1");
2365
2366 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2367
2368 // The extension should be enabled now.
2369 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2370
2371 std::string version2("2");
2372
2373 // Update to a new version.
2374 UpdateNoPermissionsTestExtension(id, version2, ENABLED);
2375
2376 // The extension should still be there and enabled.
2377 const Extension* extension = registry()->enabled_extensions().GetByID(id);
2378 ASSERT_TRUE(extension);
2379 // The version should have increased.
Devlin Cronin03bf2d22017-12-20 08:21:052380 EXPECT_EQ(1, extension->version().CompareTo(base::Version(version1)));
mamire9609642016-06-28 22:17:542381
2382 // Check that the approved version has been updated in the prefs as well.
2383 // Prefs are updated via Sync. If the prefs are updated, then the new
2384 // approved version has been pushed to Sync as well.
2385 std::string approved_version;
2386 PrefService* pref_service = profile()->GetPrefs();
2387 const base::DictionaryValue* approved_extensions =
2388 pref_service->GetDictionary(prefs::kSupervisedUserApprovedExtensions);
2389 approved_extensions->GetStringWithoutPathExpansion(id, &approved_version);
2390
Devlin Cronin03bf2d22017-12-20 08:21:052391 EXPECT_EQ(base::Version(approved_version), extension->version());
mamirf7715a2a2016-07-04 13:05:082392 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542393}
2394
2395TEST_F(ExtensionServiceTestSupervised,
2396 UpdateSUInitiatedInstallWithPermissionIncrease) {
mamire9609642016-06-28 22:17:542397 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2398
2399 InitServices(true /* profile_is_supervised */);
2400
2401 std::string id = InstallPermissionsTestExtension(false /* by_custodian */);
2402 std::string version1("1");
2403
2404 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2405
2406 // The extension should be enabled now.
2407 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2408
2409 std::string version3("3");
2410
2411 UpdatePermissionsTestExtension(id, version3, DISABLED);
2412
2413 // The extension should be disabled.
2414 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2415 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:362416 id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE));
mamire9609642016-06-28 22:17:542417
2418 std::string version2("2");
2419 // Approve an older version
2420 SimulateCustodianApprovalChangeViaSync(id, version2,
2421 SyncChange::ACTION_UPDATE);
2422
2423 // The extension should remain disabled.
2424 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2425 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:362426 id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE));
mamire9609642016-06-28 22:17:542427 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:362428 id, extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
mamire9609642016-06-28 22:17:542429
mamirf7715a2a2016-07-04 13:05:082430 EXPECT_TRUE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542431 // Approve the latest version
2432 SimulateCustodianApprovalChangeViaSync(id, version3,
2433 SyncChange::ACTION_UPDATE);
2434
2435 // The extension should be enabled again.
2436 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082437 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542438}
2439
2440TEST_F(ExtensionServiceTestSupervised,
2441 UpdateSUInitiatedInstallWithPermissionIncreaseApprovalArrivesFirst) {
mamire9609642016-06-28 22:17:542442 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2443
2444 InitServices(true /* profile_is_supervised */);
2445
2446 std::string id = InstallPermissionsTestExtension(false /* by_custodian */);
2447
2448 std::string version1("1");
2449 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2450
2451 // The extension should be enabled now.
2452 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2453
2454 std::string version2("2");
2455 // Approve a newer version
2456 SimulateCustodianApprovalChangeViaSync(id, version2,
2457 SyncChange::ACTION_UPDATE);
2458
2459 // The extension should be disabled.
2460 CheckDisabledForCustodianApproval(id);
2461
2462 // Now update the extension to the same version that was approved.
2463 UpdatePermissionsTestExtension(id, version2, ENABLED);
2464 // The extension should be enabled again.
2465 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082466 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542467}
2468
treib9afc6212015-10-30 18:49:582469TEST_F(ExtensionServiceSyncTest, SyncUninstallByCustodianSkipsPolicy) {
2470 InitializeEmptyExtensionService();
2471 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:362472 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:112473 std::make_unique<syncer::FakeSyncChangeProcessor>(),
2474 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:582475
mamir192d7882016-06-22 17:10:162476 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
treib9afc6212015-10-30 18:49:582477 // Install two extensions.
2478 base::FilePath path1 = data_dir().AppendASCII("good.crx");
2479 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
2480 const Extension* extensions[] = {
2481 InstallCRX(path1, INSTALL_NEW),
mamir192d7882016-06-22 17:10:162482 InstallCRX(path2, INSTALL_NEW)
treib9afc6212015-10-30 18:49:582483 };
2484
2485 // Add a policy provider that will disallow any changes.
2486 extensions::TestManagementPolicyProvider provider(
2487 extensions::TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS);
2488 ExtensionSystem::Get(
2489 browser_context())->management_policy()->RegisterProvider(&provider);
2490
2491 // Create a sync deletion for each extension.
treib65f103042015-12-03 10:21:362492 SyncChangeList list;
treib9afc6212015-10-30 18:49:582493 for (size_t i = 0; i < arraysize(extensions); i++) {
2494 const std::string& id = extensions[i]->id();
2495 sync_pb::EntitySpecifics specifics;
2496 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2497 ext_specifics->set_id(id);
2498 ext_specifics->set_version("1.0");
2499 ext_specifics->set_installed_by_custodian(
mamir192d7882016-06-22 17:10:162500 extensions::util::WasInstalledByCustodian(id, profile()));
2501
treib9afc6212015-10-30 18:49:582502 syncer::SyncData sync_data =
2503 syncer::SyncData::CreateLocalData(id, "Name", specifics);
treib65f103042015-12-03 10:21:362504 list.push_back(SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, sync_data));
treib9afc6212015-10-30 18:49:582505 }
2506
2507 // Save the extension ids, as uninstalling destroys the Extension instance.
2508 std::string extension_ids[] = {
2509 extensions[0]->id(),
2510 extensions[1]->id()
2511 };
2512
2513 // Now apply the uninstallations.
treib65f103042015-12-03 10:21:362514 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582515
2516 // Uninstalling the extension without installed_by_custodian should have been
2517 // blocked by policy, so it should still be there.
2518 EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_ids[0]));
2519
2520 // But installed_by_custodian should result in bypassing the policy check.
2521 EXPECT_FALSE(
2522 registry()->GenerateInstalledExtensionsSet()->Contains(extension_ids[1]));
2523}
2524
brettw9e85ef42016-11-01 21:01:242525#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
asargente48ab752016-03-12 00:59:202526
2527// Tests sync behavior in the case of an item that starts out as an app and
2528// gets updated to become an extension.
2529TEST_F(ExtensionServiceSyncTest, AppToExtension) {
2530 InitializeEmptyExtensionService();
2531 service()->Init();
2532 ASSERT_TRUE(service()->is_ready());
2533
2534 // Install v1, which is an app.
2535 const Extension* v1 =
2536 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v1.crx"),
2537 INSTALL_NEW);
2538 EXPECT_TRUE(v1->is_app());
2539 EXPECT_FALSE(v1->is_extension());
2540 std::string id = v1->id();
2541
2542 StatefulChangeProcessor extensions_processor(syncer::ModelType::EXTENSIONS);
2543 StatefulChangeProcessor apps_processor(syncer::ModelType::APPS);
2544 extension_sync_service()->MergeDataAndStartSyncing(
2545 syncer::EXTENSIONS, syncer::SyncDataList(),
2546 extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222547 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202548 extension_sync_service()->MergeDataAndStartSyncing(
2549 syncer::APPS, syncer::SyncDataList(), apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222550 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202551
2552 // Check the app/extension change processors to be sure the right data was
2553 // added.
2554 EXPECT_TRUE(extensions_processor.changes().empty());
2555 EXPECT_TRUE(extensions_processor.data().empty());
2556 EXPECT_EQ(1u, apps_processor.data().size());
2557 ASSERT_EQ(1u, apps_processor.changes().size());
2558 const SyncChange& app_change = apps_processor.changes()[0];
2559 EXPECT_EQ(SyncChange::ACTION_ADD, app_change.change_type());
dchengc963c7142016-04-08 03:55:222560 std::unique_ptr<ExtensionSyncData> app_data =
asargente48ab752016-03-12 00:59:202561 ExtensionSyncData::CreateFromSyncData(app_change.sync_data());
2562 EXPECT_TRUE(app_data->is_app());
2563 EXPECT_EQ(id, app_data->id());
Devlin Cronin03bf2d22017-12-20 08:21:052564 EXPECT_EQ(v1->version(), app_data->version());
asargente48ab752016-03-12 00:59:202565
2566 // Update the app to v2, which is an extension.
2567 const Extension* v2 =
2568 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v2.crx"),
2569 INSTALL_UPDATED);
2570 EXPECT_FALSE(v2->is_app());
2571 EXPECT_TRUE(v2->is_extension());
2572 EXPECT_EQ(id, v2->id());
2573
2574 // Make sure we saw an extension item added.
2575 ASSERT_EQ(1u, extensions_processor.changes().size());
2576 const SyncChange& extension_change = extensions_processor.changes()[0];
2577 EXPECT_EQ(SyncChange::ACTION_ADD, extension_change.change_type());
dchengc963c7142016-04-08 03:55:222578 std::unique_ptr<ExtensionSyncData> extension_data =
asargente48ab752016-03-12 00:59:202579 ExtensionSyncData::CreateFromSyncData(extension_change.sync_data());
2580 EXPECT_FALSE(extension_data->is_app());
2581 EXPECT_EQ(id, extension_data->id());
Devlin Cronin03bf2d22017-12-20 08:21:052582 EXPECT_EQ(v2->version(), extension_data->version());
asargente48ab752016-03-12 00:59:202583
2584 // Get the current data from the change processors to use as the input to
2585 // the following call to MergeDataAndStartSyncing. This simulates what should
2586 // happen with sync.
2587 syncer::SyncDataList extensions_data =
2588 extensions_processor.GetAllSyncData(syncer::EXTENSIONS);
2589 syncer::SyncDataList apps_data = apps_processor.GetAllSyncData(syncer::APPS);
2590
2591 // Stop syncing, then start again.
2592 extension_sync_service()->StopSyncing(syncer::EXTENSIONS);
2593 extension_sync_service()->StopSyncing(syncer::APPS);
2594 extension_sync_service()->MergeDataAndStartSyncing(
2595 syncer::EXTENSIONS, extensions_data, extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222596 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202597 extension_sync_service()->MergeDataAndStartSyncing(
2598 syncer::APPS, apps_data, apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222599 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202600
2601 // Make sure we saw an app item deleted.
2602 bool found_delete = false;
2603 for (const auto& change : apps_processor.changes()) {
2604 if (change.change_type() == SyncChange::ACTION_DELETE) {
dchengc963c7142016-04-08 03:55:222605 std::unique_ptr<ExtensionSyncData> data =
asargente48ab752016-03-12 00:59:202606 ExtensionSyncData::CreateFromSyncChange(change);
2607 if (data->id() == id) {
2608 found_delete = true;
2609 break;
2610 }
2611 }
2612 }
2613 EXPECT_TRUE(found_delete);
2614
2615 // Make sure there is one extension, and there are no more apps.
2616 EXPECT_EQ(1u, extensions_processor.data().size());
2617 EXPECT_TRUE(apps_processor.data().empty());
2618}
proberge901ecab2017-08-31 19:24:282619
2620class BlacklistedExtensionSyncServiceTest : public ExtensionServiceSyncTest {
2621 public:
2622 BlacklistedExtensionSyncServiceTest() {}
2623
2624 void SetUp() override {
2625 ExtensionServiceSyncTest::SetUp();
2626
2627 InitializeEmptyExtensionService();
2628
2629 // Enable sync.
2630 browser_sync::ProfileSyncService* sync_service =
2631 ProfileSyncServiceFactory::GetForProfile(profile());
2632 sync_service->SetFirstSetupComplete();
2633
2634 test_blacklist_.Attach(service()->blacklist_);
2635 service()->Init();
2636
2637 // Load up a simple extension.
2638 extensions::ChromeTestExtensionLoader extension_loader(profile());
2639 extension_loader.set_pack_extension(true);
2640 extension_ = extension_loader.LoadExtension(
2641 data_dir().AppendASCII("simple_with_file"));
2642 ASSERT_TRUE(extension_);
2643 extension_id_ = extension_->id();
2644 ASSERT_TRUE(registry()->enabled_extensions().GetByID(extension_id_));
2645
2646 {
Jinho Bangb5216cec2018-01-17 19:43:112647 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
proberge901ecab2017-08-31 19:24:282648 processor_raw_ = processor.get();
2649 extension_sync_service()->MergeDataAndStartSyncing(
2650 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:112651 std::make_unique<syncer::SyncErrorFactoryMock>());
proberge901ecab2017-08-31 19:24:282652 }
2653 processor_raw_->changes().clear();
2654 }
2655
2656 void ForceBlacklistUpdate() {
2657 service()->OnBlacklistUpdated();
Gabriel Charette01507a22017-09-27 21:30:082658 content::RunAllTasksUntilIdle();
proberge901ecab2017-08-31 19:24:282659 }
2660
2661 syncer::FakeSyncChangeProcessor* processor() { return processor_raw_; }
2662
2663 const Extension* extension() { return extension_.get(); }
2664
2665 std::string& extension_id() { return extension_id_; }
2666
2667 extensions::TestBlacklist& test_blacklist() { return test_blacklist_; }
2668
2669 private:
2670 syncer::FakeSyncChangeProcessor* processor_raw_;
2671 scoped_refptr<const Extension> extension_;
2672 std::string extension_id_;
2673 extensions::TestBlacklist test_blacklist_;
2674
2675 DISALLOW_COPY_AND_ASSIGN(BlacklistedExtensionSyncServiceTest);
2676};
2677
2678// Test that sync cannot enable blacklisted extensions.
2679TEST_F(BlacklistedExtensionSyncServiceTest, SyncBlacklistedExtension) {
2680 std::string& extension_id = this->extension_id();
2681
2682 // Blacklist the extension.
2683 test_blacklist().SetBlacklistState(extension_id,
2684 extensions::BLACKLISTED_MALWARE, true);
2685 ForceBlacklistUpdate();
2686
2687 // Try enabling the extension via sync.
2688 EnableExtensionFromSync(*extension());
2689
2690 // The extension should not be enabled.
2691 EXPECT_FALSE(registry()->enabled_extensions().GetByID(extension_id));
2692 EXPECT_TRUE(processor()->changes().empty());
2693}
2694
2695// Test that some greylisted extensions can be enabled through sync.
2696TEST_F(BlacklistedExtensionSyncServiceTest, SyncAllowedGreylistedExtension) {
2697 std::string& extension_id = this->extension_id();
2698
2699 // Greylist the extension.
2700 test_blacklist().SetBlacklistState(
2701 extension_id, extensions::BLACKLISTED_POTENTIALLY_UNWANTED, true);
2702 ForceBlacklistUpdate();
2703
2704 EXPECT_FALSE(registry()->enabled_extensions().GetByID(extension_id));
2705 {
2706 ASSERT_EQ(1u, processor()->changes().size());
2707 const SyncChange& change = processor()->changes()[0];
2708 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
2709 std::unique_ptr<ExtensionSyncData> data =
2710 ExtensionSyncData::CreateFromSyncData(change.sync_data());
2711 EXPECT_EQ(extension_id, data->id());
2712 EXPECT_EQ(extensions::disable_reason::DISABLE_GREYLIST,
2713 data->disable_reasons());
2714 EXPECT_FALSE(data->enabled());
2715 }
2716 processor()->changes().clear();
2717
2718 // Manually re-enabling the extension should work.
2719 service()->EnableExtension(extension_id);
2720 EXPECT_TRUE(registry()->enabled_extensions().GetByID(extension_id));
2721 {
2722 ASSERT_EQ(1u, processor()->changes().size());
2723 const SyncChange& change = processor()->changes()[0];
2724 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
2725 std::unique_ptr<ExtensionSyncData> data =
2726 ExtensionSyncData::CreateFromSyncData(change.sync_data());
2727 EXPECT_EQ(extension_id, data->id());
2728 EXPECT_EQ(0, data->disable_reasons());
2729 EXPECT_TRUE(data->enabled());
2730 }
2731 processor()->changes().clear();
2732}