blob: 23bbc95bef2c601c023ffec1a04acafcf3cccde3 [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);
Victor Hugo Vianna Silva75334d92020-11-10 07:42:44245 extension_sync_service()->SetSyncStartFlareForTesting(base::BindRepeating(
246 &ExtensionServiceSyncTest::MockSyncStartFlare, factory.GetWeakPtr(),
247 &flare_was_called, // Safe due to WeakPtrFactory scope.
248 &triggered_type)); // Safe due to WeakPtrFactory scope.
treib9afc6212015-10-30 18:49:58249
250 // Install a component extension.
251 std::string manifest;
252 ASSERT_TRUE(base::ReadFileToString(
253 good0_path().Append(extensions::kManifestFilename), &manifest));
254 service()->component_loader()->Add(manifest, good0_path());
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02255 ASSERT_FALSE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58256 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02257 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58258
259 // Extensions added before service is_ready() don't trigger sync startup.
260 EXPECT_FALSE(flare_was_called);
261 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
262}
263
264TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledNormal) {
265 InitializeGoodInstalledExtensionService();
266
267 bool flare_was_called = false;
268 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
269 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
Victor Hugo Vianna Silva75334d92020-11-10 07:42:44270 extension_sync_service()->SetSyncStartFlareForTesting(base::BindRepeating(
271 &ExtensionServiceSyncTest::MockSyncStartFlare, factory.GetWeakPtr(),
272 &flare_was_called, // Safe due to WeakPtrFactory scope.
273 &triggered_type)); // Safe due to WeakPtrFactory scope.
treib9afc6212015-10-30 18:49:58274
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02275 ASSERT_FALSE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58276 service()->Init();
277 ASSERT_EQ(3u, loaded_.size());
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02278 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58279
280 // Extensions added before service is_ready() don't trigger sync startup.
281 EXPECT_FALSE(flare_was_called);
282 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
283}
284
285TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupOnInstall) {
286 InitializeEmptyExtensionService();
287 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02288 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58289
290 bool flare_was_called = false;
291 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
292 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
Victor Hugo Vianna Silva75334d92020-11-10 07:42:44293 extension_sync_service()->SetSyncStartFlareForTesting(base::BindRepeating(
294 &ExtensionServiceSyncTest::MockSyncStartFlare, factory.GetWeakPtr(),
295 &flare_was_called, // Safe due to WeakPtrFactory scope.
296 &triggered_type)); // Safe due to WeakPtrFactory scope.
treib9afc6212015-10-30 18:49:58297
298 base::FilePath path = data_dir().AppendASCII("good.crx");
299 InstallCRX(path, INSTALL_NEW);
300
301 EXPECT_TRUE(flare_was_called);
302 EXPECT_EQ(syncer::EXTENSIONS, triggered_type);
303
304 // Reset.
305 flare_was_called = false;
306 triggered_type = syncer::UNSPECIFIED;
307
308 // Once sync starts, flare should no longer be invoked.
309 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36310 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11311 std::make_unique<syncer::FakeSyncChangeProcessor>(),
312 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58313 path = data_dir().AppendASCII("page_action.crx");
314 InstallCRX(path, INSTALL_NEW);
315 EXPECT_FALSE(flare_was_called);
316 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
317}
318
319TEST_F(ExtensionServiceSyncTest, DisableExtensionFromSync) {
320 // Start the extensions service with one external extension already installed.
321 base::FilePath source_install_dir =
322 data_dir().AppendASCII("good").AppendASCII("Extensions");
323 base::FilePath pref_path =
324 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
325
326 InitializeInstalledExtensionService(pref_path, source_install_dir);
327
328 // The user has enabled sync.
Marc Treib5a78e9c2019-02-19 16:47:01329 syncer::SyncService* sync_service =
treib9afc6212015-10-30 18:49:58330 ProfileSyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:47331 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
treib9afc6212015-10-30 18:49:58332
333 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02334 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58335
336 ASSERT_EQ(3u, loaded_.size());
337
338 // We start enabled.
David Bertonia0b34722019-09-30 20:51:26339 const Extension* extension = registry()->enabled_extensions().GetByID(good0);
treib9afc6212015-10-30 18:49:58340 ASSERT_TRUE(extension);
341 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
342
343 // Sync starts up.
344 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36345 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11346 std::make_unique<syncer::FakeSyncChangeProcessor>(),
347 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58348
349 // Then sync data arrives telling us to disable |good0|.
Minh X. Nguyen45479012017-08-18 21:35:36350 ExtensionSyncData disable_good_crx(
351 *extension, false, extensions::disable_reason::DISABLE_USER_ACTION, false,
Toby Huangd7caf252019-10-30 01:11:16352 false);
treib65f103042015-12-03 10:21:36353 SyncChangeList list(
354 1, disable_good_crx.GetSyncChange(SyncChange::ACTION_UPDATE));
treib9afc6212015-10-30 18:49:58355 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
356
357 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
358}
359
rdevlin.cronin2f1ed4c2017-06-13 16:22:13360// Test that sync can enable and disable installed extensions.
361TEST_F(ExtensionServiceSyncTest, ReenableDisabledExtensionFromSync) {
362 InitializeEmptyExtensionService();
363
364 // Enable sync.
Marc Treib5a78e9c2019-02-19 16:47:01365 syncer::SyncService* sync_service =
rdevlin.cronin2f1ed4c2017-06-13 16:22:13366 ProfileSyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:47367 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13368
369 service()->Init();
370
371 // Load up a simple extension.
372 extensions::ChromeTestExtensionLoader extension_loader(profile());
373 extension_loader.set_pack_extension(true);
374 scoped_refptr<const Extension> extension = extension_loader.LoadExtension(
375 data_dir().AppendASCII("simple_with_file"));
376 ASSERT_TRUE(extension);
377 const std::string kExtensionId = extension->id();
378 ASSERT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
379
380 syncer::FakeSyncChangeProcessor* processor_raw = nullptr;
381 {
Jinho Bangb5216cec2018-01-17 19:43:11382 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
rdevlin.cronin2f1ed4c2017-06-13 16:22:13383 processor_raw = processor.get();
384 extension_sync_service()->MergeDataAndStartSyncing(
385 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:11386 std::make_unique<syncer::SyncErrorFactoryMock>());
rdevlin.cronin2f1ed4c2017-06-13 16:22:13387 }
388 processor_raw->changes().clear();
389
Minh X. Nguyen45479012017-08-18 21:35:36390 DisableExtensionFromSync(*extension,
391 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13392
393 // The extension should be disabled.
394 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
Minh X. Nguyen45479012017-08-18 21:35:36395 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
rdevlin.cronin2f1ed4c2017-06-13 16:22:13396 ExtensionPrefs::Get(profile())->GetDisableReasons(kExtensionId));
397 EXPECT_TRUE(processor_raw->changes().empty());
398
399 // Enable the extension. Sync should push the new state.
400 service()->EnableExtension(kExtensionId);
401 {
402 ASSERT_EQ(1u, processor_raw->changes().size());
403 const SyncChange& change = processor_raw->changes()[0];
404 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
405 std::unique_ptr<ExtensionSyncData> data =
406 ExtensionSyncData::CreateFromSyncData(change.sync_data());
407 EXPECT_EQ(kExtensionId, data->id());
408 EXPECT_EQ(0, data->disable_reasons());
409 EXPECT_TRUE(data->enabled());
410 }
411
412 // Disable the extension again. Sync should push the new state.
413 processor_raw->changes().clear();
Minh X. Nguyen45479012017-08-18 21:35:36414 service()->DisableExtension(kExtensionId,
415 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13416 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
417 {
418 ASSERT_EQ(1u, processor_raw->changes().size());
419 const SyncChange& change = processor_raw->changes()[0];
420 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
421 std::unique_ptr<ExtensionSyncData> data =
422 ExtensionSyncData::CreateFromSyncData(change.sync_data());
423 EXPECT_EQ(kExtensionId, data->id());
Minh X. Nguyen45479012017-08-18 21:35:36424 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
425 data->disable_reasons());
rdevlin.cronin2f1ed4c2017-06-13 16:22:13426 EXPECT_FALSE(data->enabled());
427 }
428 processor_raw->changes().clear();
429
430 // Enable the extension via sync.
431 EnableExtensionFromSync(*extension);
432
433 // The extension should be enabled.
434 EXPECT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
435 EXPECT_TRUE(processor_raw->changes().empty());
436}
437
438// Tests that default-installed extensions won't be affected by incoming sync
439// data. (It's feasible to have a sync entry for an extension that could be
440// default installed, since one installation may be default-installed while
441// another may not be).
442TEST_F(ExtensionServiceSyncTest,
443 DefaultInstalledExtensionsAreNotReenabledOrDisabledBySync) {
444 InitializeEmptyExtensionService();
445
446 // Enable sync.
Marc Treib5a78e9c2019-02-19 16:47:01447 syncer::SyncService* sync_service =
rdevlin.cronin2f1ed4c2017-06-13 16:22:13448 ProfileSyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:47449 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13450
451 service()->Init();
452
453 // Load up an extension that's considered default installed.
454 extensions::ChromeTestExtensionLoader extension_loader(profile());
455 extension_loader.set_pack_extension(true);
456 extension_loader.add_creation_flag(Extension::WAS_INSTALLED_BY_DEFAULT);
457 scoped_refptr<const Extension> extension = extension_loader.LoadExtension(
458 data_dir().AppendASCII("simple_with_file"));
459 ASSERT_TRUE(extension);
460
461 // The extension shouldn't sync.
462 EXPECT_FALSE(extensions::util::ShouldSync(extension.get(), profile()));
463 const std::string kExtensionId = extension->id();
464 ASSERT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
465
466 syncer::FakeSyncChangeProcessor* processor_raw = nullptr;
467 {
Jinho Bangb5216cec2018-01-17 19:43:11468 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
rdevlin.cronin2f1ed4c2017-06-13 16:22:13469 processor_raw = processor.get();
470 extension_sync_service()->MergeDataAndStartSyncing(
471 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:11472 std::make_unique<syncer::SyncErrorFactoryMock>());
rdevlin.cronin2f1ed4c2017-06-13 16:22:13473 }
474 processor_raw->changes().clear();
475
476 // Sync state says the extension is disabled (e.g. on another machine).
Minh X. Nguyen45479012017-08-18 21:35:36477 DisableExtensionFromSync(*extension,
478 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13479
480 // The extension should still be enabled, since it's default-installed.
481 EXPECT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
482 EXPECT_TRUE(processor_raw->changes().empty());
483
484 // Now disable the extension locally. Sync should *not* push new state.
Minh X. Nguyen45479012017-08-18 21:35:36485 service()->DisableExtension(kExtensionId,
486 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13487 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
488 EXPECT_TRUE(processor_raw->changes().empty());
489
490 // Sync state says the extension is enabled.
491 EnableExtensionFromSync(*extension);
492
493 // As above, the extension should not have been affected by sync.
494 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
495 EXPECT_TRUE(processor_raw->changes().empty());
496
497 // And re-enabling the extension should not push new state to sync.
498 service()->EnableExtension(kExtensionId);
499 EXPECT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
500 EXPECT_TRUE(processor_raw->changes().empty());
501}
502
treib9afc6212015-10-30 18:49:58503TEST_F(ExtensionServiceSyncTest, IgnoreSyncChangesWhenLocalStateIsMoreRecent) {
504 // Start the extension service with three extensions already installed.
505 base::FilePath source_install_dir =
506 data_dir().AppendASCII("good").AppendASCII("Extensions");
507 base::FilePath pref_path =
508 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
509
510 InitializeInstalledExtensionService(pref_path, source_install_dir);
511
512 // The user has enabled sync.
Marc Treib5a78e9c2019-02-19 16:47:01513 syncer::SyncService* sync_service =
treib9afc6212015-10-30 18:49:58514 ProfileSyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:47515 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
treib9afc6212015-10-30 18:49:58516 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
517 extension_sync_service();
518
519 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02520 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58521 ASSERT_EQ(3u, loaded_.size());
522
523 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
524 ASSERT_TRUE(service()->IsExtensionEnabled(good2));
525
526 // Disable and re-enable good0 before first sync data arrives.
Minh X. Nguyen45479012017-08-18 21:35:36527 service()->DisableExtension(good0,
528 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:58529 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
530 service()->EnableExtension(good0);
531 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
532 // Disable good2 before first sync data arrives (good1 is considered
533 // non-syncable because it has plugin permission).
Minh X. Nguyen45479012017-08-18 21:35:36534 service()->DisableExtension(good2,
535 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:58536 ASSERT_FALSE(service()->IsExtensionEnabled(good2));
537
David Bertonia0b34722019-09-30 20:51:26538 const Extension* extension0 = registry()->enabled_extensions().GetByID(good0);
David Bertoni58c113a2019-08-02 19:53:26539 const Extension* extension2 =
David Bertonia0b34722019-09-30 20:51:26540 registry()->disabled_extensions().GetByID(good2);
treib9afc6212015-10-30 18:49:58541 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension0));
542 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension2));
543
544 // Now sync data comes in that says to disable good0 and enable good2.
Minh X. Nguyen45479012017-08-18 21:35:36545 ExtensionSyncData disable_good0(
546 *extension0, false, extensions::disable_reason::DISABLE_USER_ACTION,
Toby Huangd7caf252019-10-30 01:11:16547 false, false);
Devlin Cronin93beb23d2018-05-04 21:17:35548 ExtensionSyncData enable_good2(*extension2, true,
549 extensions::disable_reason::DISABLE_NONE,
Toby Huangd7caf252019-10-30 01:11:16550 false, false);
treib9afc6212015-10-30 18:49:58551 syncer::SyncDataList sync_data;
552 sync_data.push_back(disable_good0.GetSyncData());
553 sync_data.push_back(enable_good2.GetSyncData());
554 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:22555 syncer::EXTENSIONS, sync_data,
Jinho Bangb5216cec2018-01-17 19:43:11556 std::make_unique<syncer::FakeSyncChangeProcessor>(),
557 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58558
559 // Both sync changes should be ignored, since the local state was changed
560 // before sync started, and so the local state is considered more recent.
561 EXPECT_TRUE(service()->IsExtensionEnabled(good0));
562 EXPECT_FALSE(service()->IsExtensionEnabled(good2));
563}
564
treibb794dd52015-12-01 18:47:14565TEST_F(ExtensionServiceSyncTest, DontSelfNotify) {
566 // Start the extension service with three extensions already installed.
567 base::FilePath source_install_dir =
568 data_dir().AppendASCII("good").AppendASCII("Extensions");
569 base::FilePath pref_path =
570 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
571
572 InitializeInstalledExtensionService(pref_path, source_install_dir);
573
574 // The user has enabled sync.
Marc Treib9948a682018-11-20 08:01:37575 ProfileSyncServiceFactory::GetForProfile(profile())
576 ->GetUserSettings()
Tanmoy Mollik0960d702019-09-11 15:14:47577 ->SetFirstSetupComplete(kSetSourceFromTest);
treibb794dd52015-12-01 18:47:14578 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
579 extension_sync_service();
580
581 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02582 ASSERT_TRUE(extension_system()->is_ready());
treibb794dd52015-12-01 18:47:14583 ASSERT_EQ(3u, loaded_.size());
584 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
585
586 syncer::FakeSyncChangeProcessor* processor =
587 new syncer::FakeSyncChangeProcessor;
588 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:22589 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
Jinho Bangb5216cec2018-01-17 19:43:11590 std::make_unique<syncer::SyncErrorFactoryMock>());
treibb794dd52015-12-01 18:47:14591
592 processor->changes().clear();
593
594 // Simulate various incoming sync changes, and make sure they don't result in
595 // any outgoing changes.
596
597 {
David Bertoni58c113a2019-08-02 19:53:26598 const Extension* extension =
David Bertonia0b34722019-09-30 20:51:26599 registry()->enabled_extensions().GetByID(good0);
treibb794dd52015-12-01 18:47:14600 ASSERT_TRUE(extension);
601
602 // Disable the extension.
Devlin Cronin93beb23d2018-05-04 21:17:35603 ExtensionSyncData data(*extension, false,
604 extensions::disable_reason::DISABLE_USER_ACTION,
Toby Huangd7caf252019-10-30 01:11:16605 false, false);
treib65f103042015-12-03 10:21:36606 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14607
608 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
609
610 EXPECT_TRUE(processor->changes().empty());
611 }
612
613 {
David Bertoni58c113a2019-08-02 19:53:26614 const Extension* extension =
David Bertonia0b34722019-09-30 20:51:26615 registry()->disabled_extensions().GetByID(good0);
treibb794dd52015-12-01 18:47:14616 ASSERT_TRUE(extension);
617
618 // Set incognito enabled to true.
Minh X. Nguyen45479012017-08-18 21:35:36619 ExtensionSyncData data(*extension, false,
620 extensions::disable_reason::DISABLE_NONE, true,
Toby Huangd7caf252019-10-30 01:11:16621 false);
treib65f103042015-12-03 10:21:36622 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14623
624 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
625
626 EXPECT_TRUE(processor->changes().empty());
627 }
628
629 {
David Bertoni58c113a2019-08-02 19:53:26630 const Extension* extension =
David Bertonia0b34722019-09-30 20:51:26631 registry()->disabled_extensions().GetByID(good0);
treibb794dd52015-12-01 18:47:14632 ASSERT_TRUE(extension);
633
634 // Add another disable reason.
Minh X. Nguyen45479012017-08-18 21:35:36635 ExtensionSyncData data(
636 *extension, false,
637 extensions::disable_reason::DISABLE_USER_ACTION |
638 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
Toby Huangd7caf252019-10-30 01:11:16639 false, false);
treib65f103042015-12-03 10:21:36640 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14641
642 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
643
644 EXPECT_TRUE(processor->changes().empty());
645 }
646
647 {
David Bertoni58c113a2019-08-02 19:53:26648 const Extension* extension =
David Bertonia0b34722019-09-30 20:51:26649 registry()->disabled_extensions().GetByID(good0);
treibb794dd52015-12-01 18:47:14650 ASSERT_TRUE(extension);
651
652 // Uninstall the extension.
Minh X. Nguyen45479012017-08-18 21:35:36653 ExtensionSyncData data(
654 *extension, false,
655 extensions::disable_reason::DISABLE_USER_ACTION |
656 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
Toby Huangd7caf252019-10-30 01:11:16657 false, false);
treib65f103042015-12-03 10:21:36658 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_DELETE));
treibb794dd52015-12-01 18:47:14659
660 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
661
662 EXPECT_TRUE(processor->changes().empty());
663 }
664}
665
treib9afc6212015-10-30 18:49:58666TEST_F(ExtensionServiceSyncTest, GetSyncData) {
667 InitializeEmptyExtensionService();
668 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
David Bertoni9f897c92019-09-20 17:46:35669 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58670 ASSERT_TRUE(extension);
671
672 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36673 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11674 std::make_unique<syncer::FakeSyncChangeProcessor>(),
675 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58676
677 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16678 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58679 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22680 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58681 ExtensionSyncData::CreateFromSyncData(list[0]);
682 ASSERT_TRUE(data.get());
683 EXPECT_EQ(extension->id(), data->id());
684 EXPECT_FALSE(data->uninstalled());
685 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
686 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
687 data->incognito_enabled());
Devlin Cronin03bf2d22017-12-20 08:21:05688 EXPECT_EQ(data->version(), extension->version());
treib9afc6212015-10-30 18:49:58689 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
690 data->update_url());
691 EXPECT_EQ(extension->name(), data->name());
692}
693
treib29e1b9b12015-11-11 08:50:56694TEST_F(ExtensionServiceSyncTest, GetSyncDataDisableReasons) {
695 InitializeEmptyExtensionService();
696 const Extension* extension =
697 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
698 ASSERT_TRUE(extension);
699
treib29e1b9b12015-11-11 08:50:56700 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36701 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11702 std::make_unique<syncer::FakeSyncChangeProcessor>(),
703 std::make_unique<syncer::SyncErrorFactoryMock>());
treib29e1b9b12015-11-11 08:50:56704
705 {
706 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16707 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib29e1b9b12015-11-11 08:50:56708 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22709 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56710 ExtensionSyncData::CreateFromSyncData(list[0]);
711 ASSERT_TRUE(data.get());
712 EXPECT_TRUE(data->enabled());
713 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36714 EXPECT_EQ(extensions::disable_reason::DISABLE_NONE,
715 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56716 }
717
718 // Syncable disable reason, should propagate to sync.
Minh X. Nguyen45479012017-08-18 21:35:36719 service()->DisableExtension(good_crx,
720 extensions::disable_reason::DISABLE_USER_ACTION);
treib29e1b9b12015-11-11 08:50:56721 {
722 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16723 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib29e1b9b12015-11-11 08:50:56724 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22725 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56726 ExtensionSyncData::CreateFromSyncData(list[0]);
727 ASSERT_TRUE(data.get());
728 EXPECT_FALSE(data->enabled());
729 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36730 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
731 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56732 }
733 service()->EnableExtension(good_crx);
734
735 // Non-syncable disable reason. The sync data should still say "enabled".
Minh X. Nguyen45479012017-08-18 21:35:36736 service()->DisableExtension(good_crx,
737 extensions::disable_reason::DISABLE_RELOAD);
treib29e1b9b12015-11-11 08:50:56738 {
739 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16740 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib29e1b9b12015-11-11 08:50:56741 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22742 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56743 ExtensionSyncData::CreateFromSyncData(list[0]);
744 ASSERT_TRUE(data.get());
745 EXPECT_TRUE(data->enabled());
746 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36747 EXPECT_EQ(extensions::disable_reason::DISABLE_NONE,
748 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56749 }
750 service()->EnableExtension(good_crx);
751
752 // Both a syncable and a non-syncable disable reason, only the former should
753 // propagate to sync.
Minh X. Nguyen45479012017-08-18 21:35:36754 service()->DisableExtension(good_crx,
755 extensions::disable_reason::DISABLE_USER_ACTION |
756 extensions::disable_reason::DISABLE_RELOAD);
treib29e1b9b12015-11-11 08:50:56757 {
758 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16759 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib29e1b9b12015-11-11 08:50:56760 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22761 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56762 ExtensionSyncData::CreateFromSyncData(list[0]);
763 ASSERT_TRUE(data.get());
764 EXPECT_FALSE(data->enabled());
765 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36766 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
767 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56768 }
769 service()->EnableExtension(good_crx);
770}
771
treib9afc6212015-10-30 18:49:58772TEST_F(ExtensionServiceSyncTest, GetSyncDataTerminated) {
773 InitializeEmptyExtensionService();
774 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
775 TerminateExtension(good_crx);
David Bertoni9f897c92019-09-20 17:46:35776 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58777 ASSERT_TRUE(extension);
778
treib9afc6212015-10-30 18:49:58779 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36780 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11781 std::make_unique<syncer::FakeSyncChangeProcessor>(),
782 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58783
784 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16785 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58786 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22787 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58788 ExtensionSyncData::CreateFromSyncData(list[0]);
789 ASSERT_TRUE(data.get());
790 EXPECT_EQ(extension->id(), data->id());
791 EXPECT_FALSE(data->uninstalled());
792 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
793 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
794 data->incognito_enabled());
Devlin Cronin03bf2d22017-12-20 08:21:05795 EXPECT_EQ(data->version(), extension->version());
treib9afc6212015-10-30 18:49:58796 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
797 data->update_url());
798 EXPECT_EQ(extension->name(), data->name());
799}
800
801TEST_F(ExtensionServiceSyncTest, GetSyncDataFilter) {
802 InitializeEmptyExtensionService();
803 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
David Bertoni9f897c92019-09-20 17:46:35804 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58805 ASSERT_TRUE(extension);
806
treib9afc6212015-10-30 18:49:58807 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36808 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11809 std::make_unique<syncer::FakeSyncChangeProcessor>(),
810 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58811
812 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16813 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58814 ASSERT_EQ(list.size(), 0U);
815}
816
817TEST_F(ExtensionServiceSyncTest, GetSyncExtensionDataUserSettings) {
818 InitializeEmptyExtensionService();
819 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
David Bertoni9f897c92019-09-20 17:46:35820 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58821 ASSERT_TRUE(extension);
822
treib9afc6212015-10-30 18:49:58823 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36824 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11825 std::make_unique<syncer::FakeSyncChangeProcessor>(),
826 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58827
828 {
829 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16830 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58831 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22832 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58833 ExtensionSyncData::CreateFromSyncData(list[0]);
834 ASSERT_TRUE(data.get());
835 EXPECT_TRUE(data->enabled());
836 EXPECT_FALSE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58837 }
838
Minh X. Nguyen45479012017-08-18 21:35:36839 service()->DisableExtension(good_crx,
840 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:58841 {
842 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16843 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58844 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22845 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58846 ExtensionSyncData::CreateFromSyncData(list[0]);
847 ASSERT_TRUE(data.get());
848 EXPECT_FALSE(data->enabled());
849 EXPECT_FALSE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58850 }
851
852 extensions::util::SetIsIncognitoEnabled(good_crx, profile(), true);
treib9afc6212015-10-30 18:49:58853 {
854 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16855 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58856 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22857 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58858 ExtensionSyncData::CreateFromSyncData(list[0]);
859 ASSERT_TRUE(data.get());
860 EXPECT_FALSE(data->enabled());
861 EXPECT_TRUE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58862 }
863
864 service()->EnableExtension(good_crx);
treib9afc6212015-10-30 18:49:58865 {
866 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16867 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58868 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22869 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58870 ExtensionSyncData::CreateFromSyncData(list[0]);
871 ASSERT_TRUE(data.get());
872 EXPECT_TRUE(data->enabled());
873 EXPECT_TRUE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58874 }
875}
876
877TEST_F(ExtensionServiceSyncTest, SyncForUninstalledExternalExtension) {
878 InitializeEmptyExtensionService();
catmullings22bc2372016-11-02 19:59:35879 InstallCRX(data_dir().AppendASCII("good.crx"), Manifest::EXTERNAL_PREF,
880 INSTALL_NEW, Extension::NO_FLAGS);
David Bertoni9f897c92019-09-20 17:46:35881 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58882 ASSERT_TRUE(extension);
883
treib9afc6212015-10-30 18:49:58884 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36885 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11886 std::make_unique<syncer::FakeSyncChangeProcessor>(),
887 std::make_unique<syncer::SyncErrorFactoryMock>());
asargente48ab752016-03-12 00:59:20888 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:58889
Devlin Cronin6fd1cd62017-12-05 19:13:57890 UninstallExtension(good_crx);
treib9afc6212015-10-30 18:49:58891 EXPECT_TRUE(
892 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
893
894 sync_pb::EntitySpecifics specifics;
895 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
896 sync_pb::ExtensionSpecifics* extension_specifics =
897 app_specifics->mutable_extension();
898 extension_specifics->set_id(good_crx);
899 extension_specifics->set_version("1.0");
900 extension_specifics->set_enabled(true);
901
treib65f103042015-12-03 10:21:36902 SyncChangeList list =
903 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:58904
905 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
906 EXPECT_TRUE(
907 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
908}
909
910TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettings) {
911 InitializeEmptyExtensionService();
912 const Extension* app =
913 PackAndInstallCRX(data_dir().AppendASCII("app"), INSTALL_NEW);
914 ASSERT_TRUE(app);
915 ASSERT_TRUE(app->is_app());
916
treib9afc6212015-10-30 18:49:58917 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36918 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11919 std::make_unique<syncer::FakeSyncChangeProcessor>(),
920 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58921
922 syncer::StringOrdinal initial_ordinal =
923 syncer::StringOrdinal::CreateInitialOrdinal();
924 {
925 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16926 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS);
treib9afc6212015-10-30 18:49:58927 ASSERT_EQ(list.size(), 1U);
928
dchengc963c7142016-04-08 03:55:22929 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58930 ExtensionSyncData::CreateFromSyncData(list[0]);
931 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->app_launch_ordinal()));
932 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
933 }
934
deepak.m14ba69e62015-11-17 05:42:12935 AppSorting* sorting = ExtensionSystem::Get(profile())->app_sorting();
treib9afc6212015-10-30 18:49:58936 sorting->SetAppLaunchOrdinal(app->id(), initial_ordinal.CreateAfter());
937 {
938 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16939 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS);
treib9afc6212015-10-30 18:49:58940 ASSERT_EQ(list.size(), 1U);
941
dchengc963c7142016-04-08 03:55:22942 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58943 ExtensionSyncData::CreateFromSyncData(list[0]);
944 ASSERT_TRUE(app_sync_data.get());
945 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
946 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
947 }
948
949 sorting->SetPageOrdinal(app->id(), initial_ordinal.CreateAfter());
950 {
951 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16952 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS);
treib9afc6212015-10-30 18:49:58953 ASSERT_EQ(list.size(), 1U);
954
dchengc963c7142016-04-08 03:55:22955 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58956 ExtensionSyncData::CreateFromSyncData(list[0]);
957 ASSERT_TRUE(app_sync_data.get());
958 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
959 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->page_ordinal()));
960 }
961}
962
963// TODO (rdevlin.cronin): The OnExtensionMoved() method has been removed from
964// ExtensionService, so this test probably needs a new home. Unfortunately, it
965// relies pretty heavily on things like InitializeExtension[Sync]Service() and
966// PackAndInstallCRX(). When we clean up a bit more, this should move out.
967TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettingsOnExtensionMoved) {
968 InitializeEmptyExtensionService();
969 const size_t kAppCount = 3;
970 const Extension* apps[kAppCount];
971 apps[0] = PackAndInstallCRX(data_dir().AppendASCII("app1"), INSTALL_NEW);
972 apps[1] = PackAndInstallCRX(data_dir().AppendASCII("app2"), INSTALL_NEW);
973 apps[2] = PackAndInstallCRX(data_dir().AppendASCII("app4"), INSTALL_NEW);
974 for (size_t i = 0; i < kAppCount; ++i) {
975 ASSERT_TRUE(apps[i]);
976 ASSERT_TRUE(apps[i]->is_app());
977 }
978
treib9afc6212015-10-30 18:49:58979 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36980 syncer::APPS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22981 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
982 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58983
deepak.m14ba69e62015-11-17 05:42:12984 ExtensionSystem::Get(service()->GetBrowserContext())
treib9afc6212015-10-30 18:49:58985 ->app_sorting()
986 ->OnExtensionMoved(apps[0]->id(), apps[1]->id(), apps[2]->id());
987 {
988 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16989 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS);
treib9afc6212015-10-30 18:49:58990 ASSERT_EQ(list.size(), 3U);
991
dchengc963c7142016-04-08 03:55:22992 std::unique_ptr<ExtensionSyncData> data[kAppCount];
treib9afc6212015-10-30 18:49:58993 for (size_t i = 0; i < kAppCount; ++i) {
994 data[i] = ExtensionSyncData::CreateFromSyncData(list[i]);
995 ASSERT_TRUE(data[i].get());
996 }
997
998 // The sync data is not always in the same order our apps were installed in,
999 // so we do that sorting here so we can make sure the values are changed as
1000 // expected.
1001 syncer::StringOrdinal app_launch_ordinals[kAppCount];
1002 for (size_t i = 0; i < kAppCount; ++i) {
1003 for (size_t j = 0; j < kAppCount; ++j) {
1004 if (apps[i]->id() == data[j]->id())
1005 app_launch_ordinals[i] = data[j]->app_launch_ordinal();
1006 }
1007 }
1008
1009 EXPECT_TRUE(app_launch_ordinals[1].LessThan(app_launch_ordinals[0]));
1010 EXPECT_TRUE(app_launch_ordinals[0].LessThan(app_launch_ordinals[2]));
1011 }
1012}
1013
1014TEST_F(ExtensionServiceSyncTest, GetSyncDataList) {
1015 InitializeEmptyExtensionService();
1016 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1017 InstallCRX(data_dir().AppendASCII("page_action.crx"), INSTALL_NEW);
1018 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
1019 InstallCRX(data_dir().AppendASCII("theme2.crx"), INSTALL_NEW);
1020
treib9afc6212015-10-30 18:49:581021 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361022 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111023 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1024 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581025 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361026 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111027 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1028 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581029
Minh X. Nguyen45479012017-08-18 21:35:361030 service()->DisableExtension(page_action,
1031 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:581032 TerminateExtension(theme2_crx);
1033
treib9afc6212015-10-30 18:49:581034 EXPECT_EQ(
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:161035 0u,
1036 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS).size());
1037 EXPECT_EQ(2u, extension_sync_service()
1038 ->GetAllSyncDataForTesting(syncer::EXTENSIONS)
1039 .size());
treib9afc6212015-10-30 18:49:581040}
1041
1042TEST_F(ExtensionServiceSyncTest, ProcessSyncDataUninstall) {
1043 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581044 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361045 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111046 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1047 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581048
1049 sync_pb::EntitySpecifics specifics;
1050 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1051 ext_specifics->set_id(good_crx);
1052 ext_specifics->set_version("1.0");
treib65f103042015-12-03 10:21:361053
1054 SyncChangeList list =
1055 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:581056
1057 // Should do nothing.
1058 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertoni58c113a2019-08-02 19:53:261059 EXPECT_FALSE(
David Bertonia0b34722019-09-30 20:51:261060 registry()->GetExtensionById(good_crx, ExtensionRegistry::EVERYTHING));
treib9afc6212015-10-30 18:49:581061
1062 // Install the extension.
1063 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
1064 InstallCRX(extension_path, INSTALL_NEW);
David Bertonia0b34722019-09-30 20:51:261065 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581066
1067 // Should uninstall the extension.
1068 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertoni58c113a2019-08-02 19:53:261069 EXPECT_FALSE(
David Bertonia0b34722019-09-30 20:51:261070 registry()->GetExtensionById(good_crx, ExtensionRegistry::EVERYTHING));
treib9afc6212015-10-30 18:49:581071
1072 // Should again do nothing.
1073 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertoni58c113a2019-08-02 19:53:261074 EXPECT_FALSE(
David Bertonia0b34722019-09-30 20:51:261075 registry()->GetExtensionById(good_crx, ExtensionRegistry::EVERYTHING));
treib9afc6212015-10-30 18:49:581076}
1077
1078TEST_F(ExtensionServiceSyncTest, ProcessSyncDataWrongType) {
1079 InitializeEmptyExtensionService();
asargente48ab752016-03-12 00:59:201080 StartSyncing(syncer::EXTENSIONS);
1081 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:581082
1083 // Install the extension.
1084 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
1085 InstallCRX(extension_path, INSTALL_NEW);
David Bertonia0b34722019-09-30 20:51:261086 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581087
1088 sync_pb::EntitySpecifics specifics;
1089 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
1090 sync_pb::ExtensionSpecifics* extension_specifics =
1091 app_specifics->mutable_extension();
1092 extension_specifics->set_id(good_crx);
1093 extension_specifics->set_version(
David Bertoni9f897c92019-09-20 17:46:351094 registry()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581095
1096 {
1097 extension_specifics->set_enabled(true);
treib65f103042015-12-03 10:21:361098
1099 SyncChangeList list =
1100 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:581101
1102 // Should do nothing
1103 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertonia0b34722019-09-30 20:51:261104 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581105 }
1106
1107 {
1108 extension_specifics->set_enabled(false);
treib65f103042015-12-03 10:21:361109
1110 SyncChangeList list =
1111 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581112
1113 // Should again do nothing.
1114 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertonia0b34722019-09-30 20:51:261115 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581116 }
1117}
1118
1119TEST_F(ExtensionServiceSyncTest, ProcessSyncDataSettings) {
1120 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581121 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361122 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111123 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1124 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581125
1126 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1127 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1128 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
treib9afc6212015-10-30 18:49:581129
1130 sync_pb::EntitySpecifics specifics;
1131 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1132 ext_specifics->set_id(good_crx);
1133 ext_specifics->set_version(
David Bertoni9f897c92019-09-20 17:46:351134 registry()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581135 ext_specifics->set_enabled(false);
1136
1137 {
treib65f103042015-12-03 10:21:361138 SyncChangeList list =
1139 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1140
treib9afc6212015-10-30 18:49:581141 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1142 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1143 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
treib9afc6212015-10-30 18:49:581144 }
1145
1146 {
1147 ext_specifics->set_enabled(true);
1148 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361149
1150 SyncChangeList list =
1151 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1152
treib9afc6212015-10-30 18:49:581153 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1154 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1155 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1156 }
1157
1158 {
1159 ext_specifics->set_enabled(false);
1160 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361161
1162 SyncChangeList list =
1163 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1164
treib9afc6212015-10-30 18:49:581165 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1166 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1167 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1168 }
1169
1170 {
1171 ext_specifics->set_enabled(true);
treib65f103042015-12-03 10:21:361172
1173 SyncChangeList list =
1174 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1175
treib9afc6212015-10-30 18:49:581176 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1177 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
treib9afc6212015-10-30 18:49:581178 }
1179
1180 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1181}
1182
1183TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNewExtension) {
1184 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581185 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361186 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111187 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1188 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581189
1190 const base::FilePath path = data_dir().AppendASCII("good.crx");
1191 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1192
1193 struct TestCase {
1194 const char* name; // For failure output only.
1195 bool sync_enabled; // The "enabled" flag coming in from Sync.
1196 // The disable reason(s) coming in from Sync, or -1 for "not set".
1197 int sync_disable_reasons;
1198 // The disable reason(s) that should be set on the installed extension.
1199 // This will usually be the same as |sync_disable_reasons|, but see the
1200 // "Legacy" case.
1201 int expect_disable_reasons;
1202 // Whether the extension's permissions should be auto-granted during
1203 // installation.
1204 bool expect_permissions_granted;
1205 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361206 // Standard case: Extension comes in enabled; permissions should be
1207 // granted
1208 // during installation.
1209 {"Standard", true, 0, 0, true},
1210 // If the extension comes in disabled, its permissions should still be
1211 // granted (the user already approved them on another machine).
1212 {"Disabled", false, extensions::disable_reason::DISABLE_USER_ACTION,
1213 extensions::disable_reason::DISABLE_USER_ACTION, true},
1214 // Legacy case (<M45): No disable reasons come in from Sync (see
1215 // crbug.com/484214). After installation, the reason should be set to
1216 // DISABLE_USER_ACTION (default assumption).
1217 {"Legacy", false, -1, extensions::disable_reason::DISABLE_USER_ACTION,
1218 true},
1219 // If the extension came in disabled due to a permissions increase, then
1220 // the
1221 // user has *not* approved the permissions, and they shouldn't be granted.
1222 // crbug.com/484214
1223 {"PermissionsIncrease", false,
1224 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
1225 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
treib9afc6212015-10-30 18:49:581226 };
1227
1228 for (const TestCase& test_case : test_cases) {
1229 SCOPED_TRACE(test_case.name);
1230
1231 sync_pb::EntitySpecifics specifics;
1232 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1233 ext_specifics->set_id(good_crx);
1234 ext_specifics->set_version(base::Version("1").GetString());
1235 ext_specifics->set_enabled(test_case.sync_enabled);
1236 if (test_case.sync_disable_reasons != -1)
1237 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1238
treib65f103042015-12-03 10:21:361239 SyncChangeList list =
1240 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1241
treib9afc6212015-10-30 18:49:581242 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1243
1244 ASSERT_TRUE(service()->pending_extension_manager()->IsIdPending(good_crx));
1245 UpdateExtension(good_crx, path, test_case.sync_enabled ? ENABLED
1246 : DISABLED);
1247 EXPECT_EQ(test_case.expect_disable_reasons,
1248 prefs->GetDisableReasons(good_crx));
dchengc963c7142016-04-08 03:55:221249 std::unique_ptr<const PermissionSet> permissions =
treib9afc6212015-10-30 18:49:581250 prefs->GetGrantedPermissions(good_crx);
1251 EXPECT_EQ(test_case.expect_permissions_granted, !permissions->IsEmpty());
1252 ASSERT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
Devlin Cronin7b193412017-12-14 03:46:031253 if (test_case.sync_enabled)
1254 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
1255 else
1256 EXPECT_TRUE(registry()->disabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581257
1258 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031259 UninstallExtension(good_crx);
treib9afc6212015-10-30 18:49:581260 }
1261}
1262
1263TEST_F(ExtensionServiceSyncTest, ProcessSyncDataTerminatedExtension) {
1264 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581265 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361266 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111267 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1268 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581269
1270 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1271 TerminateExtension(good_crx);
1272 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1273 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1274
1275 sync_pb::EntitySpecifics specifics;
1276 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1277 ext_specifics->set_id(good_crx);
1278 ext_specifics->set_version(
David Bertoni9f897c92019-09-20 17:46:351279 registry()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581280 ext_specifics->set_enabled(false);
1281 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361282
1283 SyncChangeList list =
1284 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581285
1286 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1287 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1288 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1289
1290 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1291}
1292
1293TEST_F(ExtensionServiceSyncTest, ProcessSyncDataVersionCheck) {
1294 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581295 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361296 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111297 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1298 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581299
1300 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1301 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1302 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1303
1304 sync_pb::EntitySpecifics specifics;
1305 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1306 ext_specifics->set_id(good_crx);
1307 ext_specifics->set_enabled(true);
1308
1309 const base::Version installed_version =
David Bertoni9f897c92019-09-20 17:46:351310 registry()->GetInstalledExtension(good_crx)->version();
treib9afc6212015-10-30 18:49:581311
1312 {
1313 ext_specifics->set_version(installed_version.GetString());
treib65f103042015-12-03 10:21:361314
1315 SyncChangeList list =
1316 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581317
1318 // Should do nothing if extension version == sync version.
1319 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1320 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1321 // Make sure the version we'll send back to sync didn't change.
1322 syncer::SyncDataList data =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:161323 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581324 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221325 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581326 ExtensionSyncData::CreateFromSyncData(data[0]);
1327 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001328 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581329 }
1330
1331 // Should do nothing if extension version > sync version.
1332 {
1333 ext_specifics->set_version("0.0.0.0");
treib65f103042015-12-03 10:21:361334
1335 SyncChangeList list =
1336 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581337
1338 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1339 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1340 // Make sure the version we'll send back to sync didn't change.
1341 syncer::SyncDataList data =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:161342 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581343 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221344 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581345 ExtensionSyncData::CreateFromSyncData(data[0]);
1346 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001347 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581348 }
1349
1350 // Should kick off an update if extension version < sync version.
1351 {
1352 const base::Version new_version("9.9.9.9");
1353 ext_specifics->set_version(new_version.GetString());
treib65f103042015-12-03 10:21:361354
1355 SyncChangeList list =
1356 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581357
1358 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1359 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1360 // Make sure that we'll send the NEW version back to sync, even though we
1361 // haven't actually updated yet. This is to prevent the data in sync from
1362 // flip-flopping back and forth until all clients are up to date.
1363 syncer::SyncDataList data =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:161364 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581365 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221366 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581367 ExtensionSyncData::CreateFromSyncData(data[0]);
1368 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001369 EXPECT_EQ(new_version, extension_data->version());
treib9afc6212015-10-30 18:49:581370 }
1371
1372 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1373}
1374
1375TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNotInstalled) {
1376 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581377 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361378 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111379 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1380 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581381
1382 sync_pb::EntitySpecifics specifics;
1383 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1384 ext_specifics->set_id(good_crx);
1385 ext_specifics->set_enabled(false);
1386 ext_specifics->set_incognito_enabled(true);
1387 ext_specifics->set_update_url("http://www.google.com/");
1388 ext_specifics->set_version("1.2.3.4");
treib65f103042015-12-03 10:21:361389
1390 SyncChangeList list =
1391 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581392
1393 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1394 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1395 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1396 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1397 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1398 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1399
1400 const extensions::PendingExtensionInfo* info;
1401 EXPECT_TRUE(
1402 (info = service()->pending_extension_manager()->GetById(good_crx)));
1403 EXPECT_EQ(ext_specifics->update_url(), info->update_url().spec());
1404 EXPECT_TRUE(info->is_from_sync());
1405 EXPECT_EQ(Manifest::INTERNAL, info->install_source());
1406 // TODO(akalin): Figure out a way to test |info.ShouldAllowInstall()|.
1407}
1408
1409TEST_F(ExtensionServiceSyncTest, ProcessSyncDataEnableDisable) {
1410 InitializeEmptyExtensionService();
1411 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361412 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111413 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1414 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581415
1416 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1417
1418 struct TestCase {
1419 const char* name; // For failure output only.
1420 // Set of disable reasons before any Sync data comes in. If this is != 0,
1421 // the extension is disabled.
1422 int previous_disable_reasons;
1423 bool sync_enable; // The enabled flag coming in from Sync.
1424 // The disable reason(s) coming in from Sync, or -1 for "not set".
1425 int sync_disable_reasons;
1426 // The expected set of disable reasons after processing the Sync update. The
1427 // extension should be disabled iff this is != 0.
1428 int expect_disable_reasons;
1429 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361430 {"NopEnable", 0, true, 0, 0},
1431 {"NopDisable", extensions::disable_reason::DISABLE_USER_ACTION, false,
1432 extensions::disable_reason::DISABLE_USER_ACTION,
1433 extensions::disable_reason::DISABLE_USER_ACTION},
1434 {"Enable", extensions::disable_reason::DISABLE_USER_ACTION, true, 0, 0},
1435 {"Disable", 0, false, extensions::disable_reason::DISABLE_USER_ACTION,
1436 extensions::disable_reason::DISABLE_USER_ACTION},
1437 {"AddDisableReason", extensions::disable_reason::DISABLE_REMOTE_INSTALL,
1438 false,
1439 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1440 extensions::disable_reason::DISABLE_USER_ACTION,
1441 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1442 extensions::disable_reason::DISABLE_USER_ACTION},
1443 {"RemoveDisableReason",
1444 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1445 extensions::disable_reason::DISABLE_USER_ACTION,
1446 false, extensions::disable_reason::DISABLE_USER_ACTION,
1447 extensions::disable_reason::DISABLE_USER_ACTION},
1448 {"PreserveLocalDisableReason", extensions::disable_reason::DISABLE_RELOAD,
1449 true, 0, extensions::disable_reason::DISABLE_RELOAD},
1450 {"PreserveOnlyLocalDisableReason",
1451 extensions::disable_reason::DISABLE_USER_ACTION |
1452 extensions::disable_reason::DISABLE_RELOAD,
1453 true, 0, extensions::disable_reason::DISABLE_RELOAD},
treib29e1b9b12015-11-11 08:50:561454
Minh X. Nguyen45479012017-08-18 21:35:361455 // Interaction with Chrome clients <=M44, which don't sync disable_reasons
1456 // at all (any existing reasons are preserved).
1457 {"M44Enable", extensions::disable_reason::DISABLE_USER_ACTION, true, -1,
1458 0},
1459 // An M44 client enables an extension that had been disabled on a new
1460 // client. The disable reasons are still be there, but should be ignored.
1461 {"M44ReEnable", extensions::disable_reason::DISABLE_USER_ACTION, true,
1462 extensions::disable_reason::DISABLE_USER_ACTION, 0},
1463 {"M44Disable", 0, false, -1,
1464 extensions::disable_reason::DISABLE_USER_ACTION},
1465 {"M44ReDisable", 0, false, 0,
1466 extensions::disable_reason::DISABLE_USER_ACTION},
1467 {"M44AlreadyDisabledByUser",
1468 extensions::disable_reason::DISABLE_USER_ACTION, false, -1,
1469 extensions::disable_reason::DISABLE_USER_ACTION},
1470 {"M44AlreadyDisabledWithOtherReason",
1471 extensions::disable_reason::DISABLE_REMOTE_INSTALL, false, -1,
1472 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1473 extensions::disable_reason::DISABLE_USER_ACTION},
treib9afc6212015-10-30 18:49:581474 };
1475
1476 for (const TestCase& test_case : test_cases) {
1477 SCOPED_TRACE(test_case.name);
1478
1479 std::string id;
1480 std::string version;
1481 // Don't keep |extension| around longer than necessary.
1482 {
1483 const Extension* extension =
1484 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1485 // The extension should now be installed and enabled.
1486 ASSERT_TRUE(extension);
1487 id = extension->id();
1488 version = extension->VersionString();
1489 }
1490 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1491
1492 // Disable it if the test case says so.
1493 if (test_case.previous_disable_reasons) {
1494 service()->DisableExtension(id, test_case.previous_disable_reasons);
1495 ASSERT_TRUE(registry()->disabled_extensions().Contains(id));
1496 }
1497
1498 // Now a sync update comes in.
1499 sync_pb::EntitySpecifics specifics;
1500 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1501 ext_specifics->set_id(id);
1502 ext_specifics->set_enabled(test_case.sync_enable);
1503 ext_specifics->set_version(version);
1504 if (test_case.sync_disable_reasons != -1)
1505 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1506
treib65f103042015-12-03 10:21:361507 SyncChangeList list =
1508 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1509
treib9afc6212015-10-30 18:49:581510 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1511
1512 // Check expectations.
1513 const bool expect_enabled = !test_case.expect_disable_reasons;
1514 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1515 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
1516
1517 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031518 UninstallExtension(id);
treib9afc6212015-10-30 18:49:581519 }
1520}
1521
Konstantin Ganenkoae1129c2017-09-15 16:28:591522class ExtensionServiceSyncCustomGalleryTest : public ExtensionServiceSyncTest {
1523 public:
1524 void SetUp() override {
1525 ExtensionServiceSyncTest::SetUp();
rdevlin.cronin2f1ed4c2017-06-13 16:22:131526
Konstantin Ganenkoae1129c2017-09-15 16:28:591527 // This is the update URL specified in the permissions test extension.
1528 // Setting it here is necessary to make the extension considered syncable.
1529 extension_test_util::SetGalleryUpdateURL(
1530 GURL("http://localhost/autoupdate/updates.xml"));
1531 }
1532};
1533
1534TEST_F(ExtensionServiceSyncCustomGalleryTest, ProcessSyncDataDeferredEnable) {
treib9afc6212015-10-30 18:49:581535 InitializeEmptyExtensionService();
1536 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361537 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111538 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1539 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581540
1541 base::FilePath base_path = data_dir().AppendASCII("permissions_increase");
1542 base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1543
1544 base::FilePath path = base_path.AppendASCII("v1");
1545 const Extension* extension = PackAndInstallCRX(path, pem_path, INSTALL_NEW);
1546 // The extension must now be installed and enabled.
1547 ASSERT_TRUE(extension);
1548 ASSERT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
1549
1550 // Save the id, as the extension object will be destroyed during updating.
1551 std::string id = extension->id();
1552
1553 // Update to a new version with increased permissions.
1554 path = base_path.AppendASCII("v2");
1555 PackCRXAndUpdateExtension(id, path, pem_path, DISABLED);
1556
1557 // Now a sync update comes in, telling us to re-enable a *newer* version.
1558 sync_pb::EntitySpecifics specifics;
1559 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1560 ext_specifics->set_id(id);
1561 ext_specifics->set_version("3");
1562 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:361563 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:581564
treib65f103042015-12-03 10:21:361565 SyncChangeList list =
1566 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1567
treib9afc6212015-10-30 18:49:581568 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1569
1570 // Since the version didn't match, the extension should still be disabled.
1571 EXPECT_TRUE(registry()->disabled_extensions().Contains(id));
1572
1573 // After we update to the matching version, the extension should get enabled.
1574 path = base_path.AppendASCII("v3");
1575 PackCRXAndUpdateExtension(id, path, pem_path, ENABLED);
1576}
1577
atuchin2eb18eb2017-03-02 07:22:151578TEST_F(ExtensionServiceSyncCustomGalleryTest,
1579 ProcessSyncDataPermissionApproval) {
treib9afc6212015-10-30 18:49:581580 InitializeEmptyExtensionService();
1581 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361582 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111583 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1584 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581585
1586 const base::FilePath base_path =
1587 data_dir().AppendASCII("permissions_increase");
1588 const base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1589 const base::FilePath path_v1 = base_path.AppendASCII("v1");
1590 const base::FilePath path_v2 = base_path.AppendASCII("v2");
1591
1592 base::ScopedTempDir crx_dir;
1593 ASSERT_TRUE(crx_dir.CreateUniqueTempDir());
vabr9142fe22016-09-08 13:19:221594 const base::FilePath crx_path_v1 = crx_dir.GetPath().AppendASCII("temp1.crx");
treib9afc6212015-10-30 18:49:581595 PackCRX(path_v1, pem_path, crx_path_v1);
vabr9142fe22016-09-08 13:19:221596 const base::FilePath crx_path_v2 = crx_dir.GetPath().AppendASCII("temp2.crx");
treib9afc6212015-10-30 18:49:581597 PackCRX(path_v2, pem_path, crx_path_v2);
1598
1599 const std::string v1("1");
1600 const std::string v2("2");
1601
1602 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1603
1604 struct TestCase {
1605 const char* name; // For failure output only.
1606 const std::string& sync_version; // The version coming in from Sync.
1607 // The disable reason(s) coming in from Sync, or -1 for "not set".
1608 int sync_disable_reasons;
1609 // The expected set of disable reasons after processing the Sync update. The
1610 // extension should be enabled iff this is 0.
1611 int expect_disable_reasons;
1612 // Whether the extension's permissions should be auto-granted.
1613 bool expect_permissions_granted;
1614 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361615 // Sync tells us to re-enable an older version. No permissions should be
1616 // granted, since we can't be sure if the user actually approved the right
1617 // set of permissions.
1618 {"OldVersion", v1, 0,
1619 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
1620 // Legacy case: Sync tells us to re-enable the extension, but doesn't
1621 // specify disable reasons. No permissions should be granted.
1622 {"Legacy", v2, -1,
1623 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
1624 // Sync tells us to re-enable the extension and explicitly removes the
1625 // disable reasons. Now the extension should have its permissions granted.
1626 {"GrantPermissions", v2, 0, extensions::disable_reason::DISABLE_NONE,
1627 true},
treib9afc6212015-10-30 18:49:581628 };
1629
1630 for (const TestCase& test_case : test_cases) {
1631 SCOPED_TRACE(test_case.name);
1632
1633 std::string id;
1634 // Don't keep |extension| around longer than necessary (it'll be destroyed
1635 // during updating).
1636 {
1637 const Extension* extension = InstallCRX(crx_path_v1, INSTALL_NEW);
1638 // The extension should now be installed and enabled.
1639 ASSERT_TRUE(extension);
1640 ASSERT_EQ(v1, extension->VersionString());
1641 id = extension->id();
1642 }
1643 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1644
dchengc963c7142016-04-08 03:55:221645 std::unique_ptr<const PermissionSet> granted_permissions_v1 =
treib9afc6212015-10-30 18:49:581646 prefs->GetGrantedPermissions(id);
1647
1648 // Update to a new version with increased permissions.
1649 UpdateExtension(id, crx_path_v2, DISABLED);
1650
1651 // Now the extension should be disabled due to a permissions increase.
1652 {
1653 const Extension* extension =
1654 registry()->disabled_extensions().GetByID(id);
1655 ASSERT_TRUE(extension);
1656 ASSERT_EQ(v2, extension->VersionString());
1657 }
1658 ASSERT_TRUE(prefs->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:361659 id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE));
treib9afc6212015-10-30 18:49:581660
1661 // No new permissions should have been granted.
dchengc963c7142016-04-08 03:55:221662 std::unique_ptr<const PermissionSet> granted_permissions_v2 =
treib9afc6212015-10-30 18:49:581663 prefs->GetGrantedPermissions(id);
1664 ASSERT_EQ(*granted_permissions_v1, *granted_permissions_v2);
1665
1666 // Now a sync update comes in.
1667 sync_pb::EntitySpecifics specifics;
1668 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1669 ext_specifics->set_id(id);
1670 ext_specifics->set_enabled(true);
1671 ext_specifics->set_version(test_case.sync_version);
1672 if (test_case.sync_disable_reasons != -1)
1673 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1674
treib65f103042015-12-03 10:21:361675 SyncChangeList list =
1676 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1677
treib9afc6212015-10-30 18:49:581678 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1679
1680 // Check expectations.
1681 const bool expect_enabled = !test_case.expect_disable_reasons;
1682 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1683 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
dchengc963c7142016-04-08 03:55:221684 std::unique_ptr<const PermissionSet> granted_permissions =
treib9afc6212015-10-30 18:49:581685 prefs->GetGrantedPermissions(id);
1686 if (test_case.expect_permissions_granted) {
dchengc963c7142016-04-08 03:55:221687 std::unique_ptr<const PermissionSet> active_permissions =
treib9afc6212015-10-30 18:49:581688 prefs->GetActivePermissions(id);
1689 EXPECT_EQ(*granted_permissions, *active_permissions);
1690 } else {
1691 EXPECT_EQ(*granted_permissions, *granted_permissions_v1);
1692 }
1693
1694 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031695 UninstallExtension(id);
treib9afc6212015-10-30 18:49:581696 }
1697}
1698
treib227b2582015-12-09 09:28:261699// Regression test for crbug.com/558299
1700TEST_F(ExtensionServiceSyncTest, DontSyncThemes) {
1701 InitializeEmptyExtensionService();
1702
1703 // The user has enabled sync.
Marc Treib9948a682018-11-20 08:01:371704 ProfileSyncServiceFactory::GetForProfile(profile())
1705 ->GetUserSettings()
Tanmoy Mollik0960d702019-09-11 15:14:471706 ->SetFirstSetupComplete(kSetSourceFromTest);
treib227b2582015-12-09 09:28:261707 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
1708 extension_sync_service();
1709
1710 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:021711 ASSERT_TRUE(extension_system()->is_ready());
treib227b2582015-12-09 09:28:261712
1713 syncer::FakeSyncChangeProcessor* processor =
1714 new syncer::FakeSyncChangeProcessor;
1715 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:221716 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
1717 base::WrapUnique(new syncer::SyncErrorFactoryMock));
treib227b2582015-12-09 09:28:261718
1719 processor->changes().clear();
1720
1721 // Sanity check: Installing an extension should result in a sync change.
1722 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1723 EXPECT_EQ(1u, processor->changes().size());
1724
1725 processor->changes().clear();
1726
1727 // Installing a theme should not result in a sync change (themes are handled
1728 // separately by ThemeSyncableService).
1729 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
Evan Stade46d716d2017-06-02 20:50:091730 content::WindowedNotificationObserver theme_change_observer(
1731 chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
1732 content::Source<ThemeService>(
1733 ThemeServiceFactory::GetForProfile(profile())));
1734 theme_change_observer.Wait();
treib227b2582015-12-09 09:28:261735 EXPECT_TRUE(processor->changes().empty());
1736}
1737
Toby Huang63a8d712019-11-27 20:07:321738// Tests sync behavior in the case of an item that starts out as an app and gets
1739// updated to become an extension.
asargente48ab752016-03-12 00:59:201740TEST_F(ExtensionServiceSyncTest, AppToExtension) {
1741 InitializeEmptyExtensionService();
1742 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:021743 ASSERT_TRUE(extension_system()->is_ready());
asargente48ab752016-03-12 00:59:201744
1745 // Install v1, which is an app.
1746 const Extension* v1 =
1747 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v1.crx"),
1748 INSTALL_NEW);
1749 EXPECT_TRUE(v1->is_app());
1750 EXPECT_FALSE(v1->is_extension());
1751 std::string id = v1->id();
1752
1753 StatefulChangeProcessor extensions_processor(syncer::ModelType::EXTENSIONS);
1754 StatefulChangeProcessor apps_processor(syncer::ModelType::APPS);
1755 extension_sync_service()->MergeDataAndStartSyncing(
1756 syncer::EXTENSIONS, syncer::SyncDataList(),
1757 extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221758 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201759 extension_sync_service()->MergeDataAndStartSyncing(
1760 syncer::APPS, syncer::SyncDataList(), apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221761 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201762
1763 // Check the app/extension change processors to be sure the right data was
1764 // added.
1765 EXPECT_TRUE(extensions_processor.changes().empty());
1766 EXPECT_TRUE(extensions_processor.data().empty());
1767 EXPECT_EQ(1u, apps_processor.data().size());
1768 ASSERT_EQ(1u, apps_processor.changes().size());
1769 const SyncChange& app_change = apps_processor.changes()[0];
1770 EXPECT_EQ(SyncChange::ACTION_ADD, app_change.change_type());
dchengc963c7142016-04-08 03:55:221771 std::unique_ptr<ExtensionSyncData> app_data =
asargente48ab752016-03-12 00:59:201772 ExtensionSyncData::CreateFromSyncData(app_change.sync_data());
1773 EXPECT_TRUE(app_data->is_app());
1774 EXPECT_EQ(id, app_data->id());
Devlin Cronin03bf2d22017-12-20 08:21:051775 EXPECT_EQ(v1->version(), app_data->version());
asargente48ab752016-03-12 00:59:201776
1777 // Update the app to v2, which is an extension.
1778 const Extension* v2 =
1779 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v2.crx"),
1780 INSTALL_UPDATED);
1781 EXPECT_FALSE(v2->is_app());
1782 EXPECT_TRUE(v2->is_extension());
1783 EXPECT_EQ(id, v2->id());
1784
1785 // Make sure we saw an extension item added.
1786 ASSERT_EQ(1u, extensions_processor.changes().size());
1787 const SyncChange& extension_change = extensions_processor.changes()[0];
1788 EXPECT_EQ(SyncChange::ACTION_ADD, extension_change.change_type());
dchengc963c7142016-04-08 03:55:221789 std::unique_ptr<ExtensionSyncData> extension_data =
asargente48ab752016-03-12 00:59:201790 ExtensionSyncData::CreateFromSyncData(extension_change.sync_data());
1791 EXPECT_FALSE(extension_data->is_app());
1792 EXPECT_EQ(id, extension_data->id());
Devlin Cronin03bf2d22017-12-20 08:21:051793 EXPECT_EQ(v2->version(), extension_data->version());
asargente48ab752016-03-12 00:59:201794
1795 // Get the current data from the change processors to use as the input to
1796 // the following call to MergeDataAndStartSyncing. This simulates what should
1797 // happen with sync.
1798 syncer::SyncDataList extensions_data =
1799 extensions_processor.GetAllSyncData(syncer::EXTENSIONS);
1800 syncer::SyncDataList apps_data = apps_processor.GetAllSyncData(syncer::APPS);
1801
1802 // Stop syncing, then start again.
1803 extension_sync_service()->StopSyncing(syncer::EXTENSIONS);
1804 extension_sync_service()->StopSyncing(syncer::APPS);
1805 extension_sync_service()->MergeDataAndStartSyncing(
1806 syncer::EXTENSIONS, extensions_data, extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221807 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201808 extension_sync_service()->MergeDataAndStartSyncing(
1809 syncer::APPS, apps_data, apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221810 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201811
1812 // Make sure we saw an app item deleted.
1813 bool found_delete = false;
1814 for (const auto& change : apps_processor.changes()) {
1815 if (change.change_type() == SyncChange::ACTION_DELETE) {
dchengc963c7142016-04-08 03:55:221816 std::unique_ptr<ExtensionSyncData> data =
asargente48ab752016-03-12 00:59:201817 ExtensionSyncData::CreateFromSyncChange(change);
1818 if (data->id() == id) {
1819 found_delete = true;
1820 break;
1821 }
1822 }
1823 }
1824 EXPECT_TRUE(found_delete);
1825
1826 // Make sure there is one extension, and there are no more apps.
1827 EXPECT_EQ(1u, extensions_processor.data().size());
1828 EXPECT_TRUE(apps_processor.data().empty());
1829}
proberge901ecab2017-08-31 19:24:281830
[email protected]950f2952020-07-10 03:35:501831class BlocklistedExtensionSyncServiceTest : public ExtensionServiceSyncTest {
proberge901ecab2017-08-31 19:24:281832 public:
[email protected]950f2952020-07-10 03:35:501833 BlocklistedExtensionSyncServiceTest() {}
proberge901ecab2017-08-31 19:24:281834
1835 void SetUp() override {
1836 ExtensionServiceSyncTest::SetUp();
1837
1838 InitializeEmptyExtensionService();
1839
1840 // Enable sync.
Marc Treib5a78e9c2019-02-19 16:47:011841 syncer::SyncService* sync_service =
proberge901ecab2017-08-31 19:24:281842 ProfileSyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:471843 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
proberge901ecab2017-08-31 19:24:281844
[email protected]950f2952020-07-10 03:35:501845 test_blocklist_.Attach(service()->blocklist_);
proberge901ecab2017-08-31 19:24:281846 service()->Init();
1847
1848 // Load up a simple extension.
1849 extensions::ChromeTestExtensionLoader extension_loader(profile());
1850 extension_loader.set_pack_extension(true);
1851 extension_ = extension_loader.LoadExtension(
1852 data_dir().AppendASCII("simple_with_file"));
1853 ASSERT_TRUE(extension_);
1854 extension_id_ = extension_->id();
1855 ASSERT_TRUE(registry()->enabled_extensions().GetByID(extension_id_));
1856
1857 {
Jinho Bangb5216cec2018-01-17 19:43:111858 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
proberge901ecab2017-08-31 19:24:281859 processor_raw_ = processor.get();
1860 extension_sync_service()->MergeDataAndStartSyncing(
1861 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:111862 std::make_unique<syncer::SyncErrorFactoryMock>());
proberge901ecab2017-08-31 19:24:281863 }
1864 processor_raw_->changes().clear();
1865 }
1866
[email protected]950f2952020-07-10 03:35:501867 void ForceBlocklistUpdate() {
1868 service()->OnBlocklistUpdated();
Gabriel Charette01507a22017-09-27 21:30:081869 content::RunAllTasksUntilIdle();
proberge901ecab2017-08-31 19:24:281870 }
1871
1872 syncer::FakeSyncChangeProcessor* processor() { return processor_raw_; }
1873
1874 const Extension* extension() { return extension_.get(); }
1875
1876 std::string& extension_id() { return extension_id_; }
1877
[email protected]950f2952020-07-10 03:35:501878 extensions::TestBlocklist& test_blocklist() { return test_blocklist_; }
proberge901ecab2017-08-31 19:24:281879
1880 private:
1881 syncer::FakeSyncChangeProcessor* processor_raw_;
1882 scoped_refptr<const Extension> extension_;
1883 std::string extension_id_;
[email protected]950f2952020-07-10 03:35:501884 extensions::TestBlocklist test_blocklist_;
proberge901ecab2017-08-31 19:24:281885
[email protected]950f2952020-07-10 03:35:501886 DISALLOW_COPY_AND_ASSIGN(BlocklistedExtensionSyncServiceTest);
proberge901ecab2017-08-31 19:24:281887};
1888
[email protected]950f2952020-07-10 03:35:501889// Test that sync cannot enable blocklisted extensions.
1890TEST_F(BlocklistedExtensionSyncServiceTest, SyncBlocklistedExtension) {
proberge901ecab2017-08-31 19:24:281891 std::string& extension_id = this->extension_id();
1892
[email protected]950f2952020-07-10 03:35:501893 // Blocklist the extension.
1894 test_blocklist().SetBlocklistState(extension_id,
[email protected]321b9292020-06-26 01:20:461895 extensions::BLOCKLISTED_MALWARE, true);
[email protected]950f2952020-07-10 03:35:501896 ForceBlocklistUpdate();
proberge901ecab2017-08-31 19:24:281897
1898 // Try enabling the extension via sync.
1899 EnableExtensionFromSync(*extension());
1900
1901 // The extension should not be enabled.
1902 EXPECT_FALSE(registry()->enabled_extensions().GetByID(extension_id));
1903 EXPECT_TRUE(processor()->changes().empty());
1904}
1905
1906// Test that some greylisted extensions can be enabled through sync.
[email protected]950f2952020-07-10 03:35:501907TEST_F(BlocklistedExtensionSyncServiceTest, SyncAllowedGreylistedExtension) {
proberge901ecab2017-08-31 19:24:281908 std::string& extension_id = this->extension_id();
1909
1910 // Greylist the extension.
[email protected]950f2952020-07-10 03:35:501911 test_blocklist().SetBlocklistState(
[email protected]321b9292020-06-26 01:20:461912 extension_id, extensions::BLOCKLISTED_POTENTIALLY_UNWANTED, true);
[email protected]950f2952020-07-10 03:35:501913 ForceBlocklistUpdate();
proberge901ecab2017-08-31 19:24:281914
1915 EXPECT_FALSE(registry()->enabled_extensions().GetByID(extension_id));
1916 {
1917 ASSERT_EQ(1u, processor()->changes().size());
1918 const SyncChange& change = processor()->changes()[0];
1919 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
1920 std::unique_ptr<ExtensionSyncData> data =
1921 ExtensionSyncData::CreateFromSyncData(change.sync_data());
1922 EXPECT_EQ(extension_id, data->id());
1923 EXPECT_EQ(extensions::disable_reason::DISABLE_GREYLIST,
1924 data->disable_reasons());
1925 EXPECT_FALSE(data->enabled());
1926 }
1927 processor()->changes().clear();
1928
1929 // Manually re-enabling the extension should work.
1930 service()->EnableExtension(extension_id);
1931 EXPECT_TRUE(registry()->enabled_extensions().GetByID(extension_id));
1932 {
1933 ASSERT_EQ(1u, processor()->changes().size());
1934 const SyncChange& change = processor()->changes()[0];
1935 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
1936 std::unique_ptr<ExtensionSyncData> data =
1937 ExtensionSyncData::CreateFromSyncData(change.sync_data());
1938 EXPECT_EQ(extension_id, data->id());
1939 EXPECT_EQ(0, data->disable_reasons());
1940 EXPECT_TRUE(data->enabled());
1941 }
1942 processor()->changes().clear();
1943}