blob: 00a2de80669ed978855e5133f1906d1e9d065805 [file] [log] [blame]
treib9afc6212015-10-30 18:49:581// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
avia2f4804a2015-12-24 23:11:135#include <stddef.h>
6
treibb6af28cd2015-12-01 11:19:467#include <map>
dchengc963c7142016-04-08 03:55:228#include <memory>
treib9afc6212015-10-30 18:49:589#include <string>
limasdf3d102542015-12-09 03:58:4510#include <utility>
treib9afc6212015-10-30 18:49:5811
12#include "base/bind.h"
13#include "base/command_line.h"
14#include "base/files/file_util.h"
dchengc963c7142016-04-08 03:55:2215#include "base/memory/ptr_util.h"
treib9afc6212015-10-30 18:49:5816#include "base/memory/weak_ptr.h"
Avi Drissman5f0fb8c2018-12-25 23:20:4917#include "base/stl_util.h"
Evan Stade46d716d2017-06-02 20:50:0918#include "chrome/browser/chrome_notification_types.h"
rdevlin.cronin2f1ed4c2017-06-13 16:22:1319#include "chrome/browser/extensions/chrome_test_extension_loader.h"
treib9afc6212015-10-30 18:49:5820#include "chrome/browser/extensions/component_loader.h"
21#include "chrome/browser/extensions/extension_service.h"
22#include "chrome/browser/extensions/extension_service_test_with_install.h"
23#include "chrome/browser/extensions/extension_sync_data.h"
24#include "chrome/browser/extensions/extension_sync_service.h"
25#include "chrome/browser/extensions/extension_util.h"
[email protected]b55906912020-07-07 10:39:4026#include "chrome/browser/extensions/test_blocklist.h"
treib9afc6212015-10-30 18:49:5827#include "chrome/browser/extensions/updater/extension_updater.h"
Hans Wennborg9208992ba2019-10-14 14:02:4928#include "chrome/browser/profiles/profile_key.h"
treib9afc6212015-10-30 18:49:5829#include "chrome/browser/sync/profile_sync_service_factory.h"
Evan Stade46d716d2017-06-02 20:50:0930#include "chrome/browser/themes/theme_service.h"
31#include "chrome/browser/themes/theme_service_factory.h"
treib9afc6212015-10-30 18:49:5832#include "chrome/common/chrome_constants.h"
Konstantin Ganenkoae1129c2017-09-15 16:28:5933#include "chrome/common/extensions/extension_test_util.h"
treib9afc6212015-10-30 18:49:5834#include "chrome/common/extensions/sync_helper.h"
35#include "chrome/test/base/testing_profile.h"
rdevlin.cronin738501d2015-11-05 21:51:3636#include "components/crx_file/id_util.h"
Marc Treib2435e772019-02-20 12:25:3837#include "components/sync/driver/sync_service.h"
38#include "components/sync/driver/sync_user_settings.h"
skym71603842016-10-10 18:17:3139#include "components/sync/model/sync_data.h"
Marc Treib2435e772019-02-20 12:25:3840#include "components/sync/protocol/sync.pb.h"
Rushan Suleymanov633f4a0a2020-10-23 11:18:4341#include "components/sync/test/model/fake_sync_change_processor.h"
42#include "components/sync/test/model/sync_change_processor_wrapper_for_test.h"
43#include "components/sync/test/model/sync_error_factory_mock.h"
treibb6af28cd2015-12-01 11:19:4644#include "components/variations/variations_associated_data.h"
Kinuko Yasuda6ec805a2019-07-29 06:12:5645#include "content/public/browser/browser_context.h"
46#include "content/public/browser/storage_partition.h"
treib9afc6212015-10-30 18:49:5847#include "extensions/browser/app_sorting.h"
Devlin Croninbffe949eb2018-01-12 03:03:4048#include "extensions/browser/disable_reason.h"
treib9afc6212015-10-30 18:49:5849#include "extensions/browser/extension_prefs.h"
50#include "extensions/browser/extension_registry.h"
51#include "extensions/browser/extension_system.h"
karandeepb810e33402017-04-05 23:41:2252#include "extensions/browser/extension_util.h"
treib9afc6212015-10-30 18:49:5853#include "extensions/browser/management_policy.h"
rdevlin.cronin738501d2015-11-05 21:51:3654#include "extensions/common/extension_builder.h"
treib9afc6212015-10-30 18:49:5855#include "extensions/common/manifest_url_handlers.h"
56#include "extensions/common/permissions/permission_set.h"
treib9afc6212015-10-30 18:49:5857
treib9afc6212015-10-30 18:49:5858using extensions::AppSorting;
59using extensions::Extension;
60using extensions::ExtensionPrefs;
David Bertoni58c113a2019-08-02 19:53:2661using extensions::ExtensionRegistry;
treib9afc6212015-10-30 18:49:5862using extensions::ExtensionSyncData;
63using extensions::ExtensionSystem;
64using extensions::Manifest;
65using extensions::PermissionSet;
treib65f103042015-12-03 10:21:3666using syncer::SyncChange;
67using syncer::SyncChangeList;
mamire9609642016-06-28 22:17:5468using testing::Mock;
treib65f103042015-12-03 10:21:3669
70namespace {
treib9afc6212015-10-30 18:49:5871
72const char good0[] = "behllobkkfkfnphdnhnkndlbkcpglgmj";
73const char good2[] = "bjafgdebaacbbbecmhlhpofkepfkgcpa";
74const char good_crx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
75const char page_action[] = "obcimlgaoabeegjmmpldobjndiealpln";
Joshua Pawlickif2f37f32018-11-05 21:40:5676const char theme2_crx[] = "ibcijncamhmjjdodjamgiipcgnnaeagd";
Tanmoy Mollik0960d702019-09-11 15:14:4777const syncer::SyncFirstSetupCompleteSource kSetSourceFromTest =
78 syncer::SyncFirstSetupCompleteSource::BASIC_FLOW;
treib9afc6212015-10-30 18:49:5879
rdevlin.cronin2f1ed4c2017-06-13 16:22:1380ExtensionSyncData GetDisableSyncData(const Extension& extension,
81 int disable_reasons) {
82 bool enabled = false;
83 bool incognito_enabled = false;
84 bool remote_install = false;
rdevlin.cronin2f1ed4c2017-06-13 16:22:1385 return ExtensionSyncData(extension, enabled, disable_reasons,
Toby Huangd7caf252019-10-30 01:11:1686 incognito_enabled, remote_install);
rdevlin.cronin2f1ed4c2017-06-13 16:22:1387}
88
89ExtensionSyncData GetEnableSyncData(const Extension& extension) {
90 bool enabled = true;
91 bool incognito_enabled = false;
92 bool remote_install = false;
Toby Huangd7caf252019-10-30 01:11:1693 return ExtensionSyncData(extension, enabled,
94 extensions::disable_reason::DISABLE_NONE,
95 incognito_enabled, remote_install);
rdevlin.cronin2f1ed4c2017-06-13 16:22:1396}
97
treib65f103042015-12-03 10:21:3698SyncChangeList MakeSyncChangeList(const std::string& id,
99 const sync_pb::EntitySpecifics& specifics,
100 SyncChange::SyncChangeType change_type) {
101 syncer::SyncData sync_data =
102 syncer::SyncData::CreateLocalData(id, "Name", specifics);
103 return SyncChangeList(1, SyncChange(FROM_HERE, change_type, sync_data));
104}
105
asargente48ab752016-03-12 00:59:20106// This is a FakeSyncChangeProcessor specialization that maintains a store of
107// SyncData items in the superclass' data_ member variable, treating it like a
108// map keyed by the extension id from the SyncData. Each instance of this class
109// should only be used for one model type (which should be either extensions or
110// apps) to match how the real sync system handles things.
111class StatefulChangeProcessor : public syncer::FakeSyncChangeProcessor {
112 public:
113 explicit StatefulChangeProcessor(syncer::ModelType expected_type)
114 : expected_type_(expected_type) {
115 EXPECT_TRUE(expected_type == syncer::ModelType::EXTENSIONS ||
116 expected_type == syncer::ModelType::APPS);
117 }
118
119 ~StatefulChangeProcessor() override {}
120
121 // We let our parent class, FakeSyncChangeProcessor, handle saving the
122 // changes for us, but in addition we "apply" these changes by treating
123 // the FakeSyncChangeProcessor's SyncDataList as a map keyed by extension
124 // id.
Victor Hugo Vianna Silvad591a082020-04-16 10:56:36125 base::Optional<syncer::ModelError> ProcessSyncChanges(
Brett Wilsone1a70422017-09-12 05:10:09126 const base::Location& from_here,
asargente48ab752016-03-12 00:59:20127 const syncer::SyncChangeList& change_list) override {
128 syncer::FakeSyncChangeProcessor::ProcessSyncChanges(from_here, change_list);
129 for (const auto& change : change_list) {
130 syncer::SyncData sync_data = change.sync_data();
131 EXPECT_EQ(expected_type_, sync_data.GetDataType());
132
dchengc963c7142016-04-08 03:55:22133 std::unique_ptr<ExtensionSyncData> modified =
asargente48ab752016-03-12 00:59:20134 ExtensionSyncData::CreateFromSyncData(sync_data);
135
136 // Start by removing any existing entry for this extension id.
137 syncer::SyncDataList& data_list = data();
138 for (auto iter = data_list.begin(); iter != data_list.end(); ++iter) {
dchengc963c7142016-04-08 03:55:22139 std::unique_ptr<ExtensionSyncData> existing =
asargente48ab752016-03-12 00:59:20140 ExtensionSyncData::CreateFromSyncData(*iter);
141 if (existing->id() == modified->id()) {
142 data_list.erase(iter);
143 break;
144 }
145 }
146
147 // Now add in the new data for this id, if appropriate.
148 if (change.change_type() == SyncChange::ACTION_ADD ||
149 change.change_type() == SyncChange::ACTION_UPDATE) {
150 data_list.push_back(sync_data);
151 } else if (change.change_type() != SyncChange::ACTION_DELETE) {
152 ADD_FAILURE() << "Unexpected change type " << change.change_type();
153 }
154 }
Victor Hugo Vianna Silvad591a082020-04-16 10:56:36155 return base::nullopt;
asargente48ab752016-03-12 00:59:20156 }
157
158 // We override this to help catch the error of trying to use a single
159 // StatefulChangeProcessor to process changes for both extensions and apps
160 // sync data.
161 syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override {
162 EXPECT_EQ(expected_type_, type);
163 return FakeSyncChangeProcessor::GetAllSyncData(type);
164 }
165
166 // This is a helper to vend a wrapped version of this object suitable for
167 // passing in to MergeDataAndStartSyncing, which takes a
dchengc963c7142016-04-08 03:55:22168 // std::unique_ptr<SyncChangeProcessor>, since in tests we typically don't
169 // want to
asargente48ab752016-03-12 00:59:20170 // give up ownership of a local change processor.
dchengc963c7142016-04-08 03:55:22171 std::unique_ptr<syncer::SyncChangeProcessor> GetWrapped() {
Jinho Bangb5216cec2018-01-17 19:43:11172 return std::make_unique<syncer::SyncChangeProcessorWrapperForTest>(this);
asargente48ab752016-03-12 00:59:20173 }
174
175 protected:
176 // The expected ModelType of changes that this processor will see.
177 syncer::ModelType expected_type_;
178
179 DISALLOW_COPY_AND_ASSIGN(StatefulChangeProcessor);
180};
181
treib65f103042015-12-03 10:21:36182} // namespace
183
treib9afc6212015-10-30 18:49:58184class ExtensionServiceSyncTest
185 : public extensions::ExtensionServiceTestWithInstall {
186 public:
187 void MockSyncStartFlare(bool* was_called,
188 syncer::ModelType* model_type_passed_in,
189 syncer::ModelType model_type) {
190 *was_called = true;
191 *model_type_passed_in = model_type;
192 }
193
asargente48ab752016-03-12 00:59:20194 // Helper to call MergeDataAndStartSyncing with no server data and dummy
195 // change processor / error factory.
196 void StartSyncing(syncer::ModelType type) {
197 ASSERT_TRUE(type == syncer::EXTENSIONS || type == syncer::APPS);
198 extension_sync_service()->MergeDataAndStartSyncing(
199 type, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11200 std::make_unique<syncer::FakeSyncChangeProcessor>(),
201 std::make_unique<syncer::SyncErrorFactoryMock>());
asargente48ab752016-03-12 00:59:20202 }
203
rdevlin.cronin2f1ed4c2017-06-13 16:22:13204 void DisableExtensionFromSync(const Extension& extension,
205 int disable_reasons) {
Minh X. Nguyen45479012017-08-18 21:35:36206 ExtensionSyncData disable_extension = GetDisableSyncData(
207 extension, extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13208 SyncChangeList list(
209 1, disable_extension.GetSyncChange(SyncChange::ACTION_UPDATE));
210 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
211 }
212
213 void EnableExtensionFromSync(const Extension& extension) {
214 ExtensionSyncData enable_extension = GetEnableSyncData(extension);
215 SyncChangeList list(
216 1, enable_extension.GetSyncChange(SyncChange::ACTION_UPDATE));
217 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
218 }
219
treib9afc6212015-10-30 18:49:58220 protected:
221 // Paths to some of the fake extensions.
222 base::FilePath good0_path() {
223 return data_dir()
224 .AppendASCII("good")
225 .AppendASCII("Extensions")
226 .AppendASCII(good0)
227 .AppendASCII("1.0.0.0");
228 }
229
230 ExtensionSyncService* extension_sync_service() {
231 return ExtensionSyncService::Get(profile());
232 }
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02233
234 ExtensionSystem* extension_system() {
235 return ExtensionSystem::Get(profile());
236 }
treib9afc6212015-10-30 18:49:58237};
238
239TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledComponent) {
240 InitializeEmptyExtensionService();
241
242 bool flare_was_called = false;
243 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
244 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
245 extension_sync_service()->SetSyncStartFlareForTesting(
246 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
247 factory.GetWeakPtr(),
248 &flare_was_called, // Safe due to WeakPtrFactory scope.
249 &triggered_type)); // Safe due to WeakPtrFactory scope.
250
251 // Install a component extension.
252 std::string manifest;
253 ASSERT_TRUE(base::ReadFileToString(
254 good0_path().Append(extensions::kManifestFilename), &manifest));
255 service()->component_loader()->Add(manifest, good0_path());
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02256 ASSERT_FALSE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58257 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02258 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58259
260 // Extensions added before service is_ready() don't trigger sync startup.
261 EXPECT_FALSE(flare_was_called);
262 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
263}
264
265TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledNormal) {
266 InitializeGoodInstalledExtensionService();
267
268 bool flare_was_called = false;
269 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
270 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
271 extension_sync_service()->SetSyncStartFlareForTesting(
272 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
273 factory.GetWeakPtr(),
274 &flare_was_called, // Safe due to WeakPtrFactory scope.
275 &triggered_type)); // Safe due to WeakPtrFactory scope.
276
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02277 ASSERT_FALSE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58278 service()->Init();
279 ASSERT_EQ(3u, loaded_.size());
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02280 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58281
282 // Extensions added before service is_ready() don't trigger sync startup.
283 EXPECT_FALSE(flare_was_called);
284 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
285}
286
287TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupOnInstall) {
288 InitializeEmptyExtensionService();
289 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02290 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58291
292 bool flare_was_called = false;
293 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
294 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
295 extension_sync_service()->SetSyncStartFlareForTesting(
296 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
297 factory.GetWeakPtr(),
298 &flare_was_called, // Safe due to WeakPtrFactory scope.
299 &triggered_type)); // Safe due to WeakPtrFactory scope.
300
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,
Toby Huangd7caf252019-10-30 01:11:16355 false);
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,
Toby Huangd7caf252019-10-30 01:11:16550 false, false);
Devlin Cronin93beb23d2018-05-04 21:17:35551 ExtensionSyncData enable_good2(*extension2, true,
552 extensions::disable_reason::DISABLE_NONE,
Toby Huangd7caf252019-10-30 01:11:16553 false, false);
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.
Devlin Cronin93beb23d2018-05-04 21:17:35606 ExtensionSyncData data(*extension, false,
607 extensions::disable_reason::DISABLE_USER_ACTION,
Toby Huangd7caf252019-10-30 01:11:16608 false, false);
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,
Toby Huangd7caf252019-10-30 01:11:16624 false);
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,
Toby Huangd7caf252019-10-30 01:11:16642 false, false);
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,
Toby Huangd7caf252019-10-30 01:11:16660 false, false);
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();
catmullings22bc2372016-11-02 19:59:35882 InstallCRX(data_dir().AppendASCII("good.crx"), Manifest::EXTERNAL_PREF,
883 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());
1408 EXPECT_EQ(Manifest::INTERNAL, info->install_source());
1409 // 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
atuchin2eb18eb2017-03-02 07:22:151581TEST_F(ExtensionServiceSyncCustomGalleryTest,
1582 ProcessSyncDataPermissionApproval) {
treib9afc6212015-10-30 18:49:581583 InitializeEmptyExtensionService();
1584 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361585 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111586 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1587 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581588
1589 const base::FilePath base_path =
1590 data_dir().AppendASCII("permissions_increase");
1591 const base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1592 const base::FilePath path_v1 = base_path.AppendASCII("v1");
1593 const base::FilePath path_v2 = base_path.AppendASCII("v2");
1594
1595 base::ScopedTempDir crx_dir;
1596 ASSERT_TRUE(crx_dir.CreateUniqueTempDir());
vabr9142fe22016-09-08 13:19:221597 const base::FilePath crx_path_v1 = crx_dir.GetPath().AppendASCII("temp1.crx");
treib9afc6212015-10-30 18:49:581598 PackCRX(path_v1, pem_path, crx_path_v1);
vabr9142fe22016-09-08 13:19:221599 const base::FilePath crx_path_v2 = crx_dir.GetPath().AppendASCII("temp2.crx");
treib9afc6212015-10-30 18:49:581600 PackCRX(path_v2, pem_path, crx_path_v2);
1601
1602 const std::string v1("1");
1603 const std::string v2("2");
1604
1605 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1606
1607 struct TestCase {
1608 const char* name; // For failure output only.
1609 const std::string& sync_version; // The version coming in from Sync.
1610 // The disable reason(s) coming in from Sync, or -1 for "not set".
1611 int sync_disable_reasons;
1612 // The expected set of disable reasons after processing the Sync update. The
1613 // extension should be enabled iff this is 0.
1614 int expect_disable_reasons;
1615 // Whether the extension's permissions should be auto-granted.
1616 bool expect_permissions_granted;
1617 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361618 // Sync tells us to re-enable an older version. No permissions should be
1619 // granted, since we can't be sure if the user actually approved the right
1620 // set of permissions.
1621 {"OldVersion", v1, 0,
1622 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
1623 // Legacy case: Sync tells us to re-enable the extension, but doesn't
1624 // specify disable reasons. No permissions should be granted.
1625 {"Legacy", v2, -1,
1626 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
1627 // Sync tells us to re-enable the extension and explicitly removes the
1628 // disable reasons. Now the extension should have its permissions granted.
1629 {"GrantPermissions", v2, 0, extensions::disable_reason::DISABLE_NONE,
1630 true},
treib9afc6212015-10-30 18:49:581631 };
1632
1633 for (const TestCase& test_case : test_cases) {
1634 SCOPED_TRACE(test_case.name);
1635
1636 std::string id;
1637 // Don't keep |extension| around longer than necessary (it'll be destroyed
1638 // during updating).
1639 {
1640 const Extension* extension = InstallCRX(crx_path_v1, INSTALL_NEW);
1641 // The extension should now be installed and enabled.
1642 ASSERT_TRUE(extension);
1643 ASSERT_EQ(v1, extension->VersionString());
1644 id = extension->id();
1645 }
1646 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1647
dchengc963c7142016-04-08 03:55:221648 std::unique_ptr<const PermissionSet> granted_permissions_v1 =
treib9afc6212015-10-30 18:49:581649 prefs->GetGrantedPermissions(id);
1650
1651 // Update to a new version with increased permissions.
1652 UpdateExtension(id, crx_path_v2, DISABLED);
1653
1654 // Now the extension should be disabled due to a permissions increase.
1655 {
1656 const Extension* extension =
1657 registry()->disabled_extensions().GetByID(id);
1658 ASSERT_TRUE(extension);
1659 ASSERT_EQ(v2, extension->VersionString());
1660 }
1661 ASSERT_TRUE(prefs->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:361662 id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE));
treib9afc6212015-10-30 18:49:581663
1664 // No new permissions should have been granted.
dchengc963c7142016-04-08 03:55:221665 std::unique_ptr<const PermissionSet> granted_permissions_v2 =
treib9afc6212015-10-30 18:49:581666 prefs->GetGrantedPermissions(id);
1667 ASSERT_EQ(*granted_permissions_v1, *granted_permissions_v2);
1668
1669 // Now a sync update comes in.
1670 sync_pb::EntitySpecifics specifics;
1671 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1672 ext_specifics->set_id(id);
1673 ext_specifics->set_enabled(true);
1674 ext_specifics->set_version(test_case.sync_version);
1675 if (test_case.sync_disable_reasons != -1)
1676 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1677
treib65f103042015-12-03 10:21:361678 SyncChangeList list =
1679 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1680
treib9afc6212015-10-30 18:49:581681 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1682
1683 // Check expectations.
1684 const bool expect_enabled = !test_case.expect_disable_reasons;
1685 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1686 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
dchengc963c7142016-04-08 03:55:221687 std::unique_ptr<const PermissionSet> granted_permissions =
treib9afc6212015-10-30 18:49:581688 prefs->GetGrantedPermissions(id);
1689 if (test_case.expect_permissions_granted) {
dchengc963c7142016-04-08 03:55:221690 std::unique_ptr<const PermissionSet> active_permissions =
treib9afc6212015-10-30 18:49:581691 prefs->GetActivePermissions(id);
1692 EXPECT_EQ(*granted_permissions, *active_permissions);
1693 } else {
1694 EXPECT_EQ(*granted_permissions, *granted_permissions_v1);
1695 }
1696
1697 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031698 UninstallExtension(id);
treib9afc6212015-10-30 18:49:581699 }
1700}
1701
treib227b2582015-12-09 09:28:261702// Regression test for crbug.com/558299
1703TEST_F(ExtensionServiceSyncTest, DontSyncThemes) {
1704 InitializeEmptyExtensionService();
1705
1706 // The user has enabled sync.
Marc Treib9948a682018-11-20 08:01:371707 ProfileSyncServiceFactory::GetForProfile(profile())
1708 ->GetUserSettings()
Tanmoy Mollik0960d702019-09-11 15:14:471709 ->SetFirstSetupComplete(kSetSourceFromTest);
treib227b2582015-12-09 09:28:261710 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
1711 extension_sync_service();
1712
1713 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:021714 ASSERT_TRUE(extension_system()->is_ready());
treib227b2582015-12-09 09:28:261715
1716 syncer::FakeSyncChangeProcessor* processor =
1717 new syncer::FakeSyncChangeProcessor;
1718 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:221719 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
1720 base::WrapUnique(new syncer::SyncErrorFactoryMock));
treib227b2582015-12-09 09:28:261721
1722 processor->changes().clear();
1723
1724 // Sanity check: Installing an extension should result in a sync change.
1725 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1726 EXPECT_EQ(1u, processor->changes().size());
1727
1728 processor->changes().clear();
1729
1730 // Installing a theme should not result in a sync change (themes are handled
1731 // separately by ThemeSyncableService).
1732 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
Evan Stade46d716d2017-06-02 20:50:091733 content::WindowedNotificationObserver theme_change_observer(
1734 chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
1735 content::Source<ThemeService>(
1736 ThemeServiceFactory::GetForProfile(profile())));
1737 theme_change_observer.Wait();
treib227b2582015-12-09 09:28:261738 EXPECT_TRUE(processor->changes().empty());
1739}
1740
Toby Huang63a8d712019-11-27 20:07:321741// Tests sync behavior in the case of an item that starts out as an app and gets
1742// updated to become an extension.
asargente48ab752016-03-12 00:59:201743TEST_F(ExtensionServiceSyncTest, AppToExtension) {
1744 InitializeEmptyExtensionService();
1745 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:021746 ASSERT_TRUE(extension_system()->is_ready());
asargente48ab752016-03-12 00:59:201747
1748 // Install v1, which is an app.
1749 const Extension* v1 =
1750 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v1.crx"),
1751 INSTALL_NEW);
1752 EXPECT_TRUE(v1->is_app());
1753 EXPECT_FALSE(v1->is_extension());
1754 std::string id = v1->id();
1755
1756 StatefulChangeProcessor extensions_processor(syncer::ModelType::EXTENSIONS);
1757 StatefulChangeProcessor apps_processor(syncer::ModelType::APPS);
1758 extension_sync_service()->MergeDataAndStartSyncing(
1759 syncer::EXTENSIONS, syncer::SyncDataList(),
1760 extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221761 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201762 extension_sync_service()->MergeDataAndStartSyncing(
1763 syncer::APPS, syncer::SyncDataList(), apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221764 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201765
1766 // Check the app/extension change processors to be sure the right data was
1767 // added.
1768 EXPECT_TRUE(extensions_processor.changes().empty());
1769 EXPECT_TRUE(extensions_processor.data().empty());
1770 EXPECT_EQ(1u, apps_processor.data().size());
1771 ASSERT_EQ(1u, apps_processor.changes().size());
1772 const SyncChange& app_change = apps_processor.changes()[0];
1773 EXPECT_EQ(SyncChange::ACTION_ADD, app_change.change_type());
dchengc963c7142016-04-08 03:55:221774 std::unique_ptr<ExtensionSyncData> app_data =
asargente48ab752016-03-12 00:59:201775 ExtensionSyncData::CreateFromSyncData(app_change.sync_data());
1776 EXPECT_TRUE(app_data->is_app());
1777 EXPECT_EQ(id, app_data->id());
Devlin Cronin03bf2d22017-12-20 08:21:051778 EXPECT_EQ(v1->version(), app_data->version());
asargente48ab752016-03-12 00:59:201779
1780 // Update the app to v2, which is an extension.
1781 const Extension* v2 =
1782 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v2.crx"),
1783 INSTALL_UPDATED);
1784 EXPECT_FALSE(v2->is_app());
1785 EXPECT_TRUE(v2->is_extension());
1786 EXPECT_EQ(id, v2->id());
1787
1788 // Make sure we saw an extension item added.
1789 ASSERT_EQ(1u, extensions_processor.changes().size());
1790 const SyncChange& extension_change = extensions_processor.changes()[0];
1791 EXPECT_EQ(SyncChange::ACTION_ADD, extension_change.change_type());
dchengc963c7142016-04-08 03:55:221792 std::unique_ptr<ExtensionSyncData> extension_data =
asargente48ab752016-03-12 00:59:201793 ExtensionSyncData::CreateFromSyncData(extension_change.sync_data());
1794 EXPECT_FALSE(extension_data->is_app());
1795 EXPECT_EQ(id, extension_data->id());
Devlin Cronin03bf2d22017-12-20 08:21:051796 EXPECT_EQ(v2->version(), extension_data->version());
asargente48ab752016-03-12 00:59:201797
1798 // Get the current data from the change processors to use as the input to
1799 // the following call to MergeDataAndStartSyncing. This simulates what should
1800 // happen with sync.
1801 syncer::SyncDataList extensions_data =
1802 extensions_processor.GetAllSyncData(syncer::EXTENSIONS);
1803 syncer::SyncDataList apps_data = apps_processor.GetAllSyncData(syncer::APPS);
1804
1805 // Stop syncing, then start again.
1806 extension_sync_service()->StopSyncing(syncer::EXTENSIONS);
1807 extension_sync_service()->StopSyncing(syncer::APPS);
1808 extension_sync_service()->MergeDataAndStartSyncing(
1809 syncer::EXTENSIONS, extensions_data, extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221810 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201811 extension_sync_service()->MergeDataAndStartSyncing(
1812 syncer::APPS, apps_data, apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221813 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201814
1815 // Make sure we saw an app item deleted.
1816 bool found_delete = false;
1817 for (const auto& change : apps_processor.changes()) {
1818 if (change.change_type() == SyncChange::ACTION_DELETE) {
dchengc963c7142016-04-08 03:55:221819 std::unique_ptr<ExtensionSyncData> data =
asargente48ab752016-03-12 00:59:201820 ExtensionSyncData::CreateFromSyncChange(change);
1821 if (data->id() == id) {
1822 found_delete = true;
1823 break;
1824 }
1825 }
1826 }
1827 EXPECT_TRUE(found_delete);
1828
1829 // Make sure there is one extension, and there are no more apps.
1830 EXPECT_EQ(1u, extensions_processor.data().size());
1831 EXPECT_TRUE(apps_processor.data().empty());
1832}
proberge901ecab2017-08-31 19:24:281833
[email protected]950f2952020-07-10 03:35:501834class BlocklistedExtensionSyncServiceTest : public ExtensionServiceSyncTest {
proberge901ecab2017-08-31 19:24:281835 public:
[email protected]950f2952020-07-10 03:35:501836 BlocklistedExtensionSyncServiceTest() {}
proberge901ecab2017-08-31 19:24:281837
1838 void SetUp() override {
1839 ExtensionServiceSyncTest::SetUp();
1840
1841 InitializeEmptyExtensionService();
1842
1843 // Enable sync.
Marc Treib5a78e9c2019-02-19 16:47:011844 syncer::SyncService* sync_service =
proberge901ecab2017-08-31 19:24:281845 ProfileSyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:471846 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
proberge901ecab2017-08-31 19:24:281847
[email protected]950f2952020-07-10 03:35:501848 test_blocklist_.Attach(service()->blocklist_);
proberge901ecab2017-08-31 19:24:281849 service()->Init();
1850
1851 // Load up a simple extension.
1852 extensions::ChromeTestExtensionLoader extension_loader(profile());
1853 extension_loader.set_pack_extension(true);
1854 extension_ = extension_loader.LoadExtension(
1855 data_dir().AppendASCII("simple_with_file"));
1856 ASSERT_TRUE(extension_);
1857 extension_id_ = extension_->id();
1858 ASSERT_TRUE(registry()->enabled_extensions().GetByID(extension_id_));
1859
1860 {
Jinho Bangb5216cec2018-01-17 19:43:111861 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
proberge901ecab2017-08-31 19:24:281862 processor_raw_ = processor.get();
1863 extension_sync_service()->MergeDataAndStartSyncing(
1864 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:111865 std::make_unique<syncer::SyncErrorFactoryMock>());
proberge901ecab2017-08-31 19:24:281866 }
1867 processor_raw_->changes().clear();
1868 }
1869
[email protected]950f2952020-07-10 03:35:501870 void ForceBlocklistUpdate() {
1871 service()->OnBlocklistUpdated();
Gabriel Charette01507a22017-09-27 21:30:081872 content::RunAllTasksUntilIdle();
proberge901ecab2017-08-31 19:24:281873 }
1874
1875 syncer::FakeSyncChangeProcessor* processor() { return processor_raw_; }
1876
1877 const Extension* extension() { return extension_.get(); }
1878
1879 std::string& extension_id() { return extension_id_; }
1880
[email protected]950f2952020-07-10 03:35:501881 extensions::TestBlocklist& test_blocklist() { return test_blocklist_; }
proberge901ecab2017-08-31 19:24:281882
1883 private:
1884 syncer::FakeSyncChangeProcessor* processor_raw_;
1885 scoped_refptr<const Extension> extension_;
1886 std::string extension_id_;
[email protected]950f2952020-07-10 03:35:501887 extensions::TestBlocklist test_blocklist_;
proberge901ecab2017-08-31 19:24:281888
[email protected]950f2952020-07-10 03:35:501889 DISALLOW_COPY_AND_ASSIGN(BlocklistedExtensionSyncServiceTest);
proberge901ecab2017-08-31 19:24:281890};
1891
[email protected]950f2952020-07-10 03:35:501892// Test that sync cannot enable blocklisted extensions.
1893TEST_F(BlocklistedExtensionSyncServiceTest, SyncBlocklistedExtension) {
proberge901ecab2017-08-31 19:24:281894 std::string& extension_id = this->extension_id();
1895
[email protected]950f2952020-07-10 03:35:501896 // Blocklist the extension.
1897 test_blocklist().SetBlocklistState(extension_id,
[email protected]321b9292020-06-26 01:20:461898 extensions::BLOCKLISTED_MALWARE, true);
[email protected]950f2952020-07-10 03:35:501899 ForceBlocklistUpdate();
proberge901ecab2017-08-31 19:24:281900
1901 // Try enabling the extension via sync.
1902 EnableExtensionFromSync(*extension());
1903
1904 // The extension should not be enabled.
1905 EXPECT_FALSE(registry()->enabled_extensions().GetByID(extension_id));
1906 EXPECT_TRUE(processor()->changes().empty());
1907}
1908
1909// Test that some greylisted extensions can be enabled through sync.
[email protected]950f2952020-07-10 03:35:501910TEST_F(BlocklistedExtensionSyncServiceTest, SyncAllowedGreylistedExtension) {
proberge901ecab2017-08-31 19:24:281911 std::string& extension_id = this->extension_id();
1912
1913 // Greylist the extension.
[email protected]950f2952020-07-10 03:35:501914 test_blocklist().SetBlocklistState(
[email protected]321b9292020-06-26 01:20:461915 extension_id, extensions::BLOCKLISTED_POTENTIALLY_UNWANTED, true);
[email protected]950f2952020-07-10 03:35:501916 ForceBlocklistUpdate();
proberge901ecab2017-08-31 19:24:281917
1918 EXPECT_FALSE(registry()->enabled_extensions().GetByID(extension_id));
1919 {
1920 ASSERT_EQ(1u, processor()->changes().size());
1921 const SyncChange& change = processor()->changes()[0];
1922 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
1923 std::unique_ptr<ExtensionSyncData> data =
1924 ExtensionSyncData::CreateFromSyncData(change.sync_data());
1925 EXPECT_EQ(extension_id, data->id());
1926 EXPECT_EQ(extensions::disable_reason::DISABLE_GREYLIST,
1927 data->disable_reasons());
1928 EXPECT_FALSE(data->enabled());
1929 }
1930 processor()->changes().clear();
1931
1932 // Manually re-enabling the extension should work.
1933 service()->EnableExtension(extension_id);
1934 EXPECT_TRUE(registry()->enabled_extensions().GetByID(extension_id));
1935 {
1936 ASSERT_EQ(1u, processor()->changes().size());
1937 const SyncChange& change = processor()->changes()[0];
1938 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
1939 std::unique_ptr<ExtensionSyncData> data =
1940 ExtensionSyncData::CreateFromSyncData(change.sync_data());
1941 EXPECT_EQ(extension_id, data->id());
1942 EXPECT_EQ(0, data->disable_reasons());
1943 EXPECT_TRUE(data->enabled());
1944 }
1945 processor()->changes().clear();
1946}