blob: bff5a5ad70196e31caee7a638071d9121fa87f1b [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"
rdevlin.cronin2f1ed4c2017-06-13 16:22:1318#include "chrome/browser/extensions/chrome_test_extension_loader.h"
treib9afc6212015-10-30 18:49:5819#include "chrome/browser/extensions/component_loader.h"
20#include "chrome/browser/extensions/extension_service.h"
21#include "chrome/browser/extensions/extension_service_test_with_install.h"
22#include "chrome/browser/extensions/extension_sync_data.h"
23#include "chrome/browser/extensions/extension_sync_service.h"
24#include "chrome/browser/extensions/extension_util.h"
[email protected]b55906912020-07-07 10:39:4025#include "chrome/browser/extensions/test_blocklist.h"
treib9afc6212015-10-30 18:49:5826#include "chrome/browser/extensions/updater/extension_updater.h"
Hans Wennborg9208992ba2019-10-14 14:02:4927#include "chrome/browser/profiles/profile_key.h"
treib9afc6212015-10-30 18:49:5828#include "chrome/browser/sync/profile_sync_service_factory.h"
Tommy Steimel2dffd3c2021-03-10 23:27:2129#include "chrome/browser/themes/test/theme_service_changed_waiter.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"
Gyuyoung Kim5626c752021-03-18 22:58:1157#include "extensions/common/mojom/manifest.mojom-shared.h"
treib9afc6212015-10-30 18:49:5858#include "extensions/common/permissions/permission_set.h"
treib9afc6212015-10-30 18:49:5859
treib9afc6212015-10-30 18:49:5860using extensions::AppSorting;
61using extensions::Extension;
62using extensions::ExtensionPrefs;
David Bertoni58c113a2019-08-02 19:53:2663using extensions::ExtensionRegistry;
treib9afc6212015-10-30 18:49:5864using extensions::ExtensionSyncData;
65using extensions::ExtensionSystem;
66using extensions::Manifest;
67using extensions::PermissionSet;
Gyuyoung Kim5626c752021-03-18 22:58:1168using extensions::mojom::ManifestLocation;
treib65f103042015-12-03 10:21:3669using syncer::SyncChange;
70using syncer::SyncChangeList;
mamire9609642016-06-28 22:17:5471using testing::Mock;
treib65f103042015-12-03 10:21:3672
73namespace {
treib9afc6212015-10-30 18:49:5874
75const char good0[] = "behllobkkfkfnphdnhnkndlbkcpglgmj";
76const char good2[] = "bjafgdebaacbbbecmhlhpofkepfkgcpa";
77const char good_crx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
78const char page_action[] = "obcimlgaoabeegjmmpldobjndiealpln";
Joshua Pawlickif2f37f32018-11-05 21:40:5679const char theme2_crx[] = "ibcijncamhmjjdodjamgiipcgnnaeagd";
Tanmoy Mollik0960d702019-09-11 15:14:4780const syncer::SyncFirstSetupCompleteSource kSetSourceFromTest =
81 syncer::SyncFirstSetupCompleteSource::BASIC_FLOW;
treib9afc6212015-10-30 18:49:5882
rdevlin.cronin2f1ed4c2017-06-13 16:22:1383ExtensionSyncData GetDisableSyncData(const Extension& extension,
84 int disable_reasons) {
85 bool enabled = false;
86 bool incognito_enabled = false;
87 bool remote_install = false;
rdevlin.cronin2f1ed4c2017-06-13 16:22:1388 return ExtensionSyncData(extension, enabled, disable_reasons,
Swapnilf6f2f1d2021-01-14 18:50:4389 incognito_enabled, remote_install, GURL());
rdevlin.cronin2f1ed4c2017-06-13 16:22:1390}
91
92ExtensionSyncData GetEnableSyncData(const Extension& extension) {
93 bool enabled = true;
94 bool incognito_enabled = false;
95 bool remote_install = false;
Toby Huangd7caf252019-10-30 01:11:1696 return ExtensionSyncData(extension, enabled,
97 extensions::disable_reason::DISABLE_NONE,
Swapnilf6f2f1d2021-01-14 18:50:4398 incognito_enabled, remote_install, GURL());
rdevlin.cronin2f1ed4c2017-06-13 16:22:1399}
100
treib65f103042015-12-03 10:21:36101SyncChangeList MakeSyncChangeList(const std::string& id,
102 const sync_pb::EntitySpecifics& specifics,
103 SyncChange::SyncChangeType change_type) {
104 syncer::SyncData sync_data =
105 syncer::SyncData::CreateLocalData(id, "Name", specifics);
106 return SyncChangeList(1, SyncChange(FROM_HERE, change_type, sync_data));
107}
108
asargente48ab752016-03-12 00:59:20109// This is a FakeSyncChangeProcessor specialization that maintains a store of
110// SyncData items in the superclass' data_ member variable, treating it like a
111// map keyed by the extension id from the SyncData. Each instance of this class
112// should only be used for one model type (which should be either extensions or
113// apps) to match how the real sync system handles things.
114class StatefulChangeProcessor : public syncer::FakeSyncChangeProcessor {
115 public:
116 explicit StatefulChangeProcessor(syncer::ModelType expected_type)
117 : expected_type_(expected_type) {
118 EXPECT_TRUE(expected_type == syncer::ModelType::EXTENSIONS ||
119 expected_type == syncer::ModelType::APPS);
120 }
121
122 ~StatefulChangeProcessor() override {}
123
124 // We let our parent class, FakeSyncChangeProcessor, handle saving the
125 // changes for us, but in addition we "apply" these changes by treating
126 // the FakeSyncChangeProcessor's SyncDataList as a map keyed by extension
127 // id.
Victor Hugo Vianna Silvad591a082020-04-16 10:56:36128 base::Optional<syncer::ModelError> ProcessSyncChanges(
Brett Wilsone1a70422017-09-12 05:10:09129 const base::Location& from_here,
asargente48ab752016-03-12 00:59:20130 const syncer::SyncChangeList& change_list) override {
131 syncer::FakeSyncChangeProcessor::ProcessSyncChanges(from_here, change_list);
132 for (const auto& change : change_list) {
133 syncer::SyncData sync_data = change.sync_data();
134 EXPECT_EQ(expected_type_, sync_data.GetDataType());
135
dchengc963c7142016-04-08 03:55:22136 std::unique_ptr<ExtensionSyncData> modified =
asargente48ab752016-03-12 00:59:20137 ExtensionSyncData::CreateFromSyncData(sync_data);
138
139 // Start by removing any existing entry for this extension id.
140 syncer::SyncDataList& data_list = data();
141 for (auto iter = data_list.begin(); iter != data_list.end(); ++iter) {
dchengc963c7142016-04-08 03:55:22142 std::unique_ptr<ExtensionSyncData> existing =
asargente48ab752016-03-12 00:59:20143 ExtensionSyncData::CreateFromSyncData(*iter);
144 if (existing->id() == modified->id()) {
145 data_list.erase(iter);
146 break;
147 }
148 }
149
150 // Now add in the new data for this id, if appropriate.
151 if (change.change_type() == SyncChange::ACTION_ADD ||
152 change.change_type() == SyncChange::ACTION_UPDATE) {
153 data_list.push_back(sync_data);
154 } else if (change.change_type() != SyncChange::ACTION_DELETE) {
155 ADD_FAILURE() << "Unexpected change type " << change.change_type();
156 }
157 }
Victor Hugo Vianna Silvad591a082020-04-16 10:56:36158 return base::nullopt;
asargente48ab752016-03-12 00:59:20159 }
160
161 // We override this to help catch the error of trying to use a single
162 // StatefulChangeProcessor to process changes for both extensions and apps
163 // sync data.
164 syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override {
165 EXPECT_EQ(expected_type_, type);
166 return FakeSyncChangeProcessor::GetAllSyncData(type);
167 }
168
169 // This is a helper to vend a wrapped version of this object suitable for
170 // passing in to MergeDataAndStartSyncing, which takes a
dchengc963c7142016-04-08 03:55:22171 // std::unique_ptr<SyncChangeProcessor>, since in tests we typically don't
172 // want to
asargente48ab752016-03-12 00:59:20173 // give up ownership of a local change processor.
dchengc963c7142016-04-08 03:55:22174 std::unique_ptr<syncer::SyncChangeProcessor> GetWrapped() {
Jinho Bangb5216cec2018-01-17 19:43:11175 return std::make_unique<syncer::SyncChangeProcessorWrapperForTest>(this);
asargente48ab752016-03-12 00:59:20176 }
177
178 protected:
179 // The expected ModelType of changes that this processor will see.
180 syncer::ModelType expected_type_;
181
182 DISALLOW_COPY_AND_ASSIGN(StatefulChangeProcessor);
183};
184
treib65f103042015-12-03 10:21:36185} // namespace
186
treib9afc6212015-10-30 18:49:58187class ExtensionServiceSyncTest
188 : public extensions::ExtensionServiceTestWithInstall {
189 public:
190 void MockSyncStartFlare(bool* was_called,
191 syncer::ModelType* model_type_passed_in,
192 syncer::ModelType model_type) {
193 *was_called = true;
194 *model_type_passed_in = model_type;
195 }
196
asargente48ab752016-03-12 00:59:20197 // Helper to call MergeDataAndStartSyncing with no server data and dummy
198 // change processor / error factory.
199 void StartSyncing(syncer::ModelType type) {
200 ASSERT_TRUE(type == syncer::EXTENSIONS || type == syncer::APPS);
201 extension_sync_service()->MergeDataAndStartSyncing(
202 type, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11203 std::make_unique<syncer::FakeSyncChangeProcessor>(),
204 std::make_unique<syncer::SyncErrorFactoryMock>());
asargente48ab752016-03-12 00:59:20205 }
206
rdevlin.cronin2f1ed4c2017-06-13 16:22:13207 void DisableExtensionFromSync(const Extension& extension,
208 int disable_reasons) {
Minh X. Nguyen45479012017-08-18 21:35:36209 ExtensionSyncData disable_extension = GetDisableSyncData(
210 extension, extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13211 SyncChangeList list(
212 1, disable_extension.GetSyncChange(SyncChange::ACTION_UPDATE));
213 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
214 }
215
216 void EnableExtensionFromSync(const Extension& extension) {
217 ExtensionSyncData enable_extension = GetEnableSyncData(extension);
218 SyncChangeList list(
219 1, enable_extension.GetSyncChange(SyncChange::ACTION_UPDATE));
220 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
221 }
222
treib9afc6212015-10-30 18:49:58223 protected:
224 // Paths to some of the fake extensions.
225 base::FilePath good0_path() {
226 return data_dir()
227 .AppendASCII("good")
228 .AppendASCII("Extensions")
229 .AppendASCII(good0)
230 .AppendASCII("1.0.0.0");
231 }
232
233 ExtensionSyncService* extension_sync_service() {
234 return ExtensionSyncService::Get(profile());
235 }
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02236
237 ExtensionSystem* extension_system() {
238 return ExtensionSystem::Get(profile());
239 }
treib9afc6212015-10-30 18:49:58240};
241
242TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledComponent) {
243 InitializeEmptyExtensionService();
244
245 bool flare_was_called = false;
246 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
247 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
Victor Hugo Vianna Silva75334d92020-11-10 07:42:44248 extension_sync_service()->SetSyncStartFlareForTesting(base::BindRepeating(
249 &ExtensionServiceSyncTest::MockSyncStartFlare, factory.GetWeakPtr(),
250 &flare_was_called, // Safe due to WeakPtrFactory scope.
251 &triggered_type)); // Safe due to WeakPtrFactory scope.
treib9afc6212015-10-30 18:49:58252
253 // Install a component extension.
254 std::string manifest;
255 ASSERT_TRUE(base::ReadFileToString(
256 good0_path().Append(extensions::kManifestFilename), &manifest));
257 service()->component_loader()->Add(manifest, good0_path());
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02258 ASSERT_FALSE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58259 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02260 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58261
262 // Extensions added before service is_ready() don't trigger sync startup.
263 EXPECT_FALSE(flare_was_called);
264 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
265}
266
267TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledNormal) {
268 InitializeGoodInstalledExtensionService();
269
270 bool flare_was_called = false;
271 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
272 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
Victor Hugo Vianna Silva75334d92020-11-10 07:42:44273 extension_sync_service()->SetSyncStartFlareForTesting(base::BindRepeating(
274 &ExtensionServiceSyncTest::MockSyncStartFlare, factory.GetWeakPtr(),
275 &flare_was_called, // Safe due to WeakPtrFactory scope.
276 &triggered_type)); // Safe due to WeakPtrFactory scope.
treib9afc6212015-10-30 18:49:58277
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02278 ASSERT_FALSE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58279 service()->Init();
280 ASSERT_EQ(3u, loaded_.size());
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02281 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58282
283 // Extensions added before service is_ready() don't trigger sync startup.
284 EXPECT_FALSE(flare_was_called);
285 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
286}
287
288TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupOnInstall) {
289 InitializeEmptyExtensionService();
290 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02291 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58292
293 bool flare_was_called = false;
294 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
295 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
Victor Hugo Vianna Silva75334d92020-11-10 07:42:44296 extension_sync_service()->SetSyncStartFlareForTesting(base::BindRepeating(
297 &ExtensionServiceSyncTest::MockSyncStartFlare, factory.GetWeakPtr(),
298 &flare_was_called, // Safe due to WeakPtrFactory scope.
299 &triggered_type)); // Safe due to WeakPtrFactory scope.
treib9afc6212015-10-30 18:49:58300
301 base::FilePath path = data_dir().AppendASCII("good.crx");
302 InstallCRX(path, INSTALL_NEW);
303
304 EXPECT_TRUE(flare_was_called);
305 EXPECT_EQ(syncer::EXTENSIONS, triggered_type);
306
307 // Reset.
308 flare_was_called = false;
309 triggered_type = syncer::UNSPECIFIED;
310
311 // Once sync starts, flare should no longer be invoked.
312 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36313 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11314 std::make_unique<syncer::FakeSyncChangeProcessor>(),
315 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58316 path = data_dir().AppendASCII("page_action.crx");
317 InstallCRX(path, INSTALL_NEW);
318 EXPECT_FALSE(flare_was_called);
319 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
320}
321
322TEST_F(ExtensionServiceSyncTest, DisableExtensionFromSync) {
323 // Start the extensions service with one external extension already installed.
324 base::FilePath source_install_dir =
325 data_dir().AppendASCII("good").AppendASCII("Extensions");
326 base::FilePath pref_path =
327 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
328
329 InitializeInstalledExtensionService(pref_path, source_install_dir);
330
331 // The user has enabled sync.
Marc Treib5a78e9c2019-02-19 16:47:01332 syncer::SyncService* sync_service =
treib9afc6212015-10-30 18:49:58333 ProfileSyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:47334 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
treib9afc6212015-10-30 18:49:58335
336 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02337 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58338
339 ASSERT_EQ(3u, loaded_.size());
340
341 // We start enabled.
David Bertonia0b34722019-09-30 20:51:26342 const Extension* extension = registry()->enabled_extensions().GetByID(good0);
treib9afc6212015-10-30 18:49:58343 ASSERT_TRUE(extension);
344 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
345
346 // Sync starts up.
347 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36348 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11349 std::make_unique<syncer::FakeSyncChangeProcessor>(),
350 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58351
352 // Then sync data arrives telling us to disable |good0|.
Minh X. Nguyen45479012017-08-18 21:35:36353 ExtensionSyncData disable_good_crx(
354 *extension, false, extensions::disable_reason::DISABLE_USER_ACTION, false,
Swapnilf6f2f1d2021-01-14 18:50:43355 false, extension_urls::GetWebstoreUpdateUrl());
treib65f103042015-12-03 10:21:36356 SyncChangeList list(
357 1, disable_good_crx.GetSyncChange(SyncChange::ACTION_UPDATE));
treib9afc6212015-10-30 18:49:58358 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
359
360 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
361}
362
rdevlin.cronin2f1ed4c2017-06-13 16:22:13363// Test that sync can enable and disable installed extensions.
364TEST_F(ExtensionServiceSyncTest, ReenableDisabledExtensionFromSync) {
365 InitializeEmptyExtensionService();
366
367 // Enable sync.
Marc Treib5a78e9c2019-02-19 16:47:01368 syncer::SyncService* sync_service =
rdevlin.cronin2f1ed4c2017-06-13 16:22:13369 ProfileSyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:47370 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13371
372 service()->Init();
373
374 // Load up a simple extension.
375 extensions::ChromeTestExtensionLoader extension_loader(profile());
376 extension_loader.set_pack_extension(true);
377 scoped_refptr<const Extension> extension = extension_loader.LoadExtension(
378 data_dir().AppendASCII("simple_with_file"));
379 ASSERT_TRUE(extension);
380 const std::string kExtensionId = extension->id();
381 ASSERT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
382
383 syncer::FakeSyncChangeProcessor* processor_raw = nullptr;
384 {
Jinho Bangb5216cec2018-01-17 19:43:11385 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
rdevlin.cronin2f1ed4c2017-06-13 16:22:13386 processor_raw = processor.get();
387 extension_sync_service()->MergeDataAndStartSyncing(
388 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:11389 std::make_unique<syncer::SyncErrorFactoryMock>());
rdevlin.cronin2f1ed4c2017-06-13 16:22:13390 }
391 processor_raw->changes().clear();
392
Minh X. Nguyen45479012017-08-18 21:35:36393 DisableExtensionFromSync(*extension,
394 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13395
396 // The extension should be disabled.
397 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
Minh X. Nguyen45479012017-08-18 21:35:36398 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
rdevlin.cronin2f1ed4c2017-06-13 16:22:13399 ExtensionPrefs::Get(profile())->GetDisableReasons(kExtensionId));
400 EXPECT_TRUE(processor_raw->changes().empty());
401
402 // Enable the extension. Sync should push the new state.
403 service()->EnableExtension(kExtensionId);
404 {
405 ASSERT_EQ(1u, processor_raw->changes().size());
406 const SyncChange& change = processor_raw->changes()[0];
407 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
408 std::unique_ptr<ExtensionSyncData> data =
409 ExtensionSyncData::CreateFromSyncData(change.sync_data());
410 EXPECT_EQ(kExtensionId, data->id());
411 EXPECT_EQ(0, data->disable_reasons());
412 EXPECT_TRUE(data->enabled());
413 }
414
415 // Disable the extension again. Sync should push the new state.
416 processor_raw->changes().clear();
Minh X. Nguyen45479012017-08-18 21:35:36417 service()->DisableExtension(kExtensionId,
418 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13419 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
420 {
421 ASSERT_EQ(1u, processor_raw->changes().size());
422 const SyncChange& change = processor_raw->changes()[0];
423 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
424 std::unique_ptr<ExtensionSyncData> data =
425 ExtensionSyncData::CreateFromSyncData(change.sync_data());
426 EXPECT_EQ(kExtensionId, data->id());
Minh X. Nguyen45479012017-08-18 21:35:36427 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
428 data->disable_reasons());
rdevlin.cronin2f1ed4c2017-06-13 16:22:13429 EXPECT_FALSE(data->enabled());
430 }
431 processor_raw->changes().clear();
432
433 // Enable the extension via sync.
434 EnableExtensionFromSync(*extension);
435
436 // The extension should be enabled.
437 EXPECT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
438 EXPECT_TRUE(processor_raw->changes().empty());
439}
440
441// Tests that default-installed extensions won't be affected by incoming sync
442// data. (It's feasible to have a sync entry for an extension that could be
443// default installed, since one installation may be default-installed while
444// another may not be).
445TEST_F(ExtensionServiceSyncTest,
446 DefaultInstalledExtensionsAreNotReenabledOrDisabledBySync) {
447 InitializeEmptyExtensionService();
448
449 // Enable sync.
Marc Treib5a78e9c2019-02-19 16:47:01450 syncer::SyncService* sync_service =
rdevlin.cronin2f1ed4c2017-06-13 16:22:13451 ProfileSyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:47452 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13453
454 service()->Init();
455
456 // Load up an extension that's considered default installed.
457 extensions::ChromeTestExtensionLoader extension_loader(profile());
458 extension_loader.set_pack_extension(true);
459 extension_loader.add_creation_flag(Extension::WAS_INSTALLED_BY_DEFAULT);
460 scoped_refptr<const Extension> extension = extension_loader.LoadExtension(
461 data_dir().AppendASCII("simple_with_file"));
462 ASSERT_TRUE(extension);
463
464 // The extension shouldn't sync.
465 EXPECT_FALSE(extensions::util::ShouldSync(extension.get(), profile()));
466 const std::string kExtensionId = extension->id();
467 ASSERT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
468
469 syncer::FakeSyncChangeProcessor* processor_raw = nullptr;
470 {
Jinho Bangb5216cec2018-01-17 19:43:11471 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
rdevlin.cronin2f1ed4c2017-06-13 16:22:13472 processor_raw = processor.get();
473 extension_sync_service()->MergeDataAndStartSyncing(
474 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:11475 std::make_unique<syncer::SyncErrorFactoryMock>());
rdevlin.cronin2f1ed4c2017-06-13 16:22:13476 }
477 processor_raw->changes().clear();
478
479 // Sync state says the extension is disabled (e.g. on another machine).
Minh X. Nguyen45479012017-08-18 21:35:36480 DisableExtensionFromSync(*extension,
481 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13482
483 // The extension should still be enabled, since it's default-installed.
484 EXPECT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
485 EXPECT_TRUE(processor_raw->changes().empty());
486
487 // Now disable the extension locally. Sync should *not* push new state.
Minh X. Nguyen45479012017-08-18 21:35:36488 service()->DisableExtension(kExtensionId,
489 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13490 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
491 EXPECT_TRUE(processor_raw->changes().empty());
492
493 // Sync state says the extension is enabled.
494 EnableExtensionFromSync(*extension);
495
496 // As above, the extension should not have been affected by sync.
497 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
498 EXPECT_TRUE(processor_raw->changes().empty());
499
500 // And re-enabling the extension should not push new state to sync.
501 service()->EnableExtension(kExtensionId);
502 EXPECT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
503 EXPECT_TRUE(processor_raw->changes().empty());
504}
505
treib9afc6212015-10-30 18:49:58506TEST_F(ExtensionServiceSyncTest, IgnoreSyncChangesWhenLocalStateIsMoreRecent) {
507 // Start the extension service with three extensions already installed.
508 base::FilePath source_install_dir =
509 data_dir().AppendASCII("good").AppendASCII("Extensions");
510 base::FilePath pref_path =
511 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
512
513 InitializeInstalledExtensionService(pref_path, source_install_dir);
514
515 // The user has enabled sync.
Marc Treib5a78e9c2019-02-19 16:47:01516 syncer::SyncService* sync_service =
treib9afc6212015-10-30 18:49:58517 ProfileSyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:47518 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
treib9afc6212015-10-30 18:49:58519 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
520 extension_sync_service();
521
522 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02523 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58524 ASSERT_EQ(3u, loaded_.size());
525
526 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
527 ASSERT_TRUE(service()->IsExtensionEnabled(good2));
528
529 // Disable and re-enable good0 before first sync data arrives.
Minh X. Nguyen45479012017-08-18 21:35:36530 service()->DisableExtension(good0,
531 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:58532 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
533 service()->EnableExtension(good0);
534 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
535 // Disable good2 before first sync data arrives (good1 is considered
536 // non-syncable because it has plugin permission).
Minh X. Nguyen45479012017-08-18 21:35:36537 service()->DisableExtension(good2,
538 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:58539 ASSERT_FALSE(service()->IsExtensionEnabled(good2));
540
David Bertonia0b34722019-09-30 20:51:26541 const Extension* extension0 = registry()->enabled_extensions().GetByID(good0);
David Bertoni58c113a2019-08-02 19:53:26542 const Extension* extension2 =
David Bertonia0b34722019-09-30 20:51:26543 registry()->disabled_extensions().GetByID(good2);
treib9afc6212015-10-30 18:49:58544 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension0));
545 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension2));
546
547 // Now sync data comes in that says to disable good0 and enable good2.
Minh X. Nguyen45479012017-08-18 21:35:36548 ExtensionSyncData disable_good0(
549 *extension0, false, extensions::disable_reason::DISABLE_USER_ACTION,
Swapnilf6f2f1d2021-01-14 18:50:43550 false, false, extension_urls::GetWebstoreUpdateUrl());
551 ExtensionSyncData enable_good2(
552 *extension2, true, extensions::disable_reason::DISABLE_NONE, false, false,
553 extension_urls::GetWebstoreUpdateUrl());
treib9afc6212015-10-30 18:49:58554 syncer::SyncDataList sync_data;
555 sync_data.push_back(disable_good0.GetSyncData());
556 sync_data.push_back(enable_good2.GetSyncData());
557 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:22558 syncer::EXTENSIONS, sync_data,
Jinho Bangb5216cec2018-01-17 19:43:11559 std::make_unique<syncer::FakeSyncChangeProcessor>(),
560 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58561
562 // Both sync changes should be ignored, since the local state was changed
563 // before sync started, and so the local state is considered more recent.
564 EXPECT_TRUE(service()->IsExtensionEnabled(good0));
565 EXPECT_FALSE(service()->IsExtensionEnabled(good2));
566}
567
treibb794dd52015-12-01 18:47:14568TEST_F(ExtensionServiceSyncTest, DontSelfNotify) {
569 // Start the extension service with three extensions already installed.
570 base::FilePath source_install_dir =
571 data_dir().AppendASCII("good").AppendASCII("Extensions");
572 base::FilePath pref_path =
573 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
574
575 InitializeInstalledExtensionService(pref_path, source_install_dir);
576
577 // The user has enabled sync.
Marc Treib9948a682018-11-20 08:01:37578 ProfileSyncServiceFactory::GetForProfile(profile())
579 ->GetUserSettings()
Tanmoy Mollik0960d702019-09-11 15:14:47580 ->SetFirstSetupComplete(kSetSourceFromTest);
treibb794dd52015-12-01 18:47:14581 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
582 extension_sync_service();
583
584 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02585 ASSERT_TRUE(extension_system()->is_ready());
treibb794dd52015-12-01 18:47:14586 ASSERT_EQ(3u, loaded_.size());
587 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
588
589 syncer::FakeSyncChangeProcessor* processor =
590 new syncer::FakeSyncChangeProcessor;
591 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:22592 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
Jinho Bangb5216cec2018-01-17 19:43:11593 std::make_unique<syncer::SyncErrorFactoryMock>());
treibb794dd52015-12-01 18:47:14594
595 processor->changes().clear();
596
597 // Simulate various incoming sync changes, and make sure they don't result in
598 // any outgoing changes.
599
600 {
David Bertoni58c113a2019-08-02 19:53:26601 const Extension* extension =
David Bertonia0b34722019-09-30 20:51:26602 registry()->enabled_extensions().GetByID(good0);
treibb794dd52015-12-01 18:47:14603 ASSERT_TRUE(extension);
604
605 // Disable the extension.
Swapnilf6f2f1d2021-01-14 18:50:43606 ExtensionSyncData data(
607 *extension, false, extensions::disable_reason::DISABLE_USER_ACTION,
608 false, false, extension_urls::GetWebstoreUpdateUrl());
treib65f103042015-12-03 10:21:36609 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14610
611 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
612
613 EXPECT_TRUE(processor->changes().empty());
614 }
615
616 {
David Bertoni58c113a2019-08-02 19:53:26617 const Extension* extension =
David Bertonia0b34722019-09-30 20:51:26618 registry()->disabled_extensions().GetByID(good0);
treibb794dd52015-12-01 18:47:14619 ASSERT_TRUE(extension);
620
621 // Set incognito enabled to true.
Minh X. Nguyen45479012017-08-18 21:35:36622 ExtensionSyncData data(*extension, false,
623 extensions::disable_reason::DISABLE_NONE, true,
Swapnilf6f2f1d2021-01-14 18:50:43624 false, extension_urls::GetWebstoreUpdateUrl());
treib65f103042015-12-03 10:21:36625 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14626
627 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
628
629 EXPECT_TRUE(processor->changes().empty());
630 }
631
632 {
David Bertoni58c113a2019-08-02 19:53:26633 const Extension* extension =
David Bertonia0b34722019-09-30 20:51:26634 registry()->disabled_extensions().GetByID(good0);
treibb794dd52015-12-01 18:47:14635 ASSERT_TRUE(extension);
636
637 // Add another disable reason.
Minh X. Nguyen45479012017-08-18 21:35:36638 ExtensionSyncData data(
639 *extension, false,
640 extensions::disable_reason::DISABLE_USER_ACTION |
641 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
Swapnilf6f2f1d2021-01-14 18:50:43642 false, false, extension_urls::GetWebstoreUpdateUrl());
treib65f103042015-12-03 10:21:36643 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14644
645 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
646
647 EXPECT_TRUE(processor->changes().empty());
648 }
649
650 {
David Bertoni58c113a2019-08-02 19:53:26651 const Extension* extension =
David Bertonia0b34722019-09-30 20:51:26652 registry()->disabled_extensions().GetByID(good0);
treibb794dd52015-12-01 18:47:14653 ASSERT_TRUE(extension);
654
655 // Uninstall the extension.
Minh X. Nguyen45479012017-08-18 21:35:36656 ExtensionSyncData data(
657 *extension, false,
658 extensions::disable_reason::DISABLE_USER_ACTION |
659 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
Swapnilf6f2f1d2021-01-14 18:50:43660 false, false, extension_urls::GetWebstoreUpdateUrl());
treib65f103042015-12-03 10:21:36661 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_DELETE));
treibb794dd52015-12-01 18:47:14662
663 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
664
665 EXPECT_TRUE(processor->changes().empty());
666 }
667}
668
treib9afc6212015-10-30 18:49:58669TEST_F(ExtensionServiceSyncTest, GetSyncData) {
670 InitializeEmptyExtensionService();
671 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
David Bertoni9f897c92019-09-20 17:46:35672 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58673 ASSERT_TRUE(extension);
674
675 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36676 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11677 std::make_unique<syncer::FakeSyncChangeProcessor>(),
678 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58679
680 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16681 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58682 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22683 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58684 ExtensionSyncData::CreateFromSyncData(list[0]);
685 ASSERT_TRUE(data.get());
686 EXPECT_EQ(extension->id(), data->id());
687 EXPECT_FALSE(data->uninstalled());
688 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
689 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
690 data->incognito_enabled());
Devlin Cronin03bf2d22017-12-20 08:21:05691 EXPECT_EQ(data->version(), extension->version());
treib9afc6212015-10-30 18:49:58692 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
693 data->update_url());
694 EXPECT_EQ(extension->name(), data->name());
695}
696
treib29e1b9b12015-11-11 08:50:56697TEST_F(ExtensionServiceSyncTest, GetSyncDataDisableReasons) {
698 InitializeEmptyExtensionService();
699 const Extension* extension =
700 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
701 ASSERT_TRUE(extension);
702
treib29e1b9b12015-11-11 08:50:56703 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36704 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11705 std::make_unique<syncer::FakeSyncChangeProcessor>(),
706 std::make_unique<syncer::SyncErrorFactoryMock>());
treib29e1b9b12015-11-11 08:50:56707
708 {
709 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16710 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib29e1b9b12015-11-11 08:50:56711 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22712 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56713 ExtensionSyncData::CreateFromSyncData(list[0]);
714 ASSERT_TRUE(data.get());
715 EXPECT_TRUE(data->enabled());
716 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36717 EXPECT_EQ(extensions::disable_reason::DISABLE_NONE,
718 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56719 }
720
721 // Syncable disable reason, should propagate to sync.
Minh X. Nguyen45479012017-08-18 21:35:36722 service()->DisableExtension(good_crx,
723 extensions::disable_reason::DISABLE_USER_ACTION);
treib29e1b9b12015-11-11 08:50:56724 {
725 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16726 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib29e1b9b12015-11-11 08:50:56727 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22728 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56729 ExtensionSyncData::CreateFromSyncData(list[0]);
730 ASSERT_TRUE(data.get());
731 EXPECT_FALSE(data->enabled());
732 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36733 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
734 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56735 }
736 service()->EnableExtension(good_crx);
737
738 // Non-syncable disable reason. The sync data should still say "enabled".
Minh X. Nguyen45479012017-08-18 21:35:36739 service()->DisableExtension(good_crx,
740 extensions::disable_reason::DISABLE_RELOAD);
treib29e1b9b12015-11-11 08:50:56741 {
742 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16743 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib29e1b9b12015-11-11 08:50:56744 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22745 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56746 ExtensionSyncData::CreateFromSyncData(list[0]);
747 ASSERT_TRUE(data.get());
748 EXPECT_TRUE(data->enabled());
749 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36750 EXPECT_EQ(extensions::disable_reason::DISABLE_NONE,
751 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56752 }
753 service()->EnableExtension(good_crx);
754
755 // Both a syncable and a non-syncable disable reason, only the former should
756 // propagate to sync.
Minh X. Nguyen45479012017-08-18 21:35:36757 service()->DisableExtension(good_crx,
758 extensions::disable_reason::DISABLE_USER_ACTION |
759 extensions::disable_reason::DISABLE_RELOAD);
treib29e1b9b12015-11-11 08:50:56760 {
761 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16762 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib29e1b9b12015-11-11 08:50:56763 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22764 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56765 ExtensionSyncData::CreateFromSyncData(list[0]);
766 ASSERT_TRUE(data.get());
767 EXPECT_FALSE(data->enabled());
768 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36769 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
770 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56771 }
772 service()->EnableExtension(good_crx);
773}
774
treib9afc6212015-10-30 18:49:58775TEST_F(ExtensionServiceSyncTest, GetSyncDataTerminated) {
776 InitializeEmptyExtensionService();
777 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
778 TerminateExtension(good_crx);
David Bertoni9f897c92019-09-20 17:46:35779 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58780 ASSERT_TRUE(extension);
781
treib9afc6212015-10-30 18:49:58782 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36783 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11784 std::make_unique<syncer::FakeSyncChangeProcessor>(),
785 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58786
787 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16788 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58789 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22790 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58791 ExtensionSyncData::CreateFromSyncData(list[0]);
792 ASSERT_TRUE(data.get());
793 EXPECT_EQ(extension->id(), data->id());
794 EXPECT_FALSE(data->uninstalled());
795 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
796 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
797 data->incognito_enabled());
Devlin Cronin03bf2d22017-12-20 08:21:05798 EXPECT_EQ(data->version(), extension->version());
treib9afc6212015-10-30 18:49:58799 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
800 data->update_url());
801 EXPECT_EQ(extension->name(), data->name());
802}
803
804TEST_F(ExtensionServiceSyncTest, GetSyncDataFilter) {
805 InitializeEmptyExtensionService();
806 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
David Bertoni9f897c92019-09-20 17:46:35807 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58808 ASSERT_TRUE(extension);
809
treib9afc6212015-10-30 18:49:58810 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36811 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11812 std::make_unique<syncer::FakeSyncChangeProcessor>(),
813 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58814
815 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16816 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58817 ASSERT_EQ(list.size(), 0U);
818}
819
820TEST_F(ExtensionServiceSyncTest, GetSyncExtensionDataUserSettings) {
821 InitializeEmptyExtensionService();
822 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
David Bertoni9f897c92019-09-20 17:46:35823 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58824 ASSERT_TRUE(extension);
825
treib9afc6212015-10-30 18:49:58826 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36827 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11828 std::make_unique<syncer::FakeSyncChangeProcessor>(),
829 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58830
831 {
832 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16833 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58834 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22835 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58836 ExtensionSyncData::CreateFromSyncData(list[0]);
837 ASSERT_TRUE(data.get());
838 EXPECT_TRUE(data->enabled());
839 EXPECT_FALSE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58840 }
841
Minh X. Nguyen45479012017-08-18 21:35:36842 service()->DisableExtension(good_crx,
843 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:58844 {
845 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16846 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58847 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22848 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58849 ExtensionSyncData::CreateFromSyncData(list[0]);
850 ASSERT_TRUE(data.get());
851 EXPECT_FALSE(data->enabled());
852 EXPECT_FALSE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58853 }
854
855 extensions::util::SetIsIncognitoEnabled(good_crx, profile(), true);
treib9afc6212015-10-30 18:49:58856 {
857 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16858 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58859 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22860 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58861 ExtensionSyncData::CreateFromSyncData(list[0]);
862 ASSERT_TRUE(data.get());
863 EXPECT_FALSE(data->enabled());
864 EXPECT_TRUE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58865 }
866
867 service()->EnableExtension(good_crx);
treib9afc6212015-10-30 18:49:58868 {
869 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16870 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58871 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22872 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58873 ExtensionSyncData::CreateFromSyncData(list[0]);
874 ASSERT_TRUE(data.get());
875 EXPECT_TRUE(data->enabled());
876 EXPECT_TRUE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58877 }
878}
879
880TEST_F(ExtensionServiceSyncTest, SyncForUninstalledExternalExtension) {
881 InitializeEmptyExtensionService();
Gyuyoung Kim9c82d5bb32021-03-20 01:28:01882 InstallCRX(data_dir().AppendASCII("good.crx"),
883 ManifestLocation::kExternalPref, INSTALL_NEW, Extension::NO_FLAGS);
David Bertoni9f897c92019-09-20 17:46:35884 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58885 ASSERT_TRUE(extension);
886
treib9afc6212015-10-30 18:49:58887 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36888 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11889 std::make_unique<syncer::FakeSyncChangeProcessor>(),
890 std::make_unique<syncer::SyncErrorFactoryMock>());
asargente48ab752016-03-12 00:59:20891 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:58892
Devlin Cronin6fd1cd62017-12-05 19:13:57893 UninstallExtension(good_crx);
treib9afc6212015-10-30 18:49:58894 EXPECT_TRUE(
895 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
896
897 sync_pb::EntitySpecifics specifics;
898 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
899 sync_pb::ExtensionSpecifics* extension_specifics =
900 app_specifics->mutable_extension();
901 extension_specifics->set_id(good_crx);
902 extension_specifics->set_version("1.0");
903 extension_specifics->set_enabled(true);
904
treib65f103042015-12-03 10:21:36905 SyncChangeList list =
906 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:58907
908 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
909 EXPECT_TRUE(
910 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
911}
912
913TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettings) {
914 InitializeEmptyExtensionService();
915 const Extension* app =
916 PackAndInstallCRX(data_dir().AppendASCII("app"), INSTALL_NEW);
917 ASSERT_TRUE(app);
918 ASSERT_TRUE(app->is_app());
919
treib9afc6212015-10-30 18:49:58920 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36921 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11922 std::make_unique<syncer::FakeSyncChangeProcessor>(),
923 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58924
925 syncer::StringOrdinal initial_ordinal =
926 syncer::StringOrdinal::CreateInitialOrdinal();
927 {
928 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16929 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS);
treib9afc6212015-10-30 18:49:58930 ASSERT_EQ(list.size(), 1U);
931
dchengc963c7142016-04-08 03:55:22932 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58933 ExtensionSyncData::CreateFromSyncData(list[0]);
934 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->app_launch_ordinal()));
935 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
936 }
937
deepak.m14ba69e62015-11-17 05:42:12938 AppSorting* sorting = ExtensionSystem::Get(profile())->app_sorting();
treib9afc6212015-10-30 18:49:58939 sorting->SetAppLaunchOrdinal(app->id(), initial_ordinal.CreateAfter());
940 {
941 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16942 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS);
treib9afc6212015-10-30 18:49:58943 ASSERT_EQ(list.size(), 1U);
944
dchengc963c7142016-04-08 03:55:22945 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58946 ExtensionSyncData::CreateFromSyncData(list[0]);
947 ASSERT_TRUE(app_sync_data.get());
948 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
949 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
950 }
951
952 sorting->SetPageOrdinal(app->id(), initial_ordinal.CreateAfter());
953 {
954 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16955 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS);
treib9afc6212015-10-30 18:49:58956 ASSERT_EQ(list.size(), 1U);
957
dchengc963c7142016-04-08 03:55:22958 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58959 ExtensionSyncData::CreateFromSyncData(list[0]);
960 ASSERT_TRUE(app_sync_data.get());
961 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
962 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->page_ordinal()));
963 }
964}
965
966// TODO (rdevlin.cronin): The OnExtensionMoved() method has been removed from
967// ExtensionService, so this test probably needs a new home. Unfortunately, it
968// relies pretty heavily on things like InitializeExtension[Sync]Service() and
969// PackAndInstallCRX(). When we clean up a bit more, this should move out.
970TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettingsOnExtensionMoved) {
971 InitializeEmptyExtensionService();
972 const size_t kAppCount = 3;
973 const Extension* apps[kAppCount];
974 apps[0] = PackAndInstallCRX(data_dir().AppendASCII("app1"), INSTALL_NEW);
975 apps[1] = PackAndInstallCRX(data_dir().AppendASCII("app2"), INSTALL_NEW);
976 apps[2] = PackAndInstallCRX(data_dir().AppendASCII("app4"), INSTALL_NEW);
977 for (size_t i = 0; i < kAppCount; ++i) {
978 ASSERT_TRUE(apps[i]);
979 ASSERT_TRUE(apps[i]->is_app());
980 }
981
treib9afc6212015-10-30 18:49:58982 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36983 syncer::APPS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22984 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
985 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58986
deepak.m14ba69e62015-11-17 05:42:12987 ExtensionSystem::Get(service()->GetBrowserContext())
treib9afc6212015-10-30 18:49:58988 ->app_sorting()
989 ->OnExtensionMoved(apps[0]->id(), apps[1]->id(), apps[2]->id());
990 {
991 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16992 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS);
treib9afc6212015-10-30 18:49:58993 ASSERT_EQ(list.size(), 3U);
994
dchengc963c7142016-04-08 03:55:22995 std::unique_ptr<ExtensionSyncData> data[kAppCount];
treib9afc6212015-10-30 18:49:58996 for (size_t i = 0; i < kAppCount; ++i) {
997 data[i] = ExtensionSyncData::CreateFromSyncData(list[i]);
998 ASSERT_TRUE(data[i].get());
999 }
1000
1001 // The sync data is not always in the same order our apps were installed in,
1002 // so we do that sorting here so we can make sure the values are changed as
1003 // expected.
1004 syncer::StringOrdinal app_launch_ordinals[kAppCount];
1005 for (size_t i = 0; i < kAppCount; ++i) {
1006 for (size_t j = 0; j < kAppCount; ++j) {
1007 if (apps[i]->id() == data[j]->id())
1008 app_launch_ordinals[i] = data[j]->app_launch_ordinal();
1009 }
1010 }
1011
1012 EXPECT_TRUE(app_launch_ordinals[1].LessThan(app_launch_ordinals[0]));
1013 EXPECT_TRUE(app_launch_ordinals[0].LessThan(app_launch_ordinals[2]));
1014 }
1015}
1016
1017TEST_F(ExtensionServiceSyncTest, GetSyncDataList) {
1018 InitializeEmptyExtensionService();
1019 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1020 InstallCRX(data_dir().AppendASCII("page_action.crx"), INSTALL_NEW);
1021 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
1022 InstallCRX(data_dir().AppendASCII("theme2.crx"), INSTALL_NEW);
1023
treib9afc6212015-10-30 18:49:581024 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361025 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111026 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1027 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581028 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361029 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111030 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1031 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581032
Minh X. Nguyen45479012017-08-18 21:35:361033 service()->DisableExtension(page_action,
1034 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:581035 TerminateExtension(theme2_crx);
1036
treib9afc6212015-10-30 18:49:581037 EXPECT_EQ(
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:161038 0u,
1039 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS).size());
1040 EXPECT_EQ(2u, extension_sync_service()
1041 ->GetAllSyncDataForTesting(syncer::EXTENSIONS)
1042 .size());
treib9afc6212015-10-30 18:49:581043}
1044
1045TEST_F(ExtensionServiceSyncTest, ProcessSyncDataUninstall) {
1046 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581047 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361048 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111049 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1050 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581051
1052 sync_pb::EntitySpecifics specifics;
1053 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1054 ext_specifics->set_id(good_crx);
1055 ext_specifics->set_version("1.0");
treib65f103042015-12-03 10:21:361056
1057 SyncChangeList list =
1058 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:581059
1060 // Should do nothing.
1061 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertoni58c113a2019-08-02 19:53:261062 EXPECT_FALSE(
David Bertonia0b34722019-09-30 20:51:261063 registry()->GetExtensionById(good_crx, ExtensionRegistry::EVERYTHING));
treib9afc6212015-10-30 18:49:581064
1065 // Install the extension.
1066 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
1067 InstallCRX(extension_path, INSTALL_NEW);
David Bertonia0b34722019-09-30 20:51:261068 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581069
1070 // Should uninstall the extension.
1071 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertoni58c113a2019-08-02 19:53:261072 EXPECT_FALSE(
David Bertonia0b34722019-09-30 20:51:261073 registry()->GetExtensionById(good_crx, ExtensionRegistry::EVERYTHING));
treib9afc6212015-10-30 18:49:581074
1075 // Should again do nothing.
1076 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertoni58c113a2019-08-02 19:53:261077 EXPECT_FALSE(
David Bertonia0b34722019-09-30 20:51:261078 registry()->GetExtensionById(good_crx, ExtensionRegistry::EVERYTHING));
treib9afc6212015-10-30 18:49:581079}
1080
1081TEST_F(ExtensionServiceSyncTest, ProcessSyncDataWrongType) {
1082 InitializeEmptyExtensionService();
asargente48ab752016-03-12 00:59:201083 StartSyncing(syncer::EXTENSIONS);
1084 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:581085
1086 // Install the extension.
1087 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
1088 InstallCRX(extension_path, INSTALL_NEW);
David Bertonia0b34722019-09-30 20:51:261089 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581090
1091 sync_pb::EntitySpecifics specifics;
1092 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
1093 sync_pb::ExtensionSpecifics* extension_specifics =
1094 app_specifics->mutable_extension();
1095 extension_specifics->set_id(good_crx);
1096 extension_specifics->set_version(
David Bertoni9f897c92019-09-20 17:46:351097 registry()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581098
1099 {
1100 extension_specifics->set_enabled(true);
treib65f103042015-12-03 10:21:361101
1102 SyncChangeList list =
1103 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:581104
1105 // Should do nothing
1106 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertonia0b34722019-09-30 20:51:261107 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581108 }
1109
1110 {
1111 extension_specifics->set_enabled(false);
treib65f103042015-12-03 10:21:361112
1113 SyncChangeList list =
1114 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581115
1116 // Should again do nothing.
1117 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertonia0b34722019-09-30 20:51:261118 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581119 }
1120}
1121
1122TEST_F(ExtensionServiceSyncTest, ProcessSyncDataSettings) {
1123 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581124 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361125 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111126 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1127 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581128
1129 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1130 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1131 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
treib9afc6212015-10-30 18:49:581132
1133 sync_pb::EntitySpecifics specifics;
1134 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1135 ext_specifics->set_id(good_crx);
1136 ext_specifics->set_version(
David Bertoni9f897c92019-09-20 17:46:351137 registry()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581138 ext_specifics->set_enabled(false);
1139
1140 {
treib65f103042015-12-03 10:21:361141 SyncChangeList list =
1142 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1143
treib9afc6212015-10-30 18:49:581144 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1145 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1146 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
treib9afc6212015-10-30 18:49:581147 }
1148
1149 {
1150 ext_specifics->set_enabled(true);
1151 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361152
1153 SyncChangeList list =
1154 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1155
treib9afc6212015-10-30 18:49:581156 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1157 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1158 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1159 }
1160
1161 {
1162 ext_specifics->set_enabled(false);
1163 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361164
1165 SyncChangeList list =
1166 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1167
treib9afc6212015-10-30 18:49:581168 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1169 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1170 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1171 }
1172
1173 {
1174 ext_specifics->set_enabled(true);
treib65f103042015-12-03 10:21:361175
1176 SyncChangeList list =
1177 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1178
treib9afc6212015-10-30 18:49:581179 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1180 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
treib9afc6212015-10-30 18:49:581181 }
1182
1183 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1184}
1185
1186TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNewExtension) {
1187 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581188 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361189 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111190 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1191 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581192
1193 const base::FilePath path = data_dir().AppendASCII("good.crx");
1194 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1195
1196 struct TestCase {
1197 const char* name; // For failure output only.
1198 bool sync_enabled; // The "enabled" flag coming in from Sync.
1199 // The disable reason(s) coming in from Sync, or -1 for "not set".
1200 int sync_disable_reasons;
1201 // The disable reason(s) that should be set on the installed extension.
1202 // This will usually be the same as |sync_disable_reasons|, but see the
1203 // "Legacy" case.
1204 int expect_disable_reasons;
1205 // Whether the extension's permissions should be auto-granted during
1206 // installation.
1207 bool expect_permissions_granted;
1208 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361209 // Standard case: Extension comes in enabled; permissions should be
1210 // granted
1211 // during installation.
1212 {"Standard", true, 0, 0, true},
1213 // If the extension comes in disabled, its permissions should still be
1214 // granted (the user already approved them on another machine).
1215 {"Disabled", false, extensions::disable_reason::DISABLE_USER_ACTION,
1216 extensions::disable_reason::DISABLE_USER_ACTION, true},
1217 // Legacy case (<M45): No disable reasons come in from Sync (see
1218 // crbug.com/484214). After installation, the reason should be set to
1219 // DISABLE_USER_ACTION (default assumption).
1220 {"Legacy", false, -1, extensions::disable_reason::DISABLE_USER_ACTION,
1221 true},
1222 // If the extension came in disabled due to a permissions increase, then
1223 // the
1224 // user has *not* approved the permissions, and they shouldn't be granted.
1225 // crbug.com/484214
1226 {"PermissionsIncrease", false,
1227 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
1228 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
treib9afc6212015-10-30 18:49:581229 };
1230
1231 for (const TestCase& test_case : test_cases) {
1232 SCOPED_TRACE(test_case.name);
1233
1234 sync_pb::EntitySpecifics specifics;
1235 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1236 ext_specifics->set_id(good_crx);
1237 ext_specifics->set_version(base::Version("1").GetString());
1238 ext_specifics->set_enabled(test_case.sync_enabled);
1239 if (test_case.sync_disable_reasons != -1)
1240 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1241
treib65f103042015-12-03 10:21:361242 SyncChangeList list =
1243 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1244
treib9afc6212015-10-30 18:49:581245 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1246
1247 ASSERT_TRUE(service()->pending_extension_manager()->IsIdPending(good_crx));
1248 UpdateExtension(good_crx, path, test_case.sync_enabled ? ENABLED
1249 : DISABLED);
1250 EXPECT_EQ(test_case.expect_disable_reasons,
1251 prefs->GetDisableReasons(good_crx));
dchengc963c7142016-04-08 03:55:221252 std::unique_ptr<const PermissionSet> permissions =
treib9afc6212015-10-30 18:49:581253 prefs->GetGrantedPermissions(good_crx);
1254 EXPECT_EQ(test_case.expect_permissions_granted, !permissions->IsEmpty());
1255 ASSERT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
Devlin Cronin7b193412017-12-14 03:46:031256 if (test_case.sync_enabled)
1257 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
1258 else
1259 EXPECT_TRUE(registry()->disabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581260
1261 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031262 UninstallExtension(good_crx);
treib9afc6212015-10-30 18:49:581263 }
1264}
1265
1266TEST_F(ExtensionServiceSyncTest, ProcessSyncDataTerminatedExtension) {
1267 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581268 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361269 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111270 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1271 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581272
1273 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1274 TerminateExtension(good_crx);
1275 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1276 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1277
1278 sync_pb::EntitySpecifics specifics;
1279 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1280 ext_specifics->set_id(good_crx);
1281 ext_specifics->set_version(
David Bertoni9f897c92019-09-20 17:46:351282 registry()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581283 ext_specifics->set_enabled(false);
1284 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361285
1286 SyncChangeList list =
1287 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581288
1289 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1290 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1291 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1292
1293 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1294}
1295
1296TEST_F(ExtensionServiceSyncTest, ProcessSyncDataVersionCheck) {
1297 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581298 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361299 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111300 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1301 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581302
1303 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1304 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1305 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1306
1307 sync_pb::EntitySpecifics specifics;
1308 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1309 ext_specifics->set_id(good_crx);
1310 ext_specifics->set_enabled(true);
1311
1312 const base::Version installed_version =
David Bertoni9f897c92019-09-20 17:46:351313 registry()->GetInstalledExtension(good_crx)->version();
treib9afc6212015-10-30 18:49:581314
1315 {
1316 ext_specifics->set_version(installed_version.GetString());
treib65f103042015-12-03 10:21:361317
1318 SyncChangeList list =
1319 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581320
1321 // Should do nothing if extension version == sync version.
1322 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1323 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1324 // Make sure the version we'll send back to sync didn't change.
1325 syncer::SyncDataList data =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:161326 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581327 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221328 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581329 ExtensionSyncData::CreateFromSyncData(data[0]);
1330 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001331 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581332 }
1333
1334 // Should do nothing if extension version > sync version.
1335 {
1336 ext_specifics->set_version("0.0.0.0");
treib65f103042015-12-03 10:21:361337
1338 SyncChangeList list =
1339 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581340
1341 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1342 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1343 // Make sure the version we'll send back to sync didn't change.
1344 syncer::SyncDataList data =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:161345 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581346 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221347 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581348 ExtensionSyncData::CreateFromSyncData(data[0]);
1349 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001350 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581351 }
1352
1353 // Should kick off an update if extension version < sync version.
1354 {
1355 const base::Version new_version("9.9.9.9");
1356 ext_specifics->set_version(new_version.GetString());
treib65f103042015-12-03 10:21:361357
1358 SyncChangeList list =
1359 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581360
1361 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1362 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1363 // Make sure that we'll send the NEW version back to sync, even though we
1364 // haven't actually updated yet. This is to prevent the data in sync from
1365 // flip-flopping back and forth until all clients are up to date.
1366 syncer::SyncDataList data =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:161367 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581368 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221369 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581370 ExtensionSyncData::CreateFromSyncData(data[0]);
1371 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001372 EXPECT_EQ(new_version, extension_data->version());
treib9afc6212015-10-30 18:49:581373 }
1374
1375 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1376}
1377
1378TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNotInstalled) {
1379 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581380 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361381 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111382 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1383 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581384
1385 sync_pb::EntitySpecifics specifics;
1386 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1387 ext_specifics->set_id(good_crx);
1388 ext_specifics->set_enabled(false);
1389 ext_specifics->set_incognito_enabled(true);
1390 ext_specifics->set_update_url("http://www.google.com/");
1391 ext_specifics->set_version("1.2.3.4");
treib65f103042015-12-03 10:21:361392
1393 SyncChangeList list =
1394 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581395
1396 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1397 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1398 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1399 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1400 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1401 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1402
1403 const extensions::PendingExtensionInfo* info;
1404 EXPECT_TRUE(
1405 (info = service()->pending_extension_manager()->GetById(good_crx)));
1406 EXPECT_EQ(ext_specifics->update_url(), info->update_url().spec());
1407 EXPECT_TRUE(info->is_from_sync());
Gyuyoung Kim5626c752021-03-18 22:58:111408 EXPECT_EQ(ManifestLocation::kInternal, info->install_source());
treib9afc6212015-10-30 18:49:581409 // TODO(akalin): Figure out a way to test |info.ShouldAllowInstall()|.
1410}
1411
1412TEST_F(ExtensionServiceSyncTest, ProcessSyncDataEnableDisable) {
1413 InitializeEmptyExtensionService();
1414 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361415 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111416 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1417 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581418
1419 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1420
1421 struct TestCase {
1422 const char* name; // For failure output only.
1423 // Set of disable reasons before any Sync data comes in. If this is != 0,
1424 // the extension is disabled.
1425 int previous_disable_reasons;
1426 bool sync_enable; // The enabled flag coming in from Sync.
1427 // The disable reason(s) coming in from Sync, or -1 for "not set".
1428 int sync_disable_reasons;
1429 // The expected set of disable reasons after processing the Sync update. The
1430 // extension should be disabled iff this is != 0.
1431 int expect_disable_reasons;
1432 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361433 {"NopEnable", 0, true, 0, 0},
1434 {"NopDisable", extensions::disable_reason::DISABLE_USER_ACTION, false,
1435 extensions::disable_reason::DISABLE_USER_ACTION,
1436 extensions::disable_reason::DISABLE_USER_ACTION},
1437 {"Enable", extensions::disable_reason::DISABLE_USER_ACTION, true, 0, 0},
1438 {"Disable", 0, false, extensions::disable_reason::DISABLE_USER_ACTION,
1439 extensions::disable_reason::DISABLE_USER_ACTION},
1440 {"AddDisableReason", extensions::disable_reason::DISABLE_REMOTE_INSTALL,
1441 false,
1442 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1443 extensions::disable_reason::DISABLE_USER_ACTION,
1444 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1445 extensions::disable_reason::DISABLE_USER_ACTION},
1446 {"RemoveDisableReason",
1447 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1448 extensions::disable_reason::DISABLE_USER_ACTION,
1449 false, extensions::disable_reason::DISABLE_USER_ACTION,
1450 extensions::disable_reason::DISABLE_USER_ACTION},
1451 {"PreserveLocalDisableReason", extensions::disable_reason::DISABLE_RELOAD,
1452 true, 0, extensions::disable_reason::DISABLE_RELOAD},
1453 {"PreserveOnlyLocalDisableReason",
1454 extensions::disable_reason::DISABLE_USER_ACTION |
1455 extensions::disable_reason::DISABLE_RELOAD,
1456 true, 0, extensions::disable_reason::DISABLE_RELOAD},
treib29e1b9b12015-11-11 08:50:561457
Minh X. Nguyen45479012017-08-18 21:35:361458 // Interaction with Chrome clients <=M44, which don't sync disable_reasons
1459 // at all (any existing reasons are preserved).
1460 {"M44Enable", extensions::disable_reason::DISABLE_USER_ACTION, true, -1,
1461 0},
1462 // An M44 client enables an extension that had been disabled on a new
1463 // client. The disable reasons are still be there, but should be ignored.
1464 {"M44ReEnable", extensions::disable_reason::DISABLE_USER_ACTION, true,
1465 extensions::disable_reason::DISABLE_USER_ACTION, 0},
1466 {"M44Disable", 0, false, -1,
1467 extensions::disable_reason::DISABLE_USER_ACTION},
1468 {"M44ReDisable", 0, false, 0,
1469 extensions::disable_reason::DISABLE_USER_ACTION},
1470 {"M44AlreadyDisabledByUser",
1471 extensions::disable_reason::DISABLE_USER_ACTION, false, -1,
1472 extensions::disable_reason::DISABLE_USER_ACTION},
1473 {"M44AlreadyDisabledWithOtherReason",
1474 extensions::disable_reason::DISABLE_REMOTE_INSTALL, false, -1,
1475 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1476 extensions::disable_reason::DISABLE_USER_ACTION},
treib9afc6212015-10-30 18:49:581477 };
1478
1479 for (const TestCase& test_case : test_cases) {
1480 SCOPED_TRACE(test_case.name);
1481
1482 std::string id;
1483 std::string version;
1484 // Don't keep |extension| around longer than necessary.
1485 {
1486 const Extension* extension =
1487 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1488 // The extension should now be installed and enabled.
1489 ASSERT_TRUE(extension);
1490 id = extension->id();
1491 version = extension->VersionString();
1492 }
1493 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1494
1495 // Disable it if the test case says so.
1496 if (test_case.previous_disable_reasons) {
1497 service()->DisableExtension(id, test_case.previous_disable_reasons);
1498 ASSERT_TRUE(registry()->disabled_extensions().Contains(id));
1499 }
1500
1501 // Now a sync update comes in.
1502 sync_pb::EntitySpecifics specifics;
1503 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1504 ext_specifics->set_id(id);
1505 ext_specifics->set_enabled(test_case.sync_enable);
1506 ext_specifics->set_version(version);
1507 if (test_case.sync_disable_reasons != -1)
1508 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1509
treib65f103042015-12-03 10:21:361510 SyncChangeList list =
1511 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1512
treib9afc6212015-10-30 18:49:581513 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1514
1515 // Check expectations.
1516 const bool expect_enabled = !test_case.expect_disable_reasons;
1517 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1518 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
1519
1520 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031521 UninstallExtension(id);
treib9afc6212015-10-30 18:49:581522 }
1523}
1524
Konstantin Ganenkoae1129c2017-09-15 16:28:591525class ExtensionServiceSyncCustomGalleryTest : public ExtensionServiceSyncTest {
1526 public:
1527 void SetUp() override {
1528 ExtensionServiceSyncTest::SetUp();
rdevlin.cronin2f1ed4c2017-06-13 16:22:131529
Konstantin Ganenkoae1129c2017-09-15 16:28:591530 // This is the update URL specified in the permissions test extension.
1531 // Setting it here is necessary to make the extension considered syncable.
1532 extension_test_util::SetGalleryUpdateURL(
1533 GURL("http://localhost/autoupdate/updates.xml"));
1534 }
1535};
1536
1537TEST_F(ExtensionServiceSyncCustomGalleryTest, ProcessSyncDataDeferredEnable) {
treib9afc6212015-10-30 18:49:581538 InitializeEmptyExtensionService();
1539 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361540 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111541 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1542 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581543
1544 base::FilePath base_path = data_dir().AppendASCII("permissions_increase");
1545 base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1546
1547 base::FilePath path = base_path.AppendASCII("v1");
1548 const Extension* extension = PackAndInstallCRX(path, pem_path, INSTALL_NEW);
1549 // The extension must now be installed and enabled.
1550 ASSERT_TRUE(extension);
1551 ASSERT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
1552
1553 // Save the id, as the extension object will be destroyed during updating.
1554 std::string id = extension->id();
1555
1556 // Update to a new version with increased permissions.
1557 path = base_path.AppendASCII("v2");
1558 PackCRXAndUpdateExtension(id, path, pem_path, DISABLED);
1559
1560 // Now a sync update comes in, telling us to re-enable a *newer* version.
1561 sync_pb::EntitySpecifics specifics;
1562 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1563 ext_specifics->set_id(id);
1564 ext_specifics->set_version("3");
1565 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:361566 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:581567
treib65f103042015-12-03 10:21:361568 SyncChangeList list =
1569 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1570
treib9afc6212015-10-30 18:49:581571 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1572
1573 // Since the version didn't match, the extension should still be disabled.
1574 EXPECT_TRUE(registry()->disabled_extensions().Contains(id));
1575
1576 // After we update to the matching version, the extension should get enabled.
1577 path = base_path.AppendASCII("v3");
1578 PackCRXAndUpdateExtension(id, path, pem_path, ENABLED);
1579}
1580
Xida Chen9dc27b12021-03-18 14:29:281581// Flaky on a few platforms.
atuchin2eb18eb2017-03-02 07:22:151582TEST_F(ExtensionServiceSyncCustomGalleryTest,
Xida Chen9dc27b12021-03-18 14:29:281583 DISABLED_ProcessSyncDataPermissionApproval) {
treib9afc6212015-10-30 18:49:581584 InitializeEmptyExtensionService();
1585 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361586 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111587 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1588 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581589
1590 const base::FilePath base_path =
1591 data_dir().AppendASCII("permissions_increase");
1592 const base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1593 const base::FilePath path_v1 = base_path.AppendASCII("v1");
1594 const base::FilePath path_v2 = base_path.AppendASCII("v2");
1595
1596 base::ScopedTempDir crx_dir;
1597 ASSERT_TRUE(crx_dir.CreateUniqueTempDir());
vabr9142fe22016-09-08 13:19:221598 const base::FilePath crx_path_v1 = crx_dir.GetPath().AppendASCII("temp1.crx");
treib9afc6212015-10-30 18:49:581599 PackCRX(path_v1, pem_path, crx_path_v1);
vabr9142fe22016-09-08 13:19:221600 const base::FilePath crx_path_v2 = crx_dir.GetPath().AppendASCII("temp2.crx");
treib9afc6212015-10-30 18:49:581601 PackCRX(path_v2, pem_path, crx_path_v2);
1602
1603 const std::string v1("1");
1604 const std::string v2("2");
1605
1606 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1607
1608 struct TestCase {
1609 const char* name; // For failure output only.
1610 const std::string& sync_version; // The version coming in from Sync.
1611 // The disable reason(s) coming in from Sync, or -1 for "not set".
1612 int sync_disable_reasons;
1613 // The expected set of disable reasons after processing the Sync update. The
1614 // extension should be enabled iff this is 0.
1615 int expect_disable_reasons;
1616 // Whether the extension's permissions should be auto-granted.
1617 bool expect_permissions_granted;
1618 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361619 // Sync tells us to re-enable an older version. No permissions should be
1620 // granted, since we can't be sure if the user actually approved the right
1621 // set of permissions.
1622 {"OldVersion", v1, 0,
1623 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
1624 // Legacy case: Sync tells us to re-enable the extension, but doesn't
1625 // specify disable reasons. No permissions should be granted.
1626 {"Legacy", v2, -1,
1627 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
1628 // Sync tells us to re-enable the extension and explicitly removes the
1629 // disable reasons. Now the extension should have its permissions granted.
1630 {"GrantPermissions", v2, 0, extensions::disable_reason::DISABLE_NONE,
1631 true},
treib9afc6212015-10-30 18:49:581632 };
1633
1634 for (const TestCase& test_case : test_cases) {
1635 SCOPED_TRACE(test_case.name);
1636
1637 std::string id;
1638 // Don't keep |extension| around longer than necessary (it'll be destroyed
1639 // during updating).
1640 {
1641 const Extension* extension = InstallCRX(crx_path_v1, INSTALL_NEW);
1642 // The extension should now be installed and enabled.
1643 ASSERT_TRUE(extension);
1644 ASSERT_EQ(v1, extension->VersionString());
1645 id = extension->id();
1646 }
1647 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1648
dchengc963c7142016-04-08 03:55:221649 std::unique_ptr<const PermissionSet> granted_permissions_v1 =
treib9afc6212015-10-30 18:49:581650 prefs->GetGrantedPermissions(id);
1651
1652 // Update to a new version with increased permissions.
1653 UpdateExtension(id, crx_path_v2, DISABLED);
1654
1655 // Now the extension should be disabled due to a permissions increase.
1656 {
1657 const Extension* extension =
1658 registry()->disabled_extensions().GetByID(id);
1659 ASSERT_TRUE(extension);
1660 ASSERT_EQ(v2, extension->VersionString());
1661 }
1662 ASSERT_TRUE(prefs->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:361663 id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE));
treib9afc6212015-10-30 18:49:581664
1665 // No new permissions should have been granted.
dchengc963c7142016-04-08 03:55:221666 std::unique_ptr<const PermissionSet> granted_permissions_v2 =
treib9afc6212015-10-30 18:49:581667 prefs->GetGrantedPermissions(id);
1668 ASSERT_EQ(*granted_permissions_v1, *granted_permissions_v2);
1669
1670 // Now a sync update comes in.
1671 sync_pb::EntitySpecifics specifics;
1672 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1673 ext_specifics->set_id(id);
1674 ext_specifics->set_enabled(true);
1675 ext_specifics->set_version(test_case.sync_version);
1676 if (test_case.sync_disable_reasons != -1)
1677 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1678
treib65f103042015-12-03 10:21:361679 SyncChangeList list =
1680 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1681
treib9afc6212015-10-30 18:49:581682 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1683
1684 // Check expectations.
1685 const bool expect_enabled = !test_case.expect_disable_reasons;
1686 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1687 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
dchengc963c7142016-04-08 03:55:221688 std::unique_ptr<const PermissionSet> granted_permissions =
treib9afc6212015-10-30 18:49:581689 prefs->GetGrantedPermissions(id);
1690 if (test_case.expect_permissions_granted) {
dchengc963c7142016-04-08 03:55:221691 std::unique_ptr<const PermissionSet> active_permissions =
treib9afc6212015-10-30 18:49:581692 prefs->GetActivePermissions(id);
1693 EXPECT_EQ(*granted_permissions, *active_permissions);
1694 } else {
1695 EXPECT_EQ(*granted_permissions, *granted_permissions_v1);
1696 }
1697
1698 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031699 UninstallExtension(id);
treib9afc6212015-10-30 18:49:581700 }
1701}
1702
treib227b2582015-12-09 09:28:261703// Regression test for crbug.com/558299
1704TEST_F(ExtensionServiceSyncTest, DontSyncThemes) {
1705 InitializeEmptyExtensionService();
1706
1707 // The user has enabled sync.
Marc Treib9948a682018-11-20 08:01:371708 ProfileSyncServiceFactory::GetForProfile(profile())
1709 ->GetUserSettings()
Tanmoy Mollik0960d702019-09-11 15:14:471710 ->SetFirstSetupComplete(kSetSourceFromTest);
treib227b2582015-12-09 09:28:261711 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
1712 extension_sync_service();
1713
1714 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:021715 ASSERT_TRUE(extension_system()->is_ready());
treib227b2582015-12-09 09:28:261716
1717 syncer::FakeSyncChangeProcessor* processor =
1718 new syncer::FakeSyncChangeProcessor;
1719 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:221720 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
1721 base::WrapUnique(new syncer::SyncErrorFactoryMock));
treib227b2582015-12-09 09:28:261722
1723 processor->changes().clear();
1724
1725 // Sanity check: Installing an extension should result in a sync change.
1726 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1727 EXPECT_EQ(1u, processor->changes().size());
1728
1729 processor->changes().clear();
1730
1731 // Installing a theme should not result in a sync change (themes are handled
1732 // separately by ThemeSyncableService).
Tommy Steimel2dffd3c2021-03-10 23:27:211733 test::ThemeServiceChangedWaiter waiter(
1734 ThemeServiceFactory::GetForProfile(profile()));
treib227b2582015-12-09 09:28:261735 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
Tommy Steimel2dffd3c2021-03-10 23:27:211736 waiter.WaitForThemeChanged();
treib227b2582015-12-09 09:28:261737 EXPECT_TRUE(processor->changes().empty());
1738}
1739
Toby Huang63a8d712019-11-27 20:07:321740// Tests sync behavior in the case of an item that starts out as an app and gets
1741// updated to become an extension.
asargente48ab752016-03-12 00:59:201742TEST_F(ExtensionServiceSyncTest, AppToExtension) {
1743 InitializeEmptyExtensionService();
1744 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:021745 ASSERT_TRUE(extension_system()->is_ready());
asargente48ab752016-03-12 00:59:201746
1747 // Install v1, which is an app.
1748 const Extension* v1 =
1749 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v1.crx"),
1750 INSTALL_NEW);
1751 EXPECT_TRUE(v1->is_app());
1752 EXPECT_FALSE(v1->is_extension());
1753 std::string id = v1->id();
1754
1755 StatefulChangeProcessor extensions_processor(syncer::ModelType::EXTENSIONS);
1756 StatefulChangeProcessor apps_processor(syncer::ModelType::APPS);
1757 extension_sync_service()->MergeDataAndStartSyncing(
1758 syncer::EXTENSIONS, syncer::SyncDataList(),
1759 extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221760 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201761 extension_sync_service()->MergeDataAndStartSyncing(
1762 syncer::APPS, syncer::SyncDataList(), apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221763 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201764
1765 // Check the app/extension change processors to be sure the right data was
1766 // added.
1767 EXPECT_TRUE(extensions_processor.changes().empty());
1768 EXPECT_TRUE(extensions_processor.data().empty());
1769 EXPECT_EQ(1u, apps_processor.data().size());
1770 ASSERT_EQ(1u, apps_processor.changes().size());
1771 const SyncChange& app_change = apps_processor.changes()[0];
1772 EXPECT_EQ(SyncChange::ACTION_ADD, app_change.change_type());
dchengc963c7142016-04-08 03:55:221773 std::unique_ptr<ExtensionSyncData> app_data =
asargente48ab752016-03-12 00:59:201774 ExtensionSyncData::CreateFromSyncData(app_change.sync_data());
1775 EXPECT_TRUE(app_data->is_app());
1776 EXPECT_EQ(id, app_data->id());
Devlin Cronin03bf2d22017-12-20 08:21:051777 EXPECT_EQ(v1->version(), app_data->version());
asargente48ab752016-03-12 00:59:201778
1779 // Update the app to v2, which is an extension.
1780 const Extension* v2 =
1781 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v2.crx"),
1782 INSTALL_UPDATED);
1783 EXPECT_FALSE(v2->is_app());
1784 EXPECT_TRUE(v2->is_extension());
1785 EXPECT_EQ(id, v2->id());
1786
1787 // Make sure we saw an extension item added.
1788 ASSERT_EQ(1u, extensions_processor.changes().size());
1789 const SyncChange& extension_change = extensions_processor.changes()[0];
1790 EXPECT_EQ(SyncChange::ACTION_ADD, extension_change.change_type());
dchengc963c7142016-04-08 03:55:221791 std::unique_ptr<ExtensionSyncData> extension_data =
asargente48ab752016-03-12 00:59:201792 ExtensionSyncData::CreateFromSyncData(extension_change.sync_data());
1793 EXPECT_FALSE(extension_data->is_app());
1794 EXPECT_EQ(id, extension_data->id());
Devlin Cronin03bf2d22017-12-20 08:21:051795 EXPECT_EQ(v2->version(), extension_data->version());
asargente48ab752016-03-12 00:59:201796
1797 // Get the current data from the change processors to use as the input to
1798 // the following call to MergeDataAndStartSyncing. This simulates what should
1799 // happen with sync.
1800 syncer::SyncDataList extensions_data =
1801 extensions_processor.GetAllSyncData(syncer::EXTENSIONS);
1802 syncer::SyncDataList apps_data = apps_processor.GetAllSyncData(syncer::APPS);
1803
1804 // Stop syncing, then start again.
1805 extension_sync_service()->StopSyncing(syncer::EXTENSIONS);
1806 extension_sync_service()->StopSyncing(syncer::APPS);
1807 extension_sync_service()->MergeDataAndStartSyncing(
1808 syncer::EXTENSIONS, extensions_data, extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221809 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201810 extension_sync_service()->MergeDataAndStartSyncing(
1811 syncer::APPS, apps_data, apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221812 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201813
1814 // Make sure we saw an app item deleted.
1815 bool found_delete = false;
1816 for (const auto& change : apps_processor.changes()) {
1817 if (change.change_type() == SyncChange::ACTION_DELETE) {
dchengc963c7142016-04-08 03:55:221818 std::unique_ptr<ExtensionSyncData> data =
asargente48ab752016-03-12 00:59:201819 ExtensionSyncData::CreateFromSyncChange(change);
1820 if (data->id() == id) {
1821 found_delete = true;
1822 break;
1823 }
1824 }
1825 }
1826 EXPECT_TRUE(found_delete);
1827
1828 // Make sure there is one extension, and there are no more apps.
1829 EXPECT_EQ(1u, extensions_processor.data().size());
1830 EXPECT_TRUE(apps_processor.data().empty());
1831}
proberge901ecab2017-08-31 19:24:281832
[email protected]950f2952020-07-10 03:35:501833class BlocklistedExtensionSyncServiceTest : public ExtensionServiceSyncTest {
proberge901ecab2017-08-31 19:24:281834 public:
[email protected]950f2952020-07-10 03:35:501835 BlocklistedExtensionSyncServiceTest() {}
proberge901ecab2017-08-31 19:24:281836
1837 void SetUp() override {
1838 ExtensionServiceSyncTest::SetUp();
1839
1840 InitializeEmptyExtensionService();
1841
1842 // Enable sync.
Marc Treib5a78e9c2019-02-19 16:47:011843 syncer::SyncService* sync_service =
proberge901ecab2017-08-31 19:24:281844 ProfileSyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:471845 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
proberge901ecab2017-08-31 19:24:281846
[email protected]950f2952020-07-10 03:35:501847 test_blocklist_.Attach(service()->blocklist_);
proberge901ecab2017-08-31 19:24:281848 service()->Init();
1849
1850 // Load up a simple extension.
1851 extensions::ChromeTestExtensionLoader extension_loader(profile());
1852 extension_loader.set_pack_extension(true);
1853 extension_ = extension_loader.LoadExtension(
1854 data_dir().AppendASCII("simple_with_file"));
1855 ASSERT_TRUE(extension_);
1856 extension_id_ = extension_->id();
1857 ASSERT_TRUE(registry()->enabled_extensions().GetByID(extension_id_));
1858
1859 {
Jinho Bangb5216cec2018-01-17 19:43:111860 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
proberge901ecab2017-08-31 19:24:281861 processor_raw_ = processor.get();
1862 extension_sync_service()->MergeDataAndStartSyncing(
1863 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:111864 std::make_unique<syncer::SyncErrorFactoryMock>());
proberge901ecab2017-08-31 19:24:281865 }
1866 processor_raw_->changes().clear();
1867 }
1868
[email protected]950f2952020-07-10 03:35:501869 void ForceBlocklistUpdate() {
1870 service()->OnBlocklistUpdated();
Gabriel Charette01507a22017-09-27 21:30:081871 content::RunAllTasksUntilIdle();
proberge901ecab2017-08-31 19:24:281872 }
1873
1874 syncer::FakeSyncChangeProcessor* processor() { return processor_raw_; }
1875
1876 const Extension* extension() { return extension_.get(); }
1877
1878 std::string& extension_id() { return extension_id_; }
1879
[email protected]950f2952020-07-10 03:35:501880 extensions::TestBlocklist& test_blocklist() { return test_blocklist_; }
proberge901ecab2017-08-31 19:24:281881
1882 private:
1883 syncer::FakeSyncChangeProcessor* processor_raw_;
1884 scoped_refptr<const Extension> extension_;
1885 std::string extension_id_;
[email protected]950f2952020-07-10 03:35:501886 extensions::TestBlocklist test_blocklist_;
proberge901ecab2017-08-31 19:24:281887
[email protected]950f2952020-07-10 03:35:501888 DISALLOW_COPY_AND_ASSIGN(BlocklistedExtensionSyncServiceTest);
proberge901ecab2017-08-31 19:24:281889};
1890
[email protected]950f2952020-07-10 03:35:501891// Test that sync cannot enable blocklisted extensions.
1892TEST_F(BlocklistedExtensionSyncServiceTest, SyncBlocklistedExtension) {
proberge901ecab2017-08-31 19:24:281893 std::string& extension_id = this->extension_id();
1894
[email protected]950f2952020-07-10 03:35:501895 // Blocklist the extension.
1896 test_blocklist().SetBlocklistState(extension_id,
[email protected]321b9292020-06-26 01:20:461897 extensions::BLOCKLISTED_MALWARE, true);
[email protected]950f2952020-07-10 03:35:501898 ForceBlocklistUpdate();
proberge901ecab2017-08-31 19:24:281899
1900 // Try enabling the extension via sync.
1901 EnableExtensionFromSync(*extension());
1902
1903 // The extension should not be enabled.
1904 EXPECT_FALSE(registry()->enabled_extensions().GetByID(extension_id));
1905 EXPECT_TRUE(processor()->changes().empty());
1906}
1907
1908// Test that some greylisted extensions can be enabled through sync.
[email protected]950f2952020-07-10 03:35:501909TEST_F(BlocklistedExtensionSyncServiceTest, SyncAllowedGreylistedExtension) {
proberge901ecab2017-08-31 19:24:281910 std::string& extension_id = this->extension_id();
1911
1912 // Greylist the extension.
[email protected]950f2952020-07-10 03:35:501913 test_blocklist().SetBlocklistState(
[email protected]321b9292020-06-26 01:20:461914 extension_id, extensions::BLOCKLISTED_POTENTIALLY_UNWANTED, true);
[email protected]950f2952020-07-10 03:35:501915 ForceBlocklistUpdate();
proberge901ecab2017-08-31 19:24:281916
1917 EXPECT_FALSE(registry()->enabled_extensions().GetByID(extension_id));
1918 {
1919 ASSERT_EQ(1u, processor()->changes().size());
1920 const SyncChange& change = processor()->changes()[0];
1921 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
1922 std::unique_ptr<ExtensionSyncData> data =
1923 ExtensionSyncData::CreateFromSyncData(change.sync_data());
1924 EXPECT_EQ(extension_id, data->id());
1925 EXPECT_EQ(extensions::disable_reason::DISABLE_GREYLIST,
1926 data->disable_reasons());
1927 EXPECT_FALSE(data->enabled());
1928 }
1929 processor()->changes().clear();
1930
1931 // Manually re-enabling the extension should work.
1932 service()->EnableExtension(extension_id);
1933 EXPECT_TRUE(registry()->enabled_extensions().GetByID(extension_id));
1934 {
1935 ASSERT_EQ(1u, processor()->changes().size());
1936 const SyncChange& change = processor()->changes()[0];
1937 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
1938 std::unique_ptr<ExtensionSyncData> data =
1939 ExtensionSyncData::CreateFromSyncData(change.sync_data());
1940 EXPECT_EQ(extension_id, data->id());
1941 EXPECT_EQ(0, data->disable_reasons());
1942 EXPECT_TRUE(data->enabled());
1943 }
1944 processor()->changes().clear();
1945}