blob: 47c5988546a37c9620ff220548821c518aae103f [file] [log] [blame]
treib9afc6212015-10-30 18:49:581// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
avia2f4804a2015-12-24 23:11:135#include <stddef.h>
6
treibb6af28cd2015-12-01 11:19:467#include <map>
dchengc963c7142016-04-08 03:55:228#include <memory>
treib9afc6212015-10-30 18:49:589#include <string>
limasdf3d102542015-12-09 03:58:4510#include <utility>
treib9afc6212015-10-30 18:49:5811
12#include "base/bind.h"
13#include "base/command_line.h"
14#include "base/files/file_util.h"
dchengc963c7142016-04-08 03:55:2215#include "base/memory/ptr_util.h"
treib9afc6212015-10-30 18:49:5816#include "base/memory/weak_ptr.h"
Avi Drissman5f0fb8c2018-12-25 23:20:4917#include "base/stl_util.h"
Evan Stade46d716d2017-06-02 20:50:0918#include "chrome/browser/chrome_notification_types.h"
rdevlin.cronin2f1ed4c2017-06-13 16:22:1319#include "chrome/browser/extensions/chrome_test_extension_loader.h"
treib9afc6212015-10-30 18:49:5820#include "chrome/browser/extensions/component_loader.h"
21#include "chrome/browser/extensions/extension_service.h"
22#include "chrome/browser/extensions/extension_service_test_with_install.h"
23#include "chrome/browser/extensions/extension_sync_data.h"
24#include "chrome/browser/extensions/extension_sync_service.h"
25#include "chrome/browser/extensions/extension_util.h"
[email protected]b55906912020-07-07 10:39:4026#include "chrome/browser/extensions/test_blocklist.h"
treib9afc6212015-10-30 18:49:5827#include "chrome/browser/extensions/updater/extension_updater.h"
Hans Wennborg9208992ba2019-10-14 14:02:4928#include "chrome/browser/profiles/profile_key.h"
treib9afc6212015-10-30 18:49:5829#include "chrome/browser/sync/profile_sync_service_factory.h"
Evan Stade46d716d2017-06-02 20:50:0930#include "chrome/browser/themes/theme_service.h"
31#include "chrome/browser/themes/theme_service_factory.h"
treib9afc6212015-10-30 18:49:5832#include "chrome/common/chrome_constants.h"
Konstantin Ganenkoae1129c2017-09-15 16:28:5933#include "chrome/common/extensions/extension_test_util.h"
treib9afc6212015-10-30 18:49:5834#include "chrome/common/extensions/sync_helper.h"
35#include "chrome/test/base/testing_profile.h"
rdevlin.cronin738501d2015-11-05 21:51:3636#include "components/crx_file/id_util.h"
Marc Treib2435e772019-02-20 12:25:3837#include "components/sync/driver/sync_service.h"
38#include "components/sync/driver/sync_user_settings.h"
skym71603842016-10-10 18:17:3139#include "components/sync/model/sync_data.h"
Marc Treib2435e772019-02-20 12:25:3840#include "components/sync/protocol/sync.pb.h"
Rushan Suleymanov633f4a0a2020-10-23 11:18:4341#include "components/sync/test/model/fake_sync_change_processor.h"
42#include "components/sync/test/model/sync_change_processor_wrapper_for_test.h"
43#include "components/sync/test/model/sync_error_factory_mock.h"
treibb6af28cd2015-12-01 11:19:4644#include "components/variations/variations_associated_data.h"
Kinuko Yasuda6ec805a2019-07-29 06:12:5645#include "content/public/browser/browser_context.h"
46#include "content/public/browser/storage_partition.h"
treib9afc6212015-10-30 18:49:5847#include "extensions/browser/app_sorting.h"
Devlin Croninbffe949eb2018-01-12 03:03:4048#include "extensions/browser/disable_reason.h"
treib9afc6212015-10-30 18:49:5849#include "extensions/browser/extension_prefs.h"
50#include "extensions/browser/extension_registry.h"
51#include "extensions/browser/extension_system.h"
karandeepb810e33402017-04-05 23:41:2252#include "extensions/browser/extension_util.h"
treib9afc6212015-10-30 18:49:5853#include "extensions/browser/management_policy.h"
rdevlin.cronin738501d2015-11-05 21:51:3654#include "extensions/common/extension_builder.h"
Swapnilf6f2f1d2021-01-14 18:50:4355#include "extensions/common/extension_urls.h"
treib9afc6212015-10-30 18:49:5856#include "extensions/common/manifest_url_handlers.h"
57#include "extensions/common/permissions/permission_set.h"
treib9afc6212015-10-30 18:49:5858
treib9afc6212015-10-30 18:49:5859using extensions::AppSorting;
60using extensions::Extension;
61using extensions::ExtensionPrefs;
David Bertoni58c113a2019-08-02 19:53:2662using extensions::ExtensionRegistry;
treib9afc6212015-10-30 18:49:5863using extensions::ExtensionSyncData;
64using extensions::ExtensionSystem;
65using extensions::Manifest;
66using extensions::PermissionSet;
treib65f103042015-12-03 10:21:3667using syncer::SyncChange;
68using syncer::SyncChangeList;
mamire9609642016-06-28 22:17:5469using testing::Mock;
treib65f103042015-12-03 10:21:3670
71namespace {
treib9afc6212015-10-30 18:49:5872
73const char good0[] = "behllobkkfkfnphdnhnkndlbkcpglgmj";
74const char good2[] = "bjafgdebaacbbbecmhlhpofkepfkgcpa";
75const char good_crx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
76const char page_action[] = "obcimlgaoabeegjmmpldobjndiealpln";
Joshua Pawlickif2f37f32018-11-05 21:40:5677const char theme2_crx[] = "ibcijncamhmjjdodjamgiipcgnnaeagd";
Tanmoy Mollik0960d702019-09-11 15:14:4778const syncer::SyncFirstSetupCompleteSource kSetSourceFromTest =
79 syncer::SyncFirstSetupCompleteSource::BASIC_FLOW;
treib9afc6212015-10-30 18:49:5880
rdevlin.cronin2f1ed4c2017-06-13 16:22:1381ExtensionSyncData GetDisableSyncData(const Extension& extension,
82 int disable_reasons) {
83 bool enabled = false;
84 bool incognito_enabled = false;
85 bool remote_install = false;
rdevlin.cronin2f1ed4c2017-06-13 16:22:1386 return ExtensionSyncData(extension, enabled, disable_reasons,
Swapnilf6f2f1d2021-01-14 18:50:4387 incognito_enabled, remote_install, GURL());
rdevlin.cronin2f1ed4c2017-06-13 16:22:1388}
89
90ExtensionSyncData GetEnableSyncData(const Extension& extension) {
91 bool enabled = true;
92 bool incognito_enabled = false;
93 bool remote_install = false;
Toby Huangd7caf252019-10-30 01:11:1694 return ExtensionSyncData(extension, enabled,
95 extensions::disable_reason::DISABLE_NONE,
Swapnilf6f2f1d2021-01-14 18:50:4396 incognito_enabled, remote_install, GURL());
rdevlin.cronin2f1ed4c2017-06-13 16:22:1397}
98
treib65f103042015-12-03 10:21:3699SyncChangeList MakeSyncChangeList(const std::string& id,
100 const sync_pb::EntitySpecifics& specifics,
101 SyncChange::SyncChangeType change_type) {
102 syncer::SyncData sync_data =
103 syncer::SyncData::CreateLocalData(id, "Name", specifics);
104 return SyncChangeList(1, SyncChange(FROM_HERE, change_type, sync_data));
105}
106
asargente48ab752016-03-12 00:59:20107// This is a FakeSyncChangeProcessor specialization that maintains a store of
108// SyncData items in the superclass' data_ member variable, treating it like a
109// map keyed by the extension id from the SyncData. Each instance of this class
110// should only be used for one model type (which should be either extensions or
111// apps) to match how the real sync system handles things.
112class StatefulChangeProcessor : public syncer::FakeSyncChangeProcessor {
113 public:
114 explicit StatefulChangeProcessor(syncer::ModelType expected_type)
115 : expected_type_(expected_type) {
116 EXPECT_TRUE(expected_type == syncer::ModelType::EXTENSIONS ||
117 expected_type == syncer::ModelType::APPS);
118 }
119
120 ~StatefulChangeProcessor() override {}
121
122 // We let our parent class, FakeSyncChangeProcessor, handle saving the
123 // changes for us, but in addition we "apply" these changes by treating
124 // the FakeSyncChangeProcessor's SyncDataList as a map keyed by extension
125 // id.
Victor Hugo Vianna Silvad591a082020-04-16 10:56:36126 base::Optional<syncer::ModelError> ProcessSyncChanges(
Brett Wilsone1a70422017-09-12 05:10:09127 const base::Location& from_here,
asargente48ab752016-03-12 00:59:20128 const syncer::SyncChangeList& change_list) override {
129 syncer::FakeSyncChangeProcessor::ProcessSyncChanges(from_here, change_list);
130 for (const auto& change : change_list) {
131 syncer::SyncData sync_data = change.sync_data();
132 EXPECT_EQ(expected_type_, sync_data.GetDataType());
133
dchengc963c7142016-04-08 03:55:22134 std::unique_ptr<ExtensionSyncData> modified =
asargente48ab752016-03-12 00:59:20135 ExtensionSyncData::CreateFromSyncData(sync_data);
136
137 // Start by removing any existing entry for this extension id.
138 syncer::SyncDataList& data_list = data();
139 for (auto iter = data_list.begin(); iter != data_list.end(); ++iter) {
dchengc963c7142016-04-08 03:55:22140 std::unique_ptr<ExtensionSyncData> existing =
asargente48ab752016-03-12 00:59:20141 ExtensionSyncData::CreateFromSyncData(*iter);
142 if (existing->id() == modified->id()) {
143 data_list.erase(iter);
144 break;
145 }
146 }
147
148 // Now add in the new data for this id, if appropriate.
149 if (change.change_type() == SyncChange::ACTION_ADD ||
150 change.change_type() == SyncChange::ACTION_UPDATE) {
151 data_list.push_back(sync_data);
152 } else if (change.change_type() != SyncChange::ACTION_DELETE) {
153 ADD_FAILURE() << "Unexpected change type " << change.change_type();
154 }
155 }
Victor Hugo Vianna Silvad591a082020-04-16 10:56:36156 return base::nullopt;
asargente48ab752016-03-12 00:59:20157 }
158
159 // We override this to help catch the error of trying to use a single
160 // StatefulChangeProcessor to process changes for both extensions and apps
161 // sync data.
162 syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override {
163 EXPECT_EQ(expected_type_, type);
164 return FakeSyncChangeProcessor::GetAllSyncData(type);
165 }
166
167 // This is a helper to vend a wrapped version of this object suitable for
168 // passing in to MergeDataAndStartSyncing, which takes a
dchengc963c7142016-04-08 03:55:22169 // std::unique_ptr<SyncChangeProcessor>, since in tests we typically don't
170 // want to
asargente48ab752016-03-12 00:59:20171 // give up ownership of a local change processor.
dchengc963c7142016-04-08 03:55:22172 std::unique_ptr<syncer::SyncChangeProcessor> GetWrapped() {
Jinho Bangb5216cec2018-01-17 19:43:11173 return std::make_unique<syncer::SyncChangeProcessorWrapperForTest>(this);
asargente48ab752016-03-12 00:59:20174 }
175
176 protected:
177 // The expected ModelType of changes that this processor will see.
178 syncer::ModelType expected_type_;
179
180 DISALLOW_COPY_AND_ASSIGN(StatefulChangeProcessor);
181};
182
treib65f103042015-12-03 10:21:36183} // namespace
184
treib9afc6212015-10-30 18:49:58185class ExtensionServiceSyncTest
186 : public extensions::ExtensionServiceTestWithInstall {
187 public:
188 void MockSyncStartFlare(bool* was_called,
189 syncer::ModelType* model_type_passed_in,
190 syncer::ModelType model_type) {
191 *was_called = true;
192 *model_type_passed_in = model_type;
193 }
194
asargente48ab752016-03-12 00:59:20195 // Helper to call MergeDataAndStartSyncing with no server data and dummy
196 // change processor / error factory.
197 void StartSyncing(syncer::ModelType type) {
198 ASSERT_TRUE(type == syncer::EXTENSIONS || type == syncer::APPS);
199 extension_sync_service()->MergeDataAndStartSyncing(
200 type, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11201 std::make_unique<syncer::FakeSyncChangeProcessor>(),
202 std::make_unique<syncer::SyncErrorFactoryMock>());
asargente48ab752016-03-12 00:59:20203 }
204
rdevlin.cronin2f1ed4c2017-06-13 16:22:13205 void DisableExtensionFromSync(const Extension& extension,
206 int disable_reasons) {
Minh X. Nguyen45479012017-08-18 21:35:36207 ExtensionSyncData disable_extension = GetDisableSyncData(
208 extension, extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13209 SyncChangeList list(
210 1, disable_extension.GetSyncChange(SyncChange::ACTION_UPDATE));
211 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
212 }
213
214 void EnableExtensionFromSync(const Extension& extension) {
215 ExtensionSyncData enable_extension = GetEnableSyncData(extension);
216 SyncChangeList list(
217 1, enable_extension.GetSyncChange(SyncChange::ACTION_UPDATE));
218 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
219 }
220
treib9afc6212015-10-30 18:49:58221 protected:
222 // Paths to some of the fake extensions.
223 base::FilePath good0_path() {
224 return data_dir()
225 .AppendASCII("good")
226 .AppendASCII("Extensions")
227 .AppendASCII(good0)
228 .AppendASCII("1.0.0.0");
229 }
230
231 ExtensionSyncService* extension_sync_service() {
232 return ExtensionSyncService::Get(profile());
233 }
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02234
235 ExtensionSystem* extension_system() {
236 return ExtensionSystem::Get(profile());
237 }
treib9afc6212015-10-30 18:49:58238};
239
240TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledComponent) {
241 InitializeEmptyExtensionService();
242
243 bool flare_was_called = false;
244 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
245 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
Victor Hugo Vianna Silva75334d92020-11-10 07:42:44246 extension_sync_service()->SetSyncStartFlareForTesting(base::BindRepeating(
247 &ExtensionServiceSyncTest::MockSyncStartFlare, factory.GetWeakPtr(),
248 &flare_was_called, // Safe due to WeakPtrFactory scope.
249 &triggered_type)); // Safe due to WeakPtrFactory scope.
treib9afc6212015-10-30 18:49:58250
251 // Install a component extension.
252 std::string manifest;
253 ASSERT_TRUE(base::ReadFileToString(
254 good0_path().Append(extensions::kManifestFilename), &manifest));
255 service()->component_loader()->Add(manifest, good0_path());
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02256 ASSERT_FALSE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58257 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02258 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58259
260 // Extensions added before service is_ready() don't trigger sync startup.
261 EXPECT_FALSE(flare_was_called);
262 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
263}
264
265TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledNormal) {
266 InitializeGoodInstalledExtensionService();
267
268 bool flare_was_called = false;
269 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
270 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
Victor Hugo Vianna Silva75334d92020-11-10 07:42:44271 extension_sync_service()->SetSyncStartFlareForTesting(base::BindRepeating(
272 &ExtensionServiceSyncTest::MockSyncStartFlare, factory.GetWeakPtr(),
273 &flare_was_called, // Safe due to WeakPtrFactory scope.
274 &triggered_type)); // Safe due to WeakPtrFactory scope.
treib9afc6212015-10-30 18:49:58275
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02276 ASSERT_FALSE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58277 service()->Init();
278 ASSERT_EQ(3u, loaded_.size());
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02279 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58280
281 // Extensions added before service is_ready() don't trigger sync startup.
282 EXPECT_FALSE(flare_was_called);
283 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
284}
285
286TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupOnInstall) {
287 InitializeEmptyExtensionService();
288 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02289 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58290
291 bool flare_was_called = false;
292 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
293 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
Victor Hugo Vianna Silva75334d92020-11-10 07:42:44294 extension_sync_service()->SetSyncStartFlareForTesting(base::BindRepeating(
295 &ExtensionServiceSyncTest::MockSyncStartFlare, factory.GetWeakPtr(),
296 &flare_was_called, // Safe due to WeakPtrFactory scope.
297 &triggered_type)); // Safe due to WeakPtrFactory scope.
treib9afc6212015-10-30 18:49:58298
299 base::FilePath path = data_dir().AppendASCII("good.crx");
300 InstallCRX(path, INSTALL_NEW);
301
302 EXPECT_TRUE(flare_was_called);
303 EXPECT_EQ(syncer::EXTENSIONS, triggered_type);
304
305 // Reset.
306 flare_was_called = false;
307 triggered_type = syncer::UNSPECIFIED;
308
309 // Once sync starts, flare should no longer be invoked.
310 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36311 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11312 std::make_unique<syncer::FakeSyncChangeProcessor>(),
313 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58314 path = data_dir().AppendASCII("page_action.crx");
315 InstallCRX(path, INSTALL_NEW);
316 EXPECT_FALSE(flare_was_called);
317 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
318}
319
320TEST_F(ExtensionServiceSyncTest, DisableExtensionFromSync) {
321 // Start the extensions service with one external extension already installed.
322 base::FilePath source_install_dir =
323 data_dir().AppendASCII("good").AppendASCII("Extensions");
324 base::FilePath pref_path =
325 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
326
327 InitializeInstalledExtensionService(pref_path, source_install_dir);
328
329 // The user has enabled sync.
Marc Treib5a78e9c2019-02-19 16:47:01330 syncer::SyncService* sync_service =
treib9afc6212015-10-30 18:49:58331 ProfileSyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:47332 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
treib9afc6212015-10-30 18:49:58333
334 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02335 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58336
337 ASSERT_EQ(3u, loaded_.size());
338
339 // We start enabled.
David Bertonia0b34722019-09-30 20:51:26340 const Extension* extension = registry()->enabled_extensions().GetByID(good0);
treib9afc6212015-10-30 18:49:58341 ASSERT_TRUE(extension);
342 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
343
344 // Sync starts up.
345 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36346 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11347 std::make_unique<syncer::FakeSyncChangeProcessor>(),
348 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58349
350 // Then sync data arrives telling us to disable |good0|.
Minh X. Nguyen45479012017-08-18 21:35:36351 ExtensionSyncData disable_good_crx(
352 *extension, false, extensions::disable_reason::DISABLE_USER_ACTION, false,
Swapnilf6f2f1d2021-01-14 18:50:43353 false, extension_urls::GetWebstoreUpdateUrl());
treib65f103042015-12-03 10:21:36354 SyncChangeList list(
355 1, disable_good_crx.GetSyncChange(SyncChange::ACTION_UPDATE));
treib9afc6212015-10-30 18:49:58356 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
357
358 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
359}
360
rdevlin.cronin2f1ed4c2017-06-13 16:22:13361// Test that sync can enable and disable installed extensions.
362TEST_F(ExtensionServiceSyncTest, ReenableDisabledExtensionFromSync) {
363 InitializeEmptyExtensionService();
364
365 // Enable sync.
Marc Treib5a78e9c2019-02-19 16:47:01366 syncer::SyncService* sync_service =
rdevlin.cronin2f1ed4c2017-06-13 16:22:13367 ProfileSyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:47368 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13369
370 service()->Init();
371
372 // Load up a simple extension.
373 extensions::ChromeTestExtensionLoader extension_loader(profile());
374 extension_loader.set_pack_extension(true);
375 scoped_refptr<const Extension> extension = extension_loader.LoadExtension(
376 data_dir().AppendASCII("simple_with_file"));
377 ASSERT_TRUE(extension);
378 const std::string kExtensionId = extension->id();
379 ASSERT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
380
381 syncer::FakeSyncChangeProcessor* processor_raw = nullptr;
382 {
Jinho Bangb5216cec2018-01-17 19:43:11383 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
rdevlin.cronin2f1ed4c2017-06-13 16:22:13384 processor_raw = processor.get();
385 extension_sync_service()->MergeDataAndStartSyncing(
386 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:11387 std::make_unique<syncer::SyncErrorFactoryMock>());
rdevlin.cronin2f1ed4c2017-06-13 16:22:13388 }
389 processor_raw->changes().clear();
390
Minh X. Nguyen45479012017-08-18 21:35:36391 DisableExtensionFromSync(*extension,
392 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13393
394 // The extension should be disabled.
395 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
Minh X. Nguyen45479012017-08-18 21:35:36396 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
rdevlin.cronin2f1ed4c2017-06-13 16:22:13397 ExtensionPrefs::Get(profile())->GetDisableReasons(kExtensionId));
398 EXPECT_TRUE(processor_raw->changes().empty());
399
400 // Enable the extension. Sync should push the new state.
401 service()->EnableExtension(kExtensionId);
402 {
403 ASSERT_EQ(1u, processor_raw->changes().size());
404 const SyncChange& change = processor_raw->changes()[0];
405 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
406 std::unique_ptr<ExtensionSyncData> data =
407 ExtensionSyncData::CreateFromSyncData(change.sync_data());
408 EXPECT_EQ(kExtensionId, data->id());
409 EXPECT_EQ(0, data->disable_reasons());
410 EXPECT_TRUE(data->enabled());
411 }
412
413 // Disable the extension again. Sync should push the new state.
414 processor_raw->changes().clear();
Minh X. Nguyen45479012017-08-18 21:35:36415 service()->DisableExtension(kExtensionId,
416 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13417 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
418 {
419 ASSERT_EQ(1u, processor_raw->changes().size());
420 const SyncChange& change = processor_raw->changes()[0];
421 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
422 std::unique_ptr<ExtensionSyncData> data =
423 ExtensionSyncData::CreateFromSyncData(change.sync_data());
424 EXPECT_EQ(kExtensionId, data->id());
Minh X. Nguyen45479012017-08-18 21:35:36425 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
426 data->disable_reasons());
rdevlin.cronin2f1ed4c2017-06-13 16:22:13427 EXPECT_FALSE(data->enabled());
428 }
429 processor_raw->changes().clear();
430
431 // Enable the extension via sync.
432 EnableExtensionFromSync(*extension);
433
434 // The extension should be enabled.
435 EXPECT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
436 EXPECT_TRUE(processor_raw->changes().empty());
437}
438
439// Tests that default-installed extensions won't be affected by incoming sync
440// data. (It's feasible to have a sync entry for an extension that could be
441// default installed, since one installation may be default-installed while
442// another may not be).
443TEST_F(ExtensionServiceSyncTest,
444 DefaultInstalledExtensionsAreNotReenabledOrDisabledBySync) {
445 InitializeEmptyExtensionService();
446
447 // Enable sync.
Marc Treib5a78e9c2019-02-19 16:47:01448 syncer::SyncService* sync_service =
rdevlin.cronin2f1ed4c2017-06-13 16:22:13449 ProfileSyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:47450 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13451
452 service()->Init();
453
454 // Load up an extension that's considered default installed.
455 extensions::ChromeTestExtensionLoader extension_loader(profile());
456 extension_loader.set_pack_extension(true);
457 extension_loader.add_creation_flag(Extension::WAS_INSTALLED_BY_DEFAULT);
458 scoped_refptr<const Extension> extension = extension_loader.LoadExtension(
459 data_dir().AppendASCII("simple_with_file"));
460 ASSERT_TRUE(extension);
461
462 // The extension shouldn't sync.
463 EXPECT_FALSE(extensions::util::ShouldSync(extension.get(), profile()));
464 const std::string kExtensionId = extension->id();
465 ASSERT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
466
467 syncer::FakeSyncChangeProcessor* processor_raw = nullptr;
468 {
Jinho Bangb5216cec2018-01-17 19:43:11469 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
rdevlin.cronin2f1ed4c2017-06-13 16:22:13470 processor_raw = processor.get();
471 extension_sync_service()->MergeDataAndStartSyncing(
472 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:11473 std::make_unique<syncer::SyncErrorFactoryMock>());
rdevlin.cronin2f1ed4c2017-06-13 16:22:13474 }
475 processor_raw->changes().clear();
476
477 // Sync state says the extension is disabled (e.g. on another machine).
Minh X. Nguyen45479012017-08-18 21:35:36478 DisableExtensionFromSync(*extension,
479 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13480
481 // The extension should still be enabled, since it's default-installed.
482 EXPECT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
483 EXPECT_TRUE(processor_raw->changes().empty());
484
485 // Now disable the extension locally. Sync should *not* push new state.
Minh X. Nguyen45479012017-08-18 21:35:36486 service()->DisableExtension(kExtensionId,
487 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13488 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
489 EXPECT_TRUE(processor_raw->changes().empty());
490
491 // Sync state says the extension is enabled.
492 EnableExtensionFromSync(*extension);
493
494 // As above, the extension should not have been affected by sync.
495 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
496 EXPECT_TRUE(processor_raw->changes().empty());
497
498 // And re-enabling the extension should not push new state to sync.
499 service()->EnableExtension(kExtensionId);
500 EXPECT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
501 EXPECT_TRUE(processor_raw->changes().empty());
502}
503
treib9afc6212015-10-30 18:49:58504TEST_F(ExtensionServiceSyncTest, IgnoreSyncChangesWhenLocalStateIsMoreRecent) {
505 // Start the extension service with three extensions already installed.
506 base::FilePath source_install_dir =
507 data_dir().AppendASCII("good").AppendASCII("Extensions");
508 base::FilePath pref_path =
509 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
510
511 InitializeInstalledExtensionService(pref_path, source_install_dir);
512
513 // The user has enabled sync.
Marc Treib5a78e9c2019-02-19 16:47:01514 syncer::SyncService* sync_service =
treib9afc6212015-10-30 18:49:58515 ProfileSyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:47516 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
treib9afc6212015-10-30 18:49:58517 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
518 extension_sync_service();
519
520 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02521 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58522 ASSERT_EQ(3u, loaded_.size());
523
524 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
525 ASSERT_TRUE(service()->IsExtensionEnabled(good2));
526
527 // Disable and re-enable good0 before first sync data arrives.
Minh X. Nguyen45479012017-08-18 21:35:36528 service()->DisableExtension(good0,
529 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:58530 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
531 service()->EnableExtension(good0);
532 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
533 // Disable good2 before first sync data arrives (good1 is considered
534 // non-syncable because it has plugin permission).
Minh X. Nguyen45479012017-08-18 21:35:36535 service()->DisableExtension(good2,
536 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:58537 ASSERT_FALSE(service()->IsExtensionEnabled(good2));
538
David Bertonia0b34722019-09-30 20:51:26539 const Extension* extension0 = registry()->enabled_extensions().GetByID(good0);
David Bertoni58c113a2019-08-02 19:53:26540 const Extension* extension2 =
David Bertonia0b34722019-09-30 20:51:26541 registry()->disabled_extensions().GetByID(good2);
treib9afc6212015-10-30 18:49:58542 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension0));
543 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension2));
544
545 // Now sync data comes in that says to disable good0 and enable good2.
Minh X. Nguyen45479012017-08-18 21:35:36546 ExtensionSyncData disable_good0(
547 *extension0, false, extensions::disable_reason::DISABLE_USER_ACTION,
Swapnilf6f2f1d2021-01-14 18:50:43548 false, false, extension_urls::GetWebstoreUpdateUrl());
549 ExtensionSyncData enable_good2(
550 *extension2, true, extensions::disable_reason::DISABLE_NONE, false, false,
551 extension_urls::GetWebstoreUpdateUrl());
treib9afc6212015-10-30 18:49:58552 syncer::SyncDataList sync_data;
553 sync_data.push_back(disable_good0.GetSyncData());
554 sync_data.push_back(enable_good2.GetSyncData());
555 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:22556 syncer::EXTENSIONS, sync_data,
Jinho Bangb5216cec2018-01-17 19:43:11557 std::make_unique<syncer::FakeSyncChangeProcessor>(),
558 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58559
560 // Both sync changes should be ignored, since the local state was changed
561 // before sync started, and so the local state is considered more recent.
562 EXPECT_TRUE(service()->IsExtensionEnabled(good0));
563 EXPECT_FALSE(service()->IsExtensionEnabled(good2));
564}
565
treibb794dd52015-12-01 18:47:14566TEST_F(ExtensionServiceSyncTest, DontSelfNotify) {
567 // Start the extension service with three extensions already installed.
568 base::FilePath source_install_dir =
569 data_dir().AppendASCII("good").AppendASCII("Extensions");
570 base::FilePath pref_path =
571 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
572
573 InitializeInstalledExtensionService(pref_path, source_install_dir);
574
575 // The user has enabled sync.
Marc Treib9948a682018-11-20 08:01:37576 ProfileSyncServiceFactory::GetForProfile(profile())
577 ->GetUserSettings()
Tanmoy Mollik0960d702019-09-11 15:14:47578 ->SetFirstSetupComplete(kSetSourceFromTest);
treibb794dd52015-12-01 18:47:14579 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
580 extension_sync_service();
581
582 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02583 ASSERT_TRUE(extension_system()->is_ready());
treibb794dd52015-12-01 18:47:14584 ASSERT_EQ(3u, loaded_.size());
585 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
586
587 syncer::FakeSyncChangeProcessor* processor =
588 new syncer::FakeSyncChangeProcessor;
589 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:22590 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
Jinho Bangb5216cec2018-01-17 19:43:11591 std::make_unique<syncer::SyncErrorFactoryMock>());
treibb794dd52015-12-01 18:47:14592
593 processor->changes().clear();
594
595 // Simulate various incoming sync changes, and make sure they don't result in
596 // any outgoing changes.
597
598 {
David Bertoni58c113a2019-08-02 19:53:26599 const Extension* extension =
David Bertonia0b34722019-09-30 20:51:26600 registry()->enabled_extensions().GetByID(good0);
treibb794dd52015-12-01 18:47:14601 ASSERT_TRUE(extension);
602
603 // Disable the extension.
Swapnilf6f2f1d2021-01-14 18:50:43604 ExtensionSyncData data(
605 *extension, false, extensions::disable_reason::DISABLE_USER_ACTION,
606 false, false, extension_urls::GetWebstoreUpdateUrl());
treib65f103042015-12-03 10:21:36607 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14608
609 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
610
611 EXPECT_TRUE(processor->changes().empty());
612 }
613
614 {
David Bertoni58c113a2019-08-02 19:53:26615 const Extension* extension =
David Bertonia0b34722019-09-30 20:51:26616 registry()->disabled_extensions().GetByID(good0);
treibb794dd52015-12-01 18:47:14617 ASSERT_TRUE(extension);
618
619 // Set incognito enabled to true.
Minh X. Nguyen45479012017-08-18 21:35:36620 ExtensionSyncData data(*extension, false,
621 extensions::disable_reason::DISABLE_NONE, true,
Swapnilf6f2f1d2021-01-14 18:50:43622 false, extension_urls::GetWebstoreUpdateUrl());
treib65f103042015-12-03 10:21:36623 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14624
625 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
626
627 EXPECT_TRUE(processor->changes().empty());
628 }
629
630 {
David Bertoni58c113a2019-08-02 19:53:26631 const Extension* extension =
David Bertonia0b34722019-09-30 20:51:26632 registry()->disabled_extensions().GetByID(good0);
treibb794dd52015-12-01 18:47:14633 ASSERT_TRUE(extension);
634
635 // Add another disable reason.
Minh X. Nguyen45479012017-08-18 21:35:36636 ExtensionSyncData data(
637 *extension, false,
638 extensions::disable_reason::DISABLE_USER_ACTION |
639 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
Swapnilf6f2f1d2021-01-14 18:50:43640 false, false, extension_urls::GetWebstoreUpdateUrl());
treib65f103042015-12-03 10:21:36641 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14642
643 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
644
645 EXPECT_TRUE(processor->changes().empty());
646 }
647
648 {
David Bertoni58c113a2019-08-02 19:53:26649 const Extension* extension =
David Bertonia0b34722019-09-30 20:51:26650 registry()->disabled_extensions().GetByID(good0);
treibb794dd52015-12-01 18:47:14651 ASSERT_TRUE(extension);
652
653 // Uninstall the extension.
Minh X. Nguyen45479012017-08-18 21:35:36654 ExtensionSyncData data(
655 *extension, false,
656 extensions::disable_reason::DISABLE_USER_ACTION |
657 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
Swapnilf6f2f1d2021-01-14 18:50:43658 false, false, extension_urls::GetWebstoreUpdateUrl());
treib65f103042015-12-03 10:21:36659 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_DELETE));
treibb794dd52015-12-01 18:47:14660
661 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
662
663 EXPECT_TRUE(processor->changes().empty());
664 }
665}
666
treib9afc6212015-10-30 18:49:58667TEST_F(ExtensionServiceSyncTest, GetSyncData) {
668 InitializeEmptyExtensionService();
669 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
David Bertoni9f897c92019-09-20 17:46:35670 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58671 ASSERT_TRUE(extension);
672
673 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36674 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11675 std::make_unique<syncer::FakeSyncChangeProcessor>(),
676 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58677
678 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16679 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58680 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22681 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58682 ExtensionSyncData::CreateFromSyncData(list[0]);
683 ASSERT_TRUE(data.get());
684 EXPECT_EQ(extension->id(), data->id());
685 EXPECT_FALSE(data->uninstalled());
686 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
687 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
688 data->incognito_enabled());
Devlin Cronin03bf2d22017-12-20 08:21:05689 EXPECT_EQ(data->version(), extension->version());
treib9afc6212015-10-30 18:49:58690 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
691 data->update_url());
692 EXPECT_EQ(extension->name(), data->name());
693}
694
treib29e1b9b12015-11-11 08:50:56695TEST_F(ExtensionServiceSyncTest, GetSyncDataDisableReasons) {
696 InitializeEmptyExtensionService();
697 const Extension* extension =
698 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
699 ASSERT_TRUE(extension);
700
treib29e1b9b12015-11-11 08:50:56701 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36702 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11703 std::make_unique<syncer::FakeSyncChangeProcessor>(),
704 std::make_unique<syncer::SyncErrorFactoryMock>());
treib29e1b9b12015-11-11 08:50:56705
706 {
707 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16708 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib29e1b9b12015-11-11 08:50:56709 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22710 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56711 ExtensionSyncData::CreateFromSyncData(list[0]);
712 ASSERT_TRUE(data.get());
713 EXPECT_TRUE(data->enabled());
714 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36715 EXPECT_EQ(extensions::disable_reason::DISABLE_NONE,
716 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56717 }
718
719 // Syncable disable reason, should propagate to sync.
Minh X. Nguyen45479012017-08-18 21:35:36720 service()->DisableExtension(good_crx,
721 extensions::disable_reason::DISABLE_USER_ACTION);
treib29e1b9b12015-11-11 08:50:56722 {
723 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16724 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib29e1b9b12015-11-11 08:50:56725 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22726 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56727 ExtensionSyncData::CreateFromSyncData(list[0]);
728 ASSERT_TRUE(data.get());
729 EXPECT_FALSE(data->enabled());
730 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36731 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
732 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56733 }
734 service()->EnableExtension(good_crx);
735
736 // Non-syncable disable reason. The sync data should still say "enabled".
Minh X. Nguyen45479012017-08-18 21:35:36737 service()->DisableExtension(good_crx,
738 extensions::disable_reason::DISABLE_RELOAD);
treib29e1b9b12015-11-11 08:50:56739 {
740 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16741 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib29e1b9b12015-11-11 08:50:56742 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22743 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56744 ExtensionSyncData::CreateFromSyncData(list[0]);
745 ASSERT_TRUE(data.get());
746 EXPECT_TRUE(data->enabled());
747 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36748 EXPECT_EQ(extensions::disable_reason::DISABLE_NONE,
749 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56750 }
751 service()->EnableExtension(good_crx);
752
753 // Both a syncable and a non-syncable disable reason, only the former should
754 // propagate to sync.
Minh X. Nguyen45479012017-08-18 21:35:36755 service()->DisableExtension(good_crx,
756 extensions::disable_reason::DISABLE_USER_ACTION |
757 extensions::disable_reason::DISABLE_RELOAD);
treib29e1b9b12015-11-11 08:50:56758 {
759 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16760 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib29e1b9b12015-11-11 08:50:56761 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22762 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56763 ExtensionSyncData::CreateFromSyncData(list[0]);
764 ASSERT_TRUE(data.get());
765 EXPECT_FALSE(data->enabled());
766 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36767 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
768 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56769 }
770 service()->EnableExtension(good_crx);
771}
772
treib9afc6212015-10-30 18:49:58773TEST_F(ExtensionServiceSyncTest, GetSyncDataTerminated) {
774 InitializeEmptyExtensionService();
775 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
776 TerminateExtension(good_crx);
David Bertoni9f897c92019-09-20 17:46:35777 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58778 ASSERT_TRUE(extension);
779
treib9afc6212015-10-30 18:49:58780 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36781 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11782 std::make_unique<syncer::FakeSyncChangeProcessor>(),
783 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58784
785 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16786 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58787 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22788 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58789 ExtensionSyncData::CreateFromSyncData(list[0]);
790 ASSERT_TRUE(data.get());
791 EXPECT_EQ(extension->id(), data->id());
792 EXPECT_FALSE(data->uninstalled());
793 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
794 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
795 data->incognito_enabled());
Devlin Cronin03bf2d22017-12-20 08:21:05796 EXPECT_EQ(data->version(), extension->version());
treib9afc6212015-10-30 18:49:58797 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
798 data->update_url());
799 EXPECT_EQ(extension->name(), data->name());
800}
801
802TEST_F(ExtensionServiceSyncTest, GetSyncDataFilter) {
803 InitializeEmptyExtensionService();
804 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
David Bertoni9f897c92019-09-20 17:46:35805 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58806 ASSERT_TRUE(extension);
807
treib9afc6212015-10-30 18:49:58808 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36809 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11810 std::make_unique<syncer::FakeSyncChangeProcessor>(),
811 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58812
813 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16814 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58815 ASSERT_EQ(list.size(), 0U);
816}
817
818TEST_F(ExtensionServiceSyncTest, GetSyncExtensionDataUserSettings) {
819 InitializeEmptyExtensionService();
820 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
David Bertoni9f897c92019-09-20 17:46:35821 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58822 ASSERT_TRUE(extension);
823
treib9afc6212015-10-30 18:49:58824 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36825 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11826 std::make_unique<syncer::FakeSyncChangeProcessor>(),
827 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58828
829 {
830 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16831 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58832 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22833 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58834 ExtensionSyncData::CreateFromSyncData(list[0]);
835 ASSERT_TRUE(data.get());
836 EXPECT_TRUE(data->enabled());
837 EXPECT_FALSE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58838 }
839
Minh X. Nguyen45479012017-08-18 21:35:36840 service()->DisableExtension(good_crx,
841 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:58842 {
843 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16844 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58845 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22846 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58847 ExtensionSyncData::CreateFromSyncData(list[0]);
848 ASSERT_TRUE(data.get());
849 EXPECT_FALSE(data->enabled());
850 EXPECT_FALSE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58851 }
852
853 extensions::util::SetIsIncognitoEnabled(good_crx, profile(), true);
treib9afc6212015-10-30 18:49:58854 {
855 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16856 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58857 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22858 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58859 ExtensionSyncData::CreateFromSyncData(list[0]);
860 ASSERT_TRUE(data.get());
861 EXPECT_FALSE(data->enabled());
862 EXPECT_TRUE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58863 }
864
865 service()->EnableExtension(good_crx);
treib9afc6212015-10-30 18:49:58866 {
867 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16868 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58869 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22870 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58871 ExtensionSyncData::CreateFromSyncData(list[0]);
872 ASSERT_TRUE(data.get());
873 EXPECT_TRUE(data->enabled());
874 EXPECT_TRUE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58875 }
876}
877
878TEST_F(ExtensionServiceSyncTest, SyncForUninstalledExternalExtension) {
879 InitializeEmptyExtensionService();
catmullings22bc2372016-11-02 19:59:35880 InstallCRX(data_dir().AppendASCII("good.crx"), Manifest::EXTERNAL_PREF,
881 INSTALL_NEW, Extension::NO_FLAGS);
David Bertoni9f897c92019-09-20 17:46:35882 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58883 ASSERT_TRUE(extension);
884
treib9afc6212015-10-30 18:49:58885 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36886 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11887 std::make_unique<syncer::FakeSyncChangeProcessor>(),
888 std::make_unique<syncer::SyncErrorFactoryMock>());
asargente48ab752016-03-12 00:59:20889 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:58890
Devlin Cronin6fd1cd62017-12-05 19:13:57891 UninstallExtension(good_crx);
treib9afc6212015-10-30 18:49:58892 EXPECT_TRUE(
893 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
894
895 sync_pb::EntitySpecifics specifics;
896 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
897 sync_pb::ExtensionSpecifics* extension_specifics =
898 app_specifics->mutable_extension();
899 extension_specifics->set_id(good_crx);
900 extension_specifics->set_version("1.0");
901 extension_specifics->set_enabled(true);
902
treib65f103042015-12-03 10:21:36903 SyncChangeList list =
904 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:58905
906 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
907 EXPECT_TRUE(
908 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
909}
910
911TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettings) {
912 InitializeEmptyExtensionService();
913 const Extension* app =
914 PackAndInstallCRX(data_dir().AppendASCII("app"), INSTALL_NEW);
915 ASSERT_TRUE(app);
916 ASSERT_TRUE(app->is_app());
917
treib9afc6212015-10-30 18:49:58918 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36919 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11920 std::make_unique<syncer::FakeSyncChangeProcessor>(),
921 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58922
923 syncer::StringOrdinal initial_ordinal =
924 syncer::StringOrdinal::CreateInitialOrdinal();
925 {
926 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16927 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS);
treib9afc6212015-10-30 18:49:58928 ASSERT_EQ(list.size(), 1U);
929
dchengc963c7142016-04-08 03:55:22930 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58931 ExtensionSyncData::CreateFromSyncData(list[0]);
932 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->app_launch_ordinal()));
933 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
934 }
935
deepak.m14ba69e62015-11-17 05:42:12936 AppSorting* sorting = ExtensionSystem::Get(profile())->app_sorting();
treib9afc6212015-10-30 18:49:58937 sorting->SetAppLaunchOrdinal(app->id(), initial_ordinal.CreateAfter());
938 {
939 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16940 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS);
treib9afc6212015-10-30 18:49:58941 ASSERT_EQ(list.size(), 1U);
942
dchengc963c7142016-04-08 03:55:22943 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58944 ExtensionSyncData::CreateFromSyncData(list[0]);
945 ASSERT_TRUE(app_sync_data.get());
946 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
947 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
948 }
949
950 sorting->SetPageOrdinal(app->id(), initial_ordinal.CreateAfter());
951 {
952 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16953 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS);
treib9afc6212015-10-30 18:49:58954 ASSERT_EQ(list.size(), 1U);
955
dchengc963c7142016-04-08 03:55:22956 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58957 ExtensionSyncData::CreateFromSyncData(list[0]);
958 ASSERT_TRUE(app_sync_data.get());
959 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
960 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->page_ordinal()));
961 }
962}
963
964// TODO (rdevlin.cronin): The OnExtensionMoved() method has been removed from
965// ExtensionService, so this test probably needs a new home. Unfortunately, it
966// relies pretty heavily on things like InitializeExtension[Sync]Service() and
967// PackAndInstallCRX(). When we clean up a bit more, this should move out.
968TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettingsOnExtensionMoved) {
969 InitializeEmptyExtensionService();
970 const size_t kAppCount = 3;
971 const Extension* apps[kAppCount];
972 apps[0] = PackAndInstallCRX(data_dir().AppendASCII("app1"), INSTALL_NEW);
973 apps[1] = PackAndInstallCRX(data_dir().AppendASCII("app2"), INSTALL_NEW);
974 apps[2] = PackAndInstallCRX(data_dir().AppendASCII("app4"), INSTALL_NEW);
975 for (size_t i = 0; i < kAppCount; ++i) {
976 ASSERT_TRUE(apps[i]);
977 ASSERT_TRUE(apps[i]->is_app());
978 }
979
treib9afc6212015-10-30 18:49:58980 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36981 syncer::APPS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22982 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
983 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58984
deepak.m14ba69e62015-11-17 05:42:12985 ExtensionSystem::Get(service()->GetBrowserContext())
treib9afc6212015-10-30 18:49:58986 ->app_sorting()
987 ->OnExtensionMoved(apps[0]->id(), apps[1]->id(), apps[2]->id());
988 {
989 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16990 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS);
treib9afc6212015-10-30 18:49:58991 ASSERT_EQ(list.size(), 3U);
992
dchengc963c7142016-04-08 03:55:22993 std::unique_ptr<ExtensionSyncData> data[kAppCount];
treib9afc6212015-10-30 18:49:58994 for (size_t i = 0; i < kAppCount; ++i) {
995 data[i] = ExtensionSyncData::CreateFromSyncData(list[i]);
996 ASSERT_TRUE(data[i].get());
997 }
998
999 // The sync data is not always in the same order our apps were installed in,
1000 // so we do that sorting here so we can make sure the values are changed as
1001 // expected.
1002 syncer::StringOrdinal app_launch_ordinals[kAppCount];
1003 for (size_t i = 0; i < kAppCount; ++i) {
1004 for (size_t j = 0; j < kAppCount; ++j) {
1005 if (apps[i]->id() == data[j]->id())
1006 app_launch_ordinals[i] = data[j]->app_launch_ordinal();
1007 }
1008 }
1009
1010 EXPECT_TRUE(app_launch_ordinals[1].LessThan(app_launch_ordinals[0]));
1011 EXPECT_TRUE(app_launch_ordinals[0].LessThan(app_launch_ordinals[2]));
1012 }
1013}
1014
1015TEST_F(ExtensionServiceSyncTest, GetSyncDataList) {
1016 InitializeEmptyExtensionService();
1017 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1018 InstallCRX(data_dir().AppendASCII("page_action.crx"), INSTALL_NEW);
1019 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
1020 InstallCRX(data_dir().AppendASCII("theme2.crx"), INSTALL_NEW);
1021
treib9afc6212015-10-30 18:49:581022 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361023 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111024 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1025 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581026 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361027 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111028 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1029 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581030
Minh X. Nguyen45479012017-08-18 21:35:361031 service()->DisableExtension(page_action,
1032 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:581033 TerminateExtension(theme2_crx);
1034
treib9afc6212015-10-30 18:49:581035 EXPECT_EQ(
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:161036 0u,
1037 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS).size());
1038 EXPECT_EQ(2u, extension_sync_service()
1039 ->GetAllSyncDataForTesting(syncer::EXTENSIONS)
1040 .size());
treib9afc6212015-10-30 18:49:581041}
1042
1043TEST_F(ExtensionServiceSyncTest, ProcessSyncDataUninstall) {
1044 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581045 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361046 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111047 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1048 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581049
1050 sync_pb::EntitySpecifics specifics;
1051 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1052 ext_specifics->set_id(good_crx);
1053 ext_specifics->set_version("1.0");
treib65f103042015-12-03 10:21:361054
1055 SyncChangeList list =
1056 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:581057
1058 // Should do nothing.
1059 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertoni58c113a2019-08-02 19:53:261060 EXPECT_FALSE(
David Bertonia0b34722019-09-30 20:51:261061 registry()->GetExtensionById(good_crx, ExtensionRegistry::EVERYTHING));
treib9afc6212015-10-30 18:49:581062
1063 // Install the extension.
1064 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
1065 InstallCRX(extension_path, INSTALL_NEW);
David Bertonia0b34722019-09-30 20:51:261066 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581067
1068 // Should uninstall the extension.
1069 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertoni58c113a2019-08-02 19:53:261070 EXPECT_FALSE(
David Bertonia0b34722019-09-30 20:51:261071 registry()->GetExtensionById(good_crx, ExtensionRegistry::EVERYTHING));
treib9afc6212015-10-30 18:49:581072
1073 // Should again do nothing.
1074 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertoni58c113a2019-08-02 19:53:261075 EXPECT_FALSE(
David Bertonia0b34722019-09-30 20:51:261076 registry()->GetExtensionById(good_crx, ExtensionRegistry::EVERYTHING));
treib9afc6212015-10-30 18:49:581077}
1078
1079TEST_F(ExtensionServiceSyncTest, ProcessSyncDataWrongType) {
1080 InitializeEmptyExtensionService();
asargente48ab752016-03-12 00:59:201081 StartSyncing(syncer::EXTENSIONS);
1082 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:581083
1084 // Install the extension.
1085 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
1086 InstallCRX(extension_path, INSTALL_NEW);
David Bertonia0b34722019-09-30 20:51:261087 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581088
1089 sync_pb::EntitySpecifics specifics;
1090 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
1091 sync_pb::ExtensionSpecifics* extension_specifics =
1092 app_specifics->mutable_extension();
1093 extension_specifics->set_id(good_crx);
1094 extension_specifics->set_version(
David Bertoni9f897c92019-09-20 17:46:351095 registry()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581096
1097 {
1098 extension_specifics->set_enabled(true);
treib65f103042015-12-03 10:21:361099
1100 SyncChangeList list =
1101 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:581102
1103 // Should do nothing
1104 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertonia0b34722019-09-30 20:51:261105 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581106 }
1107
1108 {
1109 extension_specifics->set_enabled(false);
treib65f103042015-12-03 10:21:361110
1111 SyncChangeList list =
1112 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581113
1114 // Should again do nothing.
1115 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertonia0b34722019-09-30 20:51:261116 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581117 }
1118}
1119
1120TEST_F(ExtensionServiceSyncTest, ProcessSyncDataSettings) {
1121 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581122 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361123 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111124 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1125 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581126
1127 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1128 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1129 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
treib9afc6212015-10-30 18:49:581130
1131 sync_pb::EntitySpecifics specifics;
1132 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1133 ext_specifics->set_id(good_crx);
1134 ext_specifics->set_version(
David Bertoni9f897c92019-09-20 17:46:351135 registry()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581136 ext_specifics->set_enabled(false);
1137
1138 {
treib65f103042015-12-03 10:21:361139 SyncChangeList list =
1140 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1141
treib9afc6212015-10-30 18:49:581142 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1143 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1144 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
treib9afc6212015-10-30 18:49:581145 }
1146
1147 {
1148 ext_specifics->set_enabled(true);
1149 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361150
1151 SyncChangeList list =
1152 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1153
treib9afc6212015-10-30 18:49:581154 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1155 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1156 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1157 }
1158
1159 {
1160 ext_specifics->set_enabled(false);
1161 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361162
1163 SyncChangeList list =
1164 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1165
treib9afc6212015-10-30 18:49:581166 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1167 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1168 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1169 }
1170
1171 {
1172 ext_specifics->set_enabled(true);
treib65f103042015-12-03 10:21:361173
1174 SyncChangeList list =
1175 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1176
treib9afc6212015-10-30 18:49:581177 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1178 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
treib9afc6212015-10-30 18:49:581179 }
1180
1181 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1182}
1183
1184TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNewExtension) {
1185 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581186 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361187 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111188 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1189 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581190
1191 const base::FilePath path = data_dir().AppendASCII("good.crx");
1192 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1193
1194 struct TestCase {
1195 const char* name; // For failure output only.
1196 bool sync_enabled; // The "enabled" flag coming in from Sync.
1197 // The disable reason(s) coming in from Sync, or -1 for "not set".
1198 int sync_disable_reasons;
1199 // The disable reason(s) that should be set on the installed extension.
1200 // This will usually be the same as |sync_disable_reasons|, but see the
1201 // "Legacy" case.
1202 int expect_disable_reasons;
1203 // Whether the extension's permissions should be auto-granted during
1204 // installation.
1205 bool expect_permissions_granted;
1206 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361207 // Standard case: Extension comes in enabled; permissions should be
1208 // granted
1209 // during installation.
1210 {"Standard", true, 0, 0, true},
1211 // If the extension comes in disabled, its permissions should still be
1212 // granted (the user already approved them on another machine).
1213 {"Disabled", false, extensions::disable_reason::DISABLE_USER_ACTION,
1214 extensions::disable_reason::DISABLE_USER_ACTION, true},
1215 // Legacy case (<M45): No disable reasons come in from Sync (see
1216 // crbug.com/484214). After installation, the reason should be set to
1217 // DISABLE_USER_ACTION (default assumption).
1218 {"Legacy", false, -1, extensions::disable_reason::DISABLE_USER_ACTION,
1219 true},
1220 // If the extension came in disabled due to a permissions increase, then
1221 // the
1222 // user has *not* approved the permissions, and they shouldn't be granted.
1223 // crbug.com/484214
1224 {"PermissionsIncrease", false,
1225 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
1226 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
treib9afc6212015-10-30 18:49:581227 };
1228
1229 for (const TestCase& test_case : test_cases) {
1230 SCOPED_TRACE(test_case.name);
1231
1232 sync_pb::EntitySpecifics specifics;
1233 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1234 ext_specifics->set_id(good_crx);
1235 ext_specifics->set_version(base::Version("1").GetString());
1236 ext_specifics->set_enabled(test_case.sync_enabled);
1237 if (test_case.sync_disable_reasons != -1)
1238 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1239
treib65f103042015-12-03 10:21:361240 SyncChangeList list =
1241 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1242
treib9afc6212015-10-30 18:49:581243 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1244
1245 ASSERT_TRUE(service()->pending_extension_manager()->IsIdPending(good_crx));
1246 UpdateExtension(good_crx, path, test_case.sync_enabled ? ENABLED
1247 : DISABLED);
1248 EXPECT_EQ(test_case.expect_disable_reasons,
1249 prefs->GetDisableReasons(good_crx));
dchengc963c7142016-04-08 03:55:221250 std::unique_ptr<const PermissionSet> permissions =
treib9afc6212015-10-30 18:49:581251 prefs->GetGrantedPermissions(good_crx);
1252 EXPECT_EQ(test_case.expect_permissions_granted, !permissions->IsEmpty());
1253 ASSERT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
Devlin Cronin7b193412017-12-14 03:46:031254 if (test_case.sync_enabled)
1255 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
1256 else
1257 EXPECT_TRUE(registry()->disabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581258
1259 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031260 UninstallExtension(good_crx);
treib9afc6212015-10-30 18:49:581261 }
1262}
1263
1264TEST_F(ExtensionServiceSyncTest, ProcessSyncDataTerminatedExtension) {
1265 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581266 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361267 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111268 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1269 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581270
1271 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1272 TerminateExtension(good_crx);
1273 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1274 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1275
1276 sync_pb::EntitySpecifics specifics;
1277 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1278 ext_specifics->set_id(good_crx);
1279 ext_specifics->set_version(
David Bertoni9f897c92019-09-20 17:46:351280 registry()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581281 ext_specifics->set_enabled(false);
1282 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361283
1284 SyncChangeList list =
1285 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581286
1287 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1288 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1289 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1290
1291 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1292}
1293
1294TEST_F(ExtensionServiceSyncTest, ProcessSyncDataVersionCheck) {
1295 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581296 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361297 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111298 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1299 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581300
1301 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1302 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1303 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1304
1305 sync_pb::EntitySpecifics specifics;
1306 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1307 ext_specifics->set_id(good_crx);
1308 ext_specifics->set_enabled(true);
1309
1310 const base::Version installed_version =
David Bertoni9f897c92019-09-20 17:46:351311 registry()->GetInstalledExtension(good_crx)->version();
treib9afc6212015-10-30 18:49:581312
1313 {
1314 ext_specifics->set_version(installed_version.GetString());
treib65f103042015-12-03 10:21:361315
1316 SyncChangeList list =
1317 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581318
1319 // Should do nothing if extension version == sync version.
1320 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1321 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1322 // Make sure the version we'll send back to sync didn't change.
1323 syncer::SyncDataList data =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:161324 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581325 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221326 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581327 ExtensionSyncData::CreateFromSyncData(data[0]);
1328 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001329 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581330 }
1331
1332 // Should do nothing if extension version > sync version.
1333 {
1334 ext_specifics->set_version("0.0.0.0");
treib65f103042015-12-03 10:21:361335
1336 SyncChangeList list =
1337 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581338
1339 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1340 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1341 // Make sure the version we'll send back to sync didn't change.
1342 syncer::SyncDataList data =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:161343 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581344 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221345 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581346 ExtensionSyncData::CreateFromSyncData(data[0]);
1347 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001348 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581349 }
1350
1351 // Should kick off an update if extension version < sync version.
1352 {
1353 const base::Version new_version("9.9.9.9");
1354 ext_specifics->set_version(new_version.GetString());
treib65f103042015-12-03 10:21:361355
1356 SyncChangeList list =
1357 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581358
1359 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1360 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1361 // Make sure that we'll send the NEW version back to sync, even though we
1362 // haven't actually updated yet. This is to prevent the data in sync from
1363 // flip-flopping back and forth until all clients are up to date.
1364 syncer::SyncDataList data =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:161365 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581366 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221367 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581368 ExtensionSyncData::CreateFromSyncData(data[0]);
1369 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001370 EXPECT_EQ(new_version, extension_data->version());
treib9afc6212015-10-30 18:49:581371 }
1372
1373 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1374}
1375
1376TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNotInstalled) {
1377 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581378 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361379 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111380 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1381 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581382
1383 sync_pb::EntitySpecifics specifics;
1384 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1385 ext_specifics->set_id(good_crx);
1386 ext_specifics->set_enabled(false);
1387 ext_specifics->set_incognito_enabled(true);
1388 ext_specifics->set_update_url("http://www.google.com/");
1389 ext_specifics->set_version("1.2.3.4");
treib65f103042015-12-03 10:21:361390
1391 SyncChangeList list =
1392 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581393
1394 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1395 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1396 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1397 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1398 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1399 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1400
1401 const extensions::PendingExtensionInfo* info;
1402 EXPECT_TRUE(
1403 (info = service()->pending_extension_manager()->GetById(good_crx)));
1404 EXPECT_EQ(ext_specifics->update_url(), info->update_url().spec());
1405 EXPECT_TRUE(info->is_from_sync());
1406 EXPECT_EQ(Manifest::INTERNAL, info->install_source());
1407 // TODO(akalin): Figure out a way to test |info.ShouldAllowInstall()|.
1408}
1409
1410TEST_F(ExtensionServiceSyncTest, ProcessSyncDataEnableDisable) {
1411 InitializeEmptyExtensionService();
1412 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361413 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111414 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1415 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581416
1417 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1418
1419 struct TestCase {
1420 const char* name; // For failure output only.
1421 // Set of disable reasons before any Sync data comes in. If this is != 0,
1422 // the extension is disabled.
1423 int previous_disable_reasons;
1424 bool sync_enable; // The enabled flag coming in from Sync.
1425 // The disable reason(s) coming in from Sync, or -1 for "not set".
1426 int sync_disable_reasons;
1427 // The expected set of disable reasons after processing the Sync update. The
1428 // extension should be disabled iff this is != 0.
1429 int expect_disable_reasons;
1430 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361431 {"NopEnable", 0, true, 0, 0},
1432 {"NopDisable", extensions::disable_reason::DISABLE_USER_ACTION, false,
1433 extensions::disable_reason::DISABLE_USER_ACTION,
1434 extensions::disable_reason::DISABLE_USER_ACTION},
1435 {"Enable", extensions::disable_reason::DISABLE_USER_ACTION, true, 0, 0},
1436 {"Disable", 0, false, extensions::disable_reason::DISABLE_USER_ACTION,
1437 extensions::disable_reason::DISABLE_USER_ACTION},
1438 {"AddDisableReason", extensions::disable_reason::DISABLE_REMOTE_INSTALL,
1439 false,
1440 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1441 extensions::disable_reason::DISABLE_USER_ACTION,
1442 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1443 extensions::disable_reason::DISABLE_USER_ACTION},
1444 {"RemoveDisableReason",
1445 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1446 extensions::disable_reason::DISABLE_USER_ACTION,
1447 false, extensions::disable_reason::DISABLE_USER_ACTION,
1448 extensions::disable_reason::DISABLE_USER_ACTION},
1449 {"PreserveLocalDisableReason", extensions::disable_reason::DISABLE_RELOAD,
1450 true, 0, extensions::disable_reason::DISABLE_RELOAD},
1451 {"PreserveOnlyLocalDisableReason",
1452 extensions::disable_reason::DISABLE_USER_ACTION |
1453 extensions::disable_reason::DISABLE_RELOAD,
1454 true, 0, extensions::disable_reason::DISABLE_RELOAD},
treib29e1b9b12015-11-11 08:50:561455
Minh X. Nguyen45479012017-08-18 21:35:361456 // Interaction with Chrome clients <=M44, which don't sync disable_reasons
1457 // at all (any existing reasons are preserved).
1458 {"M44Enable", extensions::disable_reason::DISABLE_USER_ACTION, true, -1,
1459 0},
1460 // An M44 client enables an extension that had been disabled on a new
1461 // client. The disable reasons are still be there, but should be ignored.
1462 {"M44ReEnable", extensions::disable_reason::DISABLE_USER_ACTION, true,
1463 extensions::disable_reason::DISABLE_USER_ACTION, 0},
1464 {"M44Disable", 0, false, -1,
1465 extensions::disable_reason::DISABLE_USER_ACTION},
1466 {"M44ReDisable", 0, false, 0,
1467 extensions::disable_reason::DISABLE_USER_ACTION},
1468 {"M44AlreadyDisabledByUser",
1469 extensions::disable_reason::DISABLE_USER_ACTION, false, -1,
1470 extensions::disable_reason::DISABLE_USER_ACTION},
1471 {"M44AlreadyDisabledWithOtherReason",
1472 extensions::disable_reason::DISABLE_REMOTE_INSTALL, false, -1,
1473 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1474 extensions::disable_reason::DISABLE_USER_ACTION},
treib9afc6212015-10-30 18:49:581475 };
1476
1477 for (const TestCase& test_case : test_cases) {
1478 SCOPED_TRACE(test_case.name);
1479
1480 std::string id;
1481 std::string version;
1482 // Don't keep |extension| around longer than necessary.
1483 {
1484 const Extension* extension =
1485 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1486 // The extension should now be installed and enabled.
1487 ASSERT_TRUE(extension);
1488 id = extension->id();
1489 version = extension->VersionString();
1490 }
1491 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1492
1493 // Disable it if the test case says so.
1494 if (test_case.previous_disable_reasons) {
1495 service()->DisableExtension(id, test_case.previous_disable_reasons);
1496 ASSERT_TRUE(registry()->disabled_extensions().Contains(id));
1497 }
1498
1499 // Now a sync update comes in.
1500 sync_pb::EntitySpecifics specifics;
1501 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1502 ext_specifics->set_id(id);
1503 ext_specifics->set_enabled(test_case.sync_enable);
1504 ext_specifics->set_version(version);
1505 if (test_case.sync_disable_reasons != -1)
1506 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1507
treib65f103042015-12-03 10:21:361508 SyncChangeList list =
1509 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1510
treib9afc6212015-10-30 18:49:581511 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1512
1513 // Check expectations.
1514 const bool expect_enabled = !test_case.expect_disable_reasons;
1515 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1516 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
1517
1518 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031519 UninstallExtension(id);
treib9afc6212015-10-30 18:49:581520 }
1521}
1522
Konstantin Ganenkoae1129c2017-09-15 16:28:591523class ExtensionServiceSyncCustomGalleryTest : public ExtensionServiceSyncTest {
1524 public:
1525 void SetUp() override {
1526 ExtensionServiceSyncTest::SetUp();
rdevlin.cronin2f1ed4c2017-06-13 16:22:131527
Konstantin Ganenkoae1129c2017-09-15 16:28:591528 // This is the update URL specified in the permissions test extension.
1529 // Setting it here is necessary to make the extension considered syncable.
1530 extension_test_util::SetGalleryUpdateURL(
1531 GURL("http://localhost/autoupdate/updates.xml"));
1532 }
1533};
1534
1535TEST_F(ExtensionServiceSyncCustomGalleryTest, ProcessSyncDataDeferredEnable) {
treib9afc6212015-10-30 18:49:581536 InitializeEmptyExtensionService();
1537 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361538 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111539 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1540 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581541
1542 base::FilePath base_path = data_dir().AppendASCII("permissions_increase");
1543 base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1544
1545 base::FilePath path = base_path.AppendASCII("v1");
1546 const Extension* extension = PackAndInstallCRX(path, pem_path, INSTALL_NEW);
1547 // The extension must now be installed and enabled.
1548 ASSERT_TRUE(extension);
1549 ASSERT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
1550
1551 // Save the id, as the extension object will be destroyed during updating.
1552 std::string id = extension->id();
1553
1554 // Update to a new version with increased permissions.
1555 path = base_path.AppendASCII("v2");
1556 PackCRXAndUpdateExtension(id, path, pem_path, DISABLED);
1557
1558 // Now a sync update comes in, telling us to re-enable a *newer* version.
1559 sync_pb::EntitySpecifics specifics;
1560 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1561 ext_specifics->set_id(id);
1562 ext_specifics->set_version("3");
1563 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:361564 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:581565
treib65f103042015-12-03 10:21:361566 SyncChangeList list =
1567 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1568
treib9afc6212015-10-30 18:49:581569 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1570
1571 // Since the version didn't match, the extension should still be disabled.
1572 EXPECT_TRUE(registry()->disabled_extensions().Contains(id));
1573
1574 // After we update to the matching version, the extension should get enabled.
1575 path = base_path.AppendASCII("v3");
1576 PackCRXAndUpdateExtension(id, path, pem_path, ENABLED);
1577}
1578
atuchin2eb18eb2017-03-02 07:22:151579TEST_F(ExtensionServiceSyncCustomGalleryTest,
1580 ProcessSyncDataPermissionApproval) {
treib9afc6212015-10-30 18:49:581581 InitializeEmptyExtensionService();
1582 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361583 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111584 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1585 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581586
1587 const base::FilePath base_path =
1588 data_dir().AppendASCII("permissions_increase");
1589 const base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1590 const base::FilePath path_v1 = base_path.AppendASCII("v1");
1591 const base::FilePath path_v2 = base_path.AppendASCII("v2");
1592
1593 base::ScopedTempDir crx_dir;
1594 ASSERT_TRUE(crx_dir.CreateUniqueTempDir());
vabr9142fe22016-09-08 13:19:221595 const base::FilePath crx_path_v1 = crx_dir.GetPath().AppendASCII("temp1.crx");
treib9afc6212015-10-30 18:49:581596 PackCRX(path_v1, pem_path, crx_path_v1);
vabr9142fe22016-09-08 13:19:221597 const base::FilePath crx_path_v2 = crx_dir.GetPath().AppendASCII("temp2.crx");
treib9afc6212015-10-30 18:49:581598 PackCRX(path_v2, pem_path, crx_path_v2);
1599
1600 const std::string v1("1");
1601 const std::string v2("2");
1602
1603 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1604
1605 struct TestCase {
1606 const char* name; // For failure output only.
1607 const std::string& sync_version; // The version coming in from Sync.
1608 // The disable reason(s) coming in from Sync, or -1 for "not set".
1609 int sync_disable_reasons;
1610 // The expected set of disable reasons after processing the Sync update. The
1611 // extension should be enabled iff this is 0.
1612 int expect_disable_reasons;
1613 // Whether the extension's permissions should be auto-granted.
1614 bool expect_permissions_granted;
1615 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361616 // Sync tells us to re-enable an older version. No permissions should be
1617 // granted, since we can't be sure if the user actually approved the right
1618 // set of permissions.
1619 {"OldVersion", v1, 0,
1620 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
1621 // Legacy case: Sync tells us to re-enable the extension, but doesn't
1622 // specify disable reasons. No permissions should be granted.
1623 {"Legacy", v2, -1,
1624 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
1625 // Sync tells us to re-enable the extension and explicitly removes the
1626 // disable reasons. Now the extension should have its permissions granted.
1627 {"GrantPermissions", v2, 0, extensions::disable_reason::DISABLE_NONE,
1628 true},
treib9afc6212015-10-30 18:49:581629 };
1630
1631 for (const TestCase& test_case : test_cases) {
1632 SCOPED_TRACE(test_case.name);
1633
1634 std::string id;
1635 // Don't keep |extension| around longer than necessary (it'll be destroyed
1636 // during updating).
1637 {
1638 const Extension* extension = InstallCRX(crx_path_v1, INSTALL_NEW);
1639 // The extension should now be installed and enabled.
1640 ASSERT_TRUE(extension);
1641 ASSERT_EQ(v1, extension->VersionString());
1642 id = extension->id();
1643 }
1644 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1645
dchengc963c7142016-04-08 03:55:221646 std::unique_ptr<const PermissionSet> granted_permissions_v1 =
treib9afc6212015-10-30 18:49:581647 prefs->GetGrantedPermissions(id);
1648
1649 // Update to a new version with increased permissions.
1650 UpdateExtension(id, crx_path_v2, DISABLED);
1651
1652 // Now the extension should be disabled due to a permissions increase.
1653 {
1654 const Extension* extension =
1655 registry()->disabled_extensions().GetByID(id);
1656 ASSERT_TRUE(extension);
1657 ASSERT_EQ(v2, extension->VersionString());
1658 }
1659 ASSERT_TRUE(prefs->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:361660 id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE));
treib9afc6212015-10-30 18:49:581661
1662 // No new permissions should have been granted.
dchengc963c7142016-04-08 03:55:221663 std::unique_ptr<const PermissionSet> granted_permissions_v2 =
treib9afc6212015-10-30 18:49:581664 prefs->GetGrantedPermissions(id);
1665 ASSERT_EQ(*granted_permissions_v1, *granted_permissions_v2);
1666
1667 // Now a sync update comes in.
1668 sync_pb::EntitySpecifics specifics;
1669 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1670 ext_specifics->set_id(id);
1671 ext_specifics->set_enabled(true);
1672 ext_specifics->set_version(test_case.sync_version);
1673 if (test_case.sync_disable_reasons != -1)
1674 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1675
treib65f103042015-12-03 10:21:361676 SyncChangeList list =
1677 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1678
treib9afc6212015-10-30 18:49:581679 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1680
1681 // Check expectations.
1682 const bool expect_enabled = !test_case.expect_disable_reasons;
1683 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1684 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
dchengc963c7142016-04-08 03:55:221685 std::unique_ptr<const PermissionSet> granted_permissions =
treib9afc6212015-10-30 18:49:581686 prefs->GetGrantedPermissions(id);
1687 if (test_case.expect_permissions_granted) {
dchengc963c7142016-04-08 03:55:221688 std::unique_ptr<const PermissionSet> active_permissions =
treib9afc6212015-10-30 18:49:581689 prefs->GetActivePermissions(id);
1690 EXPECT_EQ(*granted_permissions, *active_permissions);
1691 } else {
1692 EXPECT_EQ(*granted_permissions, *granted_permissions_v1);
1693 }
1694
1695 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031696 UninstallExtension(id);
treib9afc6212015-10-30 18:49:581697 }
1698}
1699
treib227b2582015-12-09 09:28:261700// Regression test for crbug.com/558299
1701TEST_F(ExtensionServiceSyncTest, DontSyncThemes) {
1702 InitializeEmptyExtensionService();
1703
1704 // The user has enabled sync.
Marc Treib9948a682018-11-20 08:01:371705 ProfileSyncServiceFactory::GetForProfile(profile())
1706 ->GetUserSettings()
Tanmoy Mollik0960d702019-09-11 15:14:471707 ->SetFirstSetupComplete(kSetSourceFromTest);
treib227b2582015-12-09 09:28:261708 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
1709 extension_sync_service();
1710
1711 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:021712 ASSERT_TRUE(extension_system()->is_ready());
treib227b2582015-12-09 09:28:261713
1714 syncer::FakeSyncChangeProcessor* processor =
1715 new syncer::FakeSyncChangeProcessor;
1716 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:221717 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
1718 base::WrapUnique(new syncer::SyncErrorFactoryMock));
treib227b2582015-12-09 09:28:261719
1720 processor->changes().clear();
1721
1722 // Sanity check: Installing an extension should result in a sync change.
1723 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1724 EXPECT_EQ(1u, processor->changes().size());
1725
1726 processor->changes().clear();
1727
1728 // Installing a theme should not result in a sync change (themes are handled
1729 // separately by ThemeSyncableService).
1730 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
Evan Stade46d716d2017-06-02 20:50:091731 content::WindowedNotificationObserver theme_change_observer(
1732 chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
1733 content::Source<ThemeService>(
1734 ThemeServiceFactory::GetForProfile(profile())));
1735 theme_change_observer.Wait();
treib227b2582015-12-09 09:28:261736 EXPECT_TRUE(processor->changes().empty());
1737}
1738
Toby Huang63a8d712019-11-27 20:07:321739// Tests sync behavior in the case of an item that starts out as an app and gets
1740// updated to become an extension.
asargente48ab752016-03-12 00:59:201741TEST_F(ExtensionServiceSyncTest, AppToExtension) {
1742 InitializeEmptyExtensionService();
1743 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:021744 ASSERT_TRUE(extension_system()->is_ready());
asargente48ab752016-03-12 00:59:201745
1746 // Install v1, which is an app.
1747 const Extension* v1 =
1748 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v1.crx"),
1749 INSTALL_NEW);
1750 EXPECT_TRUE(v1->is_app());
1751 EXPECT_FALSE(v1->is_extension());
1752 std::string id = v1->id();
1753
1754 StatefulChangeProcessor extensions_processor(syncer::ModelType::EXTENSIONS);
1755 StatefulChangeProcessor apps_processor(syncer::ModelType::APPS);
1756 extension_sync_service()->MergeDataAndStartSyncing(
1757 syncer::EXTENSIONS, syncer::SyncDataList(),
1758 extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221759 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201760 extension_sync_service()->MergeDataAndStartSyncing(
1761 syncer::APPS, syncer::SyncDataList(), apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221762 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201763
1764 // Check the app/extension change processors to be sure the right data was
1765 // added.
1766 EXPECT_TRUE(extensions_processor.changes().empty());
1767 EXPECT_TRUE(extensions_processor.data().empty());
1768 EXPECT_EQ(1u, apps_processor.data().size());
1769 ASSERT_EQ(1u, apps_processor.changes().size());
1770 const SyncChange& app_change = apps_processor.changes()[0];
1771 EXPECT_EQ(SyncChange::ACTION_ADD, app_change.change_type());
dchengc963c7142016-04-08 03:55:221772 std::unique_ptr<ExtensionSyncData> app_data =
asargente48ab752016-03-12 00:59:201773 ExtensionSyncData::CreateFromSyncData(app_change.sync_data());
1774 EXPECT_TRUE(app_data->is_app());
1775 EXPECT_EQ(id, app_data->id());
Devlin Cronin03bf2d22017-12-20 08:21:051776 EXPECT_EQ(v1->version(), app_data->version());
asargente48ab752016-03-12 00:59:201777
1778 // Update the app to v2, which is an extension.
1779 const Extension* v2 =
1780 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v2.crx"),
1781 INSTALL_UPDATED);
1782 EXPECT_FALSE(v2->is_app());
1783 EXPECT_TRUE(v2->is_extension());
1784 EXPECT_EQ(id, v2->id());
1785
1786 // Make sure we saw an extension item added.
1787 ASSERT_EQ(1u, extensions_processor.changes().size());
1788 const SyncChange& extension_change = extensions_processor.changes()[0];
1789 EXPECT_EQ(SyncChange::ACTION_ADD, extension_change.change_type());
dchengc963c7142016-04-08 03:55:221790 std::unique_ptr<ExtensionSyncData> extension_data =
asargente48ab752016-03-12 00:59:201791 ExtensionSyncData::CreateFromSyncData(extension_change.sync_data());
1792 EXPECT_FALSE(extension_data->is_app());
1793 EXPECT_EQ(id, extension_data->id());
Devlin Cronin03bf2d22017-12-20 08:21:051794 EXPECT_EQ(v2->version(), extension_data->version());
asargente48ab752016-03-12 00:59:201795
1796 // Get the current data from the change processors to use as the input to
1797 // the following call to MergeDataAndStartSyncing. This simulates what should
1798 // happen with sync.
1799 syncer::SyncDataList extensions_data =
1800 extensions_processor.GetAllSyncData(syncer::EXTENSIONS);
1801 syncer::SyncDataList apps_data = apps_processor.GetAllSyncData(syncer::APPS);
1802
1803 // Stop syncing, then start again.
1804 extension_sync_service()->StopSyncing(syncer::EXTENSIONS);
1805 extension_sync_service()->StopSyncing(syncer::APPS);
1806 extension_sync_service()->MergeDataAndStartSyncing(
1807 syncer::EXTENSIONS, extensions_data, extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221808 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201809 extension_sync_service()->MergeDataAndStartSyncing(
1810 syncer::APPS, apps_data, apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221811 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201812
1813 // Make sure we saw an app item deleted.
1814 bool found_delete = false;
1815 for (const auto& change : apps_processor.changes()) {
1816 if (change.change_type() == SyncChange::ACTION_DELETE) {
dchengc963c7142016-04-08 03:55:221817 std::unique_ptr<ExtensionSyncData> data =
asargente48ab752016-03-12 00:59:201818 ExtensionSyncData::CreateFromSyncChange(change);
1819 if (data->id() == id) {
1820 found_delete = true;
1821 break;
1822 }
1823 }
1824 }
1825 EXPECT_TRUE(found_delete);
1826
1827 // Make sure there is one extension, and there are no more apps.
1828 EXPECT_EQ(1u, extensions_processor.data().size());
1829 EXPECT_TRUE(apps_processor.data().empty());
1830}
proberge901ecab2017-08-31 19:24:281831
[email protected]950f2952020-07-10 03:35:501832class BlocklistedExtensionSyncServiceTest : public ExtensionServiceSyncTest {
proberge901ecab2017-08-31 19:24:281833 public:
[email protected]950f2952020-07-10 03:35:501834 BlocklistedExtensionSyncServiceTest() {}
proberge901ecab2017-08-31 19:24:281835
1836 void SetUp() override {
1837 ExtensionServiceSyncTest::SetUp();
1838
1839 InitializeEmptyExtensionService();
1840
1841 // Enable sync.
Marc Treib5a78e9c2019-02-19 16:47:011842 syncer::SyncService* sync_service =
proberge901ecab2017-08-31 19:24:281843 ProfileSyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:471844 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
proberge901ecab2017-08-31 19:24:281845
[email protected]950f2952020-07-10 03:35:501846 test_blocklist_.Attach(service()->blocklist_);
proberge901ecab2017-08-31 19:24:281847 service()->Init();
1848
1849 // Load up a simple extension.
1850 extensions::ChromeTestExtensionLoader extension_loader(profile());
1851 extension_loader.set_pack_extension(true);
1852 extension_ = extension_loader.LoadExtension(
1853 data_dir().AppendASCII("simple_with_file"));
1854 ASSERT_TRUE(extension_);
1855 extension_id_ = extension_->id();
1856 ASSERT_TRUE(registry()->enabled_extensions().GetByID(extension_id_));
1857
1858 {
Jinho Bangb5216cec2018-01-17 19:43:111859 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
proberge901ecab2017-08-31 19:24:281860 processor_raw_ = processor.get();
1861 extension_sync_service()->MergeDataAndStartSyncing(
1862 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:111863 std::make_unique<syncer::SyncErrorFactoryMock>());
proberge901ecab2017-08-31 19:24:281864 }
1865 processor_raw_->changes().clear();
1866 }
1867
[email protected]950f2952020-07-10 03:35:501868 void ForceBlocklistUpdate() {
1869 service()->OnBlocklistUpdated();
Gabriel Charette01507a22017-09-27 21:30:081870 content::RunAllTasksUntilIdle();
proberge901ecab2017-08-31 19:24:281871 }
1872
1873 syncer::FakeSyncChangeProcessor* processor() { return processor_raw_; }
1874
1875 const Extension* extension() { return extension_.get(); }
1876
1877 std::string& extension_id() { return extension_id_; }
1878
[email protected]950f2952020-07-10 03:35:501879 extensions::TestBlocklist& test_blocklist() { return test_blocklist_; }
proberge901ecab2017-08-31 19:24:281880
1881 private:
1882 syncer::FakeSyncChangeProcessor* processor_raw_;
1883 scoped_refptr<const Extension> extension_;
1884 std::string extension_id_;
[email protected]950f2952020-07-10 03:35:501885 extensions::TestBlocklist test_blocklist_;
proberge901ecab2017-08-31 19:24:281886
[email protected]950f2952020-07-10 03:35:501887 DISALLOW_COPY_AND_ASSIGN(BlocklistedExtensionSyncServiceTest);
proberge901ecab2017-08-31 19:24:281888};
1889
[email protected]950f2952020-07-10 03:35:501890// Test that sync cannot enable blocklisted extensions.
1891TEST_F(BlocklistedExtensionSyncServiceTest, SyncBlocklistedExtension) {
proberge901ecab2017-08-31 19:24:281892 std::string& extension_id = this->extension_id();
1893
[email protected]950f2952020-07-10 03:35:501894 // Blocklist the extension.
1895 test_blocklist().SetBlocklistState(extension_id,
[email protected]321b9292020-06-26 01:20:461896 extensions::BLOCKLISTED_MALWARE, true);
[email protected]950f2952020-07-10 03:35:501897 ForceBlocklistUpdate();
proberge901ecab2017-08-31 19:24:281898
1899 // Try enabling the extension via sync.
1900 EnableExtensionFromSync(*extension());
1901
1902 // The extension should not be enabled.
1903 EXPECT_FALSE(registry()->enabled_extensions().GetByID(extension_id));
1904 EXPECT_TRUE(processor()->changes().empty());
1905}
1906
1907// Test that some greylisted extensions can be enabled through sync.
[email protected]950f2952020-07-10 03:35:501908TEST_F(BlocklistedExtensionSyncServiceTest, SyncAllowedGreylistedExtension) {
proberge901ecab2017-08-31 19:24:281909 std::string& extension_id = this->extension_id();
1910
1911 // Greylist the extension.
[email protected]950f2952020-07-10 03:35:501912 test_blocklist().SetBlocklistState(
[email protected]321b9292020-06-26 01:20:461913 extension_id, extensions::BLOCKLISTED_POTENTIALLY_UNWANTED, true);
[email protected]950f2952020-07-10 03:35:501914 ForceBlocklistUpdate();
proberge901ecab2017-08-31 19:24:281915
1916 EXPECT_FALSE(registry()->enabled_extensions().GetByID(extension_id));
1917 {
1918 ASSERT_EQ(1u, processor()->changes().size());
1919 const SyncChange& change = processor()->changes()[0];
1920 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
1921 std::unique_ptr<ExtensionSyncData> data =
1922 ExtensionSyncData::CreateFromSyncData(change.sync_data());
1923 EXPECT_EQ(extension_id, data->id());
1924 EXPECT_EQ(extensions::disable_reason::DISABLE_GREYLIST,
1925 data->disable_reasons());
1926 EXPECT_FALSE(data->enabled());
1927 }
1928 processor()->changes().clear();
1929
1930 // Manually re-enabling the extension should work.
1931 service()->EnableExtension(extension_id);
1932 EXPECT_TRUE(registry()->enabled_extensions().GetByID(extension_id));
1933 {
1934 ASSERT_EQ(1u, processor()->changes().size());
1935 const SyncChange& change = processor()->changes()[0];
1936 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
1937 std::unique_ptr<ExtensionSyncData> data =
1938 ExtensionSyncData::CreateFromSyncData(change.sync_data());
1939 EXPECT_EQ(extension_id, data->id());
1940 EXPECT_EQ(0, data->disable_reasons());
1941 EXPECT_TRUE(data->enabled());
1942 }
1943 processor()->changes().clear();
1944}