blob: ab4fbc87caec500bf22b3743a77b920477d233c8 [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"
rdevlin.cronin2f1ed4c2017-06-13 16:22:1317#include "chrome/browser/extensions/chrome_test_extension_loader.h"
treib9afc6212015-10-30 18:49:5818#include "chrome/browser/extensions/component_loader.h"
19#include "chrome/browser/extensions/extension_service.h"
20#include "chrome/browser/extensions/extension_service_test_with_install.h"
21#include "chrome/browser/extensions/extension_sync_data.h"
22#include "chrome/browser/extensions/extension_sync_service.h"
23#include "chrome/browser/extensions/extension_util.h"
[email protected]b55906912020-07-07 10:39:4024#include "chrome/browser/extensions/test_blocklist.h"
treib9afc6212015-10-30 18:49:5825#include "chrome/browser/extensions/updater/extension_updater.h"
Hans Wennborg9208992ba2019-10-14 14:02:4926#include "chrome/browser/profiles/profile_key.h"
Victor Hugo Vianna Silvaff4e5f6e2021-06-01 20:12:1427#include "chrome/browser/sync/sync_service_factory.h"
Tommy Steimel2dffd3c2021-03-10 23:27:2128#include "chrome/browser/themes/test/theme_service_changed_waiter.h"
Evan Stade46d716d2017-06-02 20:50:0929#include "chrome/browser/themes/theme_service.h"
30#include "chrome/browser/themes/theme_service_factory.h"
treib9afc6212015-10-30 18:49:5831#include "chrome/common/chrome_constants.h"
Konstantin Ganenkoae1129c2017-09-15 16:28:5932#include "chrome/common/extensions/extension_test_util.h"
treib9afc6212015-10-30 18:49:5833#include "chrome/common/extensions/sync_helper.h"
34#include "chrome/test/base/testing_profile.h"
rdevlin.cronin738501d2015-11-05 21:51:3635#include "components/crx_file/id_util.h"
Marc Treib2435e772019-02-20 12:25:3836#include "components/sync/driver/sync_service.h"
37#include "components/sync/driver/sync_user_settings.h"
skym71603842016-10-10 18:17:3138#include "components/sync/model/sync_data.h"
Victor Hugo Vianna Silvae92e3002021-07-26 14:38:5039#include "components/sync/protocol/app_specifics.pb.h"
40#include "components/sync/protocol/entity_specifics.pb.h"
41#include "components/sync/protocol/extension_specifics.pb.h"
Rushan Suleymanov633f4a0a2020-10-23 11:18:4342#include "components/sync/test/model/fake_sync_change_processor.h"
43#include "components/sync/test/model/sync_change_processor_wrapper_for_test.h"
44#include "components/sync/test/model/sync_error_factory_mock.h"
treibb6af28cd2015-12-01 11:19:4645#include "components/variations/variations_associated_data.h"
Kinuko Yasuda6ec805a2019-07-29 06:12:5646#include "content/public/browser/browser_context.h"
47#include "content/public/browser/storage_partition.h"
treib9afc6212015-10-30 18:49:5848#include "extensions/browser/app_sorting.h"
Devlin Croninbffe949eb2018-01-12 03:03:4049#include "extensions/browser/disable_reason.h"
treib9afc6212015-10-30 18:49:5850#include "extensions/browser/extension_prefs.h"
51#include "extensions/browser/extension_registry.h"
52#include "extensions/browser/extension_system.h"
karandeepb810e33402017-04-05 23:41:2253#include "extensions/browser/extension_util.h"
treib9afc6212015-10-30 18:49:5854#include "extensions/browser/management_policy.h"
rdevlin.cronin738501d2015-11-05 21:51:3655#include "extensions/common/extension_builder.h"
Swapnilf6f2f1d2021-01-14 18:50:4356#include "extensions/common/extension_urls.h"
treib9afc6212015-10-30 18:49:5857#include "extensions/common/manifest_url_handlers.h"
Gyuyoung Kim5626c752021-03-18 22:58:1158#include "extensions/common/mojom/manifest.mojom-shared.h"
treib9afc6212015-10-30 18:49:5859#include "extensions/common/permissions/permission_set.h"
treib9afc6212015-10-30 18:49:5860
treib9afc6212015-10-30 18:49:5861using extensions::AppSorting;
62using extensions::Extension;
63using extensions::ExtensionPrefs;
David Bertoni58c113a2019-08-02 19:53:2664using extensions::ExtensionRegistry;
treib9afc6212015-10-30 18:49:5865using extensions::ExtensionSyncData;
66using extensions::ExtensionSystem;
67using extensions::Manifest;
68using extensions::PermissionSet;
Gyuyoung Kim5626c752021-03-18 22:58:1169using extensions::mojom::ManifestLocation;
treib65f103042015-12-03 10:21:3670using syncer::SyncChange;
71using syncer::SyncChangeList;
mamire9609642016-06-28 22:17:5472using testing::Mock;
treib65f103042015-12-03 10:21:3673
74namespace {
treib9afc6212015-10-30 18:49:5875
76const char good0[] = "behllobkkfkfnphdnhnkndlbkcpglgmj";
77const char good2[] = "bjafgdebaacbbbecmhlhpofkepfkgcpa";
78const char good_crx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
79const char page_action[] = "obcimlgaoabeegjmmpldobjndiealpln";
Joshua Pawlickif2f37f32018-11-05 21:40:5680const char theme2_crx[] = "ibcijncamhmjjdodjamgiipcgnnaeagd";
Tanmoy Mollik0960d702019-09-11 15:14:4781const syncer::SyncFirstSetupCompleteSource kSetSourceFromTest =
82 syncer::SyncFirstSetupCompleteSource::BASIC_FLOW;
treib9afc6212015-10-30 18:49:5883
rdevlin.cronin2f1ed4c2017-06-13 16:22:1384ExtensionSyncData GetDisableSyncData(const Extension& extension,
85 int disable_reasons) {
86 bool enabled = false;
87 bool incognito_enabled = false;
88 bool remote_install = false;
rdevlin.cronin2f1ed4c2017-06-13 16:22:1389 return ExtensionSyncData(extension, enabled, disable_reasons,
Swapnilf6f2f1d2021-01-14 18:50:4390 incognito_enabled, remote_install, GURL());
rdevlin.cronin2f1ed4c2017-06-13 16:22:1391}
92
93ExtensionSyncData GetEnableSyncData(const Extension& extension) {
94 bool enabled = true;
95 bool incognito_enabled = false;
96 bool remote_install = false;
Toby Huangd7caf252019-10-30 01:11:1697 return ExtensionSyncData(extension, enabled,
98 extensions::disable_reason::DISABLE_NONE,
Swapnilf6f2f1d2021-01-14 18:50:4399 incognito_enabled, remote_install, GURL());
rdevlin.cronin2f1ed4c2017-06-13 16:22:13100}
101
treib65f103042015-12-03 10:21:36102SyncChangeList MakeSyncChangeList(const std::string& id,
103 const sync_pb::EntitySpecifics& specifics,
104 SyncChange::SyncChangeType change_type) {
105 syncer::SyncData sync_data =
106 syncer::SyncData::CreateLocalData(id, "Name", specifics);
107 return SyncChangeList(1, SyncChange(FROM_HERE, change_type, sync_data));
108}
109
asargente48ab752016-03-12 00:59:20110// This is a FakeSyncChangeProcessor specialization that maintains a store of
111// SyncData items in the superclass' data_ member variable, treating it like a
112// map keyed by the extension id from the SyncData. Each instance of this class
113// should only be used for one model type (which should be either extensions or
114// apps) to match how the real sync system handles things.
115class StatefulChangeProcessor : public syncer::FakeSyncChangeProcessor {
116 public:
117 explicit StatefulChangeProcessor(syncer::ModelType expected_type)
118 : expected_type_(expected_type) {
119 EXPECT_TRUE(expected_type == syncer::ModelType::EXTENSIONS ||
120 expected_type == syncer::ModelType::APPS);
121 }
122
123 ~StatefulChangeProcessor() override {}
124
125 // We let our parent class, FakeSyncChangeProcessor, handle saving the
126 // changes for us, but in addition we "apply" these changes by treating
127 // the FakeSyncChangeProcessor's SyncDataList as a map keyed by extension
128 // id.
Anton Bikineev46bbb972021-05-15 17:53:53129 absl::optional<syncer::ModelError> ProcessSyncChanges(
Brett Wilsone1a70422017-09-12 05:10:09130 const base::Location& from_here,
asargente48ab752016-03-12 00:59:20131 const syncer::SyncChangeList& change_list) override {
132 syncer::FakeSyncChangeProcessor::ProcessSyncChanges(from_here, change_list);
133 for (const auto& change : change_list) {
134 syncer::SyncData sync_data = change.sync_data();
135 EXPECT_EQ(expected_type_, sync_data.GetDataType());
136
dchengc963c7142016-04-08 03:55:22137 std::unique_ptr<ExtensionSyncData> modified =
asargente48ab752016-03-12 00:59:20138 ExtensionSyncData::CreateFromSyncData(sync_data);
139
140 // Start by removing any existing entry for this extension id.
Mikel Astiz3001dd82021-07-19 12:40:00141 for (auto iter = data_.begin(); iter != data_.end(); ++iter) {
dchengc963c7142016-04-08 03:55:22142 std::unique_ptr<ExtensionSyncData> existing =
asargente48ab752016-03-12 00:59:20143 ExtensionSyncData::CreateFromSyncData(*iter);
144 if (existing->id() == modified->id()) {
Mikel Astiz3001dd82021-07-19 12:40:00145 data_.erase(iter);
asargente48ab752016-03-12 00:59:20146 break;
147 }
148 }
149
150 // Now add in the new data for this id, if appropriate.
151 if (change.change_type() == SyncChange::ACTION_ADD ||
152 change.change_type() == SyncChange::ACTION_UPDATE) {
Mikel Astiz3001dd82021-07-19 12:40:00153 data_.push_back(sync_data);
asargente48ab752016-03-12 00:59:20154 } else if (change.change_type() != SyncChange::ACTION_DELETE) {
155 ADD_FAILURE() << "Unexpected change type " << change.change_type();
156 }
157 }
Anton Bikineev46bbb972021-05-15 17:53:53158 return absl::nullopt;
asargente48ab752016-03-12 00:59:20159 }
160
asargente48ab752016-03-12 00:59:20161 // This is a helper to vend a wrapped version of this object suitable for
162 // passing in to MergeDataAndStartSyncing, which takes a
dchengc963c7142016-04-08 03:55:22163 // std::unique_ptr<SyncChangeProcessor>, since in tests we typically don't
164 // want to
asargente48ab752016-03-12 00:59:20165 // give up ownership of a local change processor.
dchengc963c7142016-04-08 03:55:22166 std::unique_ptr<syncer::SyncChangeProcessor> GetWrapped() {
Jinho Bangb5216cec2018-01-17 19:43:11167 return std::make_unique<syncer::SyncChangeProcessorWrapperForTest>(this);
asargente48ab752016-03-12 00:59:20168 }
169
Mikel Astiz3001dd82021-07-19 12:40:00170 const syncer::SyncDataList& data() const { return data_; }
171
172 private:
asargente48ab752016-03-12 00:59:20173 // The expected ModelType of changes that this processor will see.
Mikel Astiz3001dd82021-07-19 12:40:00174 const syncer::ModelType expected_type_;
175 syncer::SyncDataList data_;
asargente48ab752016-03-12 00:59:20176
177 DISALLOW_COPY_AND_ASSIGN(StatefulChangeProcessor);
178};
179
treib65f103042015-12-03 10:21:36180} // namespace
181
treib9afc6212015-10-30 18:49:58182class ExtensionServiceSyncTest
183 : public extensions::ExtensionServiceTestWithInstall {
184 public:
185 void MockSyncStartFlare(bool* was_called,
186 syncer::ModelType* model_type_passed_in,
187 syncer::ModelType model_type) {
188 *was_called = true;
189 *model_type_passed_in = model_type;
190 }
191
asargente48ab752016-03-12 00:59:20192 // Helper to call MergeDataAndStartSyncing with no server data and dummy
193 // change processor / error factory.
194 void StartSyncing(syncer::ModelType type) {
195 ASSERT_TRUE(type == syncer::EXTENSIONS || type == syncer::APPS);
196 extension_sync_service()->MergeDataAndStartSyncing(
197 type, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11198 std::make_unique<syncer::FakeSyncChangeProcessor>(),
199 std::make_unique<syncer::SyncErrorFactoryMock>());
asargente48ab752016-03-12 00:59:20200 }
201
rdevlin.cronin2f1ed4c2017-06-13 16:22:13202 void DisableExtensionFromSync(const Extension& extension,
203 int disable_reasons) {
Minh X. Nguyen45479012017-08-18 21:35:36204 ExtensionSyncData disable_extension = GetDisableSyncData(
205 extension, extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13206 SyncChangeList list(
207 1, disable_extension.GetSyncChange(SyncChange::ACTION_UPDATE));
208 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
209 }
210
211 void EnableExtensionFromSync(const Extension& extension) {
212 ExtensionSyncData enable_extension = GetEnableSyncData(extension);
213 SyncChangeList list(
214 1, enable_extension.GetSyncChange(SyncChange::ACTION_UPDATE));
215 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
216 }
217
treib9afc6212015-10-30 18:49:58218 protected:
219 // Paths to some of the fake extensions.
220 base::FilePath good0_path() {
221 return data_dir()
222 .AppendASCII("good")
223 .AppendASCII("Extensions")
224 .AppendASCII(good0)
225 .AppendASCII("1.0.0.0");
226 }
227
228 ExtensionSyncService* extension_sync_service() {
229 return ExtensionSyncService::Get(profile());
230 }
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02231
232 ExtensionSystem* extension_system() {
233 return ExtensionSystem::Get(profile());
234 }
treib9afc6212015-10-30 18:49:58235};
236
Song Fangzhenc38045d2021-08-05 02:38:37237TEST_F(ExtensionServiceSyncTest, DeleteAllInstalledBookMarkAppsDuringSync) {
238 InitializeEmptyExtensionService();
239
240 // Install the bookmark app.
241 InstallCRX(data_dir().AppendASCII("good.crx"),
242 ManifestLocation::kExternalPref, INSTALL_NEW,
243 Extension::FROM_BOOKMARK);
244 const Extension* extension = registry()->GetInstalledExtension(good_crx);
245 ASSERT_TRUE(extension);
246 ASSERT_TRUE(extension->from_bookmark());
247 ASSERT_FALSE(extensions::util::ShouldSync(extension, profile()));
248
249 StartSyncing(syncer::EXTENSIONS);
250
251 // Should uninstall the bookmark app.
252 EXPECT_FALSE(
253 registry()->GetExtensionById(good_crx, ExtensionRegistry::EVERYTHING));
254}
255
treib9afc6212015-10-30 18:49:58256TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledComponent) {
257 InitializeEmptyExtensionService();
258
259 bool flare_was_called = false;
260 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
261 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
Victor Hugo Vianna Silva75334d92020-11-10 07:42:44262 extension_sync_service()->SetSyncStartFlareForTesting(base::BindRepeating(
263 &ExtensionServiceSyncTest::MockSyncStartFlare, factory.GetWeakPtr(),
264 &flare_was_called, // Safe due to WeakPtrFactory scope.
265 &triggered_type)); // Safe due to WeakPtrFactory scope.
treib9afc6212015-10-30 18:49:58266
267 // Install a component extension.
268 std::string manifest;
269 ASSERT_TRUE(base::ReadFileToString(
270 good0_path().Append(extensions::kManifestFilename), &manifest));
271 service()->component_loader()->Add(manifest, good0_path());
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02272 ASSERT_FALSE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58273 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02274 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58275
276 // Extensions added before service is_ready() don't trigger sync startup.
277 EXPECT_FALSE(flare_was_called);
278 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
279}
280
281TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledNormal) {
282 InitializeGoodInstalledExtensionService();
283
284 bool flare_was_called = false;
285 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
286 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
Victor Hugo Vianna Silva75334d92020-11-10 07:42:44287 extension_sync_service()->SetSyncStartFlareForTesting(base::BindRepeating(
288 &ExtensionServiceSyncTest::MockSyncStartFlare, factory.GetWeakPtr(),
289 &flare_was_called, // Safe due to WeakPtrFactory scope.
290 &triggered_type)); // Safe due to WeakPtrFactory scope.
treib9afc6212015-10-30 18:49:58291
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02292 ASSERT_FALSE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58293 service()->Init();
294 ASSERT_EQ(3u, loaded_.size());
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02295 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58296
297 // Extensions added before service is_ready() don't trigger sync startup.
298 EXPECT_FALSE(flare_was_called);
299 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
300}
301
302TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupOnInstall) {
303 InitializeEmptyExtensionService();
304 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02305 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58306
307 bool flare_was_called = false;
308 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
309 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
Victor Hugo Vianna Silva75334d92020-11-10 07:42:44310 extension_sync_service()->SetSyncStartFlareForTesting(base::BindRepeating(
311 &ExtensionServiceSyncTest::MockSyncStartFlare, factory.GetWeakPtr(),
312 &flare_was_called, // Safe due to WeakPtrFactory scope.
313 &triggered_type)); // Safe due to WeakPtrFactory scope.
treib9afc6212015-10-30 18:49:58314
315 base::FilePath path = data_dir().AppendASCII("good.crx");
316 InstallCRX(path, INSTALL_NEW);
317
318 EXPECT_TRUE(flare_was_called);
319 EXPECT_EQ(syncer::EXTENSIONS, triggered_type);
320
321 // Reset.
322 flare_was_called = false;
323 triggered_type = syncer::UNSPECIFIED;
324
325 // Once sync starts, flare should no longer be invoked.
326 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36327 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11328 std::make_unique<syncer::FakeSyncChangeProcessor>(),
329 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58330 path = data_dir().AppendASCII("page_action.crx");
331 InstallCRX(path, INSTALL_NEW);
332 EXPECT_FALSE(flare_was_called);
333 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
334}
335
336TEST_F(ExtensionServiceSyncTest, DisableExtensionFromSync) {
337 // Start the extensions service with one external extension already installed.
338 base::FilePath source_install_dir =
339 data_dir().AppendASCII("good").AppendASCII("Extensions");
340 base::FilePath pref_path =
341 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
342
343 InitializeInstalledExtensionService(pref_path, source_install_dir);
344
345 // The user has enabled sync.
Marc Treib5a78e9c2019-02-19 16:47:01346 syncer::SyncService* sync_service =
Victor Hugo Vianna Silvaff4e5f6e2021-06-01 20:12:14347 SyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:47348 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
treib9afc6212015-10-30 18:49:58349
350 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02351 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58352
353 ASSERT_EQ(3u, loaded_.size());
354
355 // We start enabled.
David Bertonia0b34722019-09-30 20:51:26356 const Extension* extension = registry()->enabled_extensions().GetByID(good0);
treib9afc6212015-10-30 18:49:58357 ASSERT_TRUE(extension);
358 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
359
360 // Sync starts up.
361 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36362 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11363 std::make_unique<syncer::FakeSyncChangeProcessor>(),
364 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58365
366 // Then sync data arrives telling us to disable |good0|.
Minh X. Nguyen45479012017-08-18 21:35:36367 ExtensionSyncData disable_good_crx(
368 *extension, false, extensions::disable_reason::DISABLE_USER_ACTION, false,
Swapnilf6f2f1d2021-01-14 18:50:43369 false, extension_urls::GetWebstoreUpdateUrl());
treib65f103042015-12-03 10:21:36370 SyncChangeList list(
371 1, disable_good_crx.GetSyncChange(SyncChange::ACTION_UPDATE));
treib9afc6212015-10-30 18:49:58372 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
373
374 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
375}
376
rdevlin.cronin2f1ed4c2017-06-13 16:22:13377// Test that sync can enable and disable installed extensions.
378TEST_F(ExtensionServiceSyncTest, ReenableDisabledExtensionFromSync) {
379 InitializeEmptyExtensionService();
380
381 // Enable sync.
Marc Treib5a78e9c2019-02-19 16:47:01382 syncer::SyncService* sync_service =
Victor Hugo Vianna Silvaff4e5f6e2021-06-01 20:12:14383 SyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:47384 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13385
386 service()->Init();
387
388 // Load up a simple extension.
389 extensions::ChromeTestExtensionLoader extension_loader(profile());
390 extension_loader.set_pack_extension(true);
391 scoped_refptr<const Extension> extension = extension_loader.LoadExtension(
392 data_dir().AppendASCII("simple_with_file"));
393 ASSERT_TRUE(extension);
394 const std::string kExtensionId = extension->id();
395 ASSERT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
396
397 syncer::FakeSyncChangeProcessor* processor_raw = nullptr;
398 {
Jinho Bangb5216cec2018-01-17 19:43:11399 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
rdevlin.cronin2f1ed4c2017-06-13 16:22:13400 processor_raw = processor.get();
401 extension_sync_service()->MergeDataAndStartSyncing(
402 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:11403 std::make_unique<syncer::SyncErrorFactoryMock>());
rdevlin.cronin2f1ed4c2017-06-13 16:22:13404 }
405 processor_raw->changes().clear();
406
Minh X. Nguyen45479012017-08-18 21:35:36407 DisableExtensionFromSync(*extension,
408 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13409
410 // The extension should be disabled.
411 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
Minh X. Nguyen45479012017-08-18 21:35:36412 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
rdevlin.cronin2f1ed4c2017-06-13 16:22:13413 ExtensionPrefs::Get(profile())->GetDisableReasons(kExtensionId));
414 EXPECT_TRUE(processor_raw->changes().empty());
415
416 // Enable the extension. Sync should push the new state.
417 service()->EnableExtension(kExtensionId);
418 {
419 ASSERT_EQ(1u, processor_raw->changes().size());
420 const SyncChange& change = processor_raw->changes()[0];
421 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
422 std::unique_ptr<ExtensionSyncData> data =
423 ExtensionSyncData::CreateFromSyncData(change.sync_data());
424 EXPECT_EQ(kExtensionId, data->id());
425 EXPECT_EQ(0, data->disable_reasons());
426 EXPECT_TRUE(data->enabled());
427 }
428
429 // Disable the extension again. Sync should push the new state.
430 processor_raw->changes().clear();
Minh X. Nguyen45479012017-08-18 21:35:36431 service()->DisableExtension(kExtensionId,
432 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13433 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
434 {
435 ASSERT_EQ(1u, processor_raw->changes().size());
436 const SyncChange& change = processor_raw->changes()[0];
437 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
438 std::unique_ptr<ExtensionSyncData> data =
439 ExtensionSyncData::CreateFromSyncData(change.sync_data());
440 EXPECT_EQ(kExtensionId, data->id());
Minh X. Nguyen45479012017-08-18 21:35:36441 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
442 data->disable_reasons());
rdevlin.cronin2f1ed4c2017-06-13 16:22:13443 EXPECT_FALSE(data->enabled());
444 }
445 processor_raw->changes().clear();
446
447 // Enable the extension via sync.
448 EnableExtensionFromSync(*extension);
449
450 // The extension should be enabled.
451 EXPECT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
452 EXPECT_TRUE(processor_raw->changes().empty());
453}
454
455// Tests that default-installed extensions won't be affected by incoming sync
456// data. (It's feasible to have a sync entry for an extension that could be
457// default installed, since one installation may be default-installed while
458// another may not be).
459TEST_F(ExtensionServiceSyncTest,
460 DefaultInstalledExtensionsAreNotReenabledOrDisabledBySync) {
461 InitializeEmptyExtensionService();
462
463 // Enable sync.
Marc Treib5a78e9c2019-02-19 16:47:01464 syncer::SyncService* sync_service =
Victor Hugo Vianna Silvaff4e5f6e2021-06-01 20:12:14465 SyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:47466 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13467
468 service()->Init();
469
470 // Load up an extension that's considered default installed.
471 extensions::ChromeTestExtensionLoader extension_loader(profile());
472 extension_loader.set_pack_extension(true);
473 extension_loader.add_creation_flag(Extension::WAS_INSTALLED_BY_DEFAULT);
474 scoped_refptr<const Extension> extension = extension_loader.LoadExtension(
475 data_dir().AppendASCII("simple_with_file"));
476 ASSERT_TRUE(extension);
477
478 // The extension shouldn't sync.
479 EXPECT_FALSE(extensions::util::ShouldSync(extension.get(), profile()));
480 const std::string kExtensionId = extension->id();
481 ASSERT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
482
483 syncer::FakeSyncChangeProcessor* processor_raw = nullptr;
484 {
Jinho Bangb5216cec2018-01-17 19:43:11485 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
rdevlin.cronin2f1ed4c2017-06-13 16:22:13486 processor_raw = processor.get();
487 extension_sync_service()->MergeDataAndStartSyncing(
488 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:11489 std::make_unique<syncer::SyncErrorFactoryMock>());
rdevlin.cronin2f1ed4c2017-06-13 16:22:13490 }
491 processor_raw->changes().clear();
492
493 // Sync state says the extension is disabled (e.g. on another machine).
Minh X. Nguyen45479012017-08-18 21:35:36494 DisableExtensionFromSync(*extension,
495 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13496
497 // The extension should still be enabled, since it's default-installed.
498 EXPECT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
499 EXPECT_TRUE(processor_raw->changes().empty());
500
501 // Now disable the extension locally. Sync should *not* push new state.
Minh X. Nguyen45479012017-08-18 21:35:36502 service()->DisableExtension(kExtensionId,
503 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13504 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
505 EXPECT_TRUE(processor_raw->changes().empty());
506
507 // Sync state says the extension is enabled.
508 EnableExtensionFromSync(*extension);
509
510 // As above, the extension should not have been affected by sync.
511 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
512 EXPECT_TRUE(processor_raw->changes().empty());
513
514 // And re-enabling the extension should not push new state to sync.
515 service()->EnableExtension(kExtensionId);
516 EXPECT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
517 EXPECT_TRUE(processor_raw->changes().empty());
518}
519
treib9afc6212015-10-30 18:49:58520TEST_F(ExtensionServiceSyncTest, IgnoreSyncChangesWhenLocalStateIsMoreRecent) {
521 // Start the extension service with three extensions already installed.
522 base::FilePath source_install_dir =
523 data_dir().AppendASCII("good").AppendASCII("Extensions");
524 base::FilePath pref_path =
525 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
526
527 InitializeInstalledExtensionService(pref_path, source_install_dir);
528
529 // The user has enabled sync.
Marc Treib5a78e9c2019-02-19 16:47:01530 syncer::SyncService* sync_service =
Victor Hugo Vianna Silvaff4e5f6e2021-06-01 20:12:14531 SyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:47532 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
treib9afc6212015-10-30 18:49:58533 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
534 extension_sync_service();
535
536 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02537 ASSERT_TRUE(extension_system()->is_ready());
treib9afc6212015-10-30 18:49:58538 ASSERT_EQ(3u, loaded_.size());
539
540 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
541 ASSERT_TRUE(service()->IsExtensionEnabled(good2));
542
543 // Disable and re-enable good0 before first sync data arrives.
Minh X. Nguyen45479012017-08-18 21:35:36544 service()->DisableExtension(good0,
545 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:58546 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
547 service()->EnableExtension(good0);
548 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
549 // Disable good2 before first sync data arrives (good1 is considered
550 // non-syncable because it has plugin permission).
Minh X. Nguyen45479012017-08-18 21:35:36551 service()->DisableExtension(good2,
552 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:58553 ASSERT_FALSE(service()->IsExtensionEnabled(good2));
554
David Bertonia0b34722019-09-30 20:51:26555 const Extension* extension0 = registry()->enabled_extensions().GetByID(good0);
David Bertoni58c113a2019-08-02 19:53:26556 const Extension* extension2 =
David Bertonia0b34722019-09-30 20:51:26557 registry()->disabled_extensions().GetByID(good2);
treib9afc6212015-10-30 18:49:58558 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension0));
559 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension2));
560
561 // Now sync data comes in that says to disable good0 and enable good2.
Minh X. Nguyen45479012017-08-18 21:35:36562 ExtensionSyncData disable_good0(
563 *extension0, false, extensions::disable_reason::DISABLE_USER_ACTION,
Swapnilf6f2f1d2021-01-14 18:50:43564 false, false, extension_urls::GetWebstoreUpdateUrl());
565 ExtensionSyncData enable_good2(
566 *extension2, true, extensions::disable_reason::DISABLE_NONE, false, false,
567 extension_urls::GetWebstoreUpdateUrl());
treib9afc6212015-10-30 18:49:58568 syncer::SyncDataList sync_data;
569 sync_data.push_back(disable_good0.GetSyncData());
570 sync_data.push_back(enable_good2.GetSyncData());
571 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:22572 syncer::EXTENSIONS, sync_data,
Jinho Bangb5216cec2018-01-17 19:43:11573 std::make_unique<syncer::FakeSyncChangeProcessor>(),
574 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58575
576 // Both sync changes should be ignored, since the local state was changed
577 // before sync started, and so the local state is considered more recent.
578 EXPECT_TRUE(service()->IsExtensionEnabled(good0));
579 EXPECT_FALSE(service()->IsExtensionEnabled(good2));
580}
581
treibb794dd52015-12-01 18:47:14582TEST_F(ExtensionServiceSyncTest, DontSelfNotify) {
583 // Start the extension service with three extensions already installed.
584 base::FilePath source_install_dir =
585 data_dir().AppendASCII("good").AppendASCII("Extensions");
586 base::FilePath pref_path =
587 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
588
589 InitializeInstalledExtensionService(pref_path, source_install_dir);
590
591 // The user has enabled sync.
Victor Hugo Vianna Silvaff4e5f6e2021-06-01 20:12:14592 SyncServiceFactory::GetForProfile(profile())
Marc Treib9948a682018-11-20 08:01:37593 ->GetUserSettings()
Tanmoy Mollik0960d702019-09-11 15:14:47594 ->SetFirstSetupComplete(kSetSourceFromTest);
treibb794dd52015-12-01 18:47:14595 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
596 extension_sync_service();
597
598 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:02599 ASSERT_TRUE(extension_system()->is_ready());
treibb794dd52015-12-01 18:47:14600 ASSERT_EQ(3u, loaded_.size());
601 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
602
603 syncer::FakeSyncChangeProcessor* processor =
604 new syncer::FakeSyncChangeProcessor;
605 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:22606 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
Jinho Bangb5216cec2018-01-17 19:43:11607 std::make_unique<syncer::SyncErrorFactoryMock>());
treibb794dd52015-12-01 18:47:14608
609 processor->changes().clear();
610
611 // Simulate various incoming sync changes, and make sure they don't result in
612 // any outgoing changes.
613
614 {
David Bertoni58c113a2019-08-02 19:53:26615 const Extension* extension =
David Bertonia0b34722019-09-30 20:51:26616 registry()->enabled_extensions().GetByID(good0);
treibb794dd52015-12-01 18:47:14617 ASSERT_TRUE(extension);
618
619 // Disable the extension.
Swapnilf6f2f1d2021-01-14 18:50:43620 ExtensionSyncData data(
621 *extension, false, extensions::disable_reason::DISABLE_USER_ACTION,
622 false, false, extension_urls::GetWebstoreUpdateUrl());
treib65f103042015-12-03 10:21:36623 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14624
625 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
626
627 EXPECT_TRUE(processor->changes().empty());
628 }
629
630 {
David Bertoni58c113a2019-08-02 19:53:26631 const Extension* extension =
David Bertonia0b34722019-09-30 20:51:26632 registry()->disabled_extensions().GetByID(good0);
treibb794dd52015-12-01 18:47:14633 ASSERT_TRUE(extension);
634
635 // Set incognito enabled to true.
Minh X. Nguyen45479012017-08-18 21:35:36636 ExtensionSyncData data(*extension, false,
637 extensions::disable_reason::DISABLE_NONE, true,
Swapnilf6f2f1d2021-01-14 18:50:43638 false, extension_urls::GetWebstoreUpdateUrl());
treib65f103042015-12-03 10:21:36639 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14640
641 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
642
643 EXPECT_TRUE(processor->changes().empty());
644 }
645
646 {
David Bertoni58c113a2019-08-02 19:53:26647 const Extension* extension =
David Bertonia0b34722019-09-30 20:51:26648 registry()->disabled_extensions().GetByID(good0);
treibb794dd52015-12-01 18:47:14649 ASSERT_TRUE(extension);
650
651 // Add another disable reason.
Minh X. Nguyen45479012017-08-18 21:35:36652 ExtensionSyncData data(
653 *extension, false,
654 extensions::disable_reason::DISABLE_USER_ACTION |
655 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
Swapnilf6f2f1d2021-01-14 18:50:43656 false, false, extension_urls::GetWebstoreUpdateUrl());
treib65f103042015-12-03 10:21:36657 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14658
659 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
660
661 EXPECT_TRUE(processor->changes().empty());
662 }
663
664 {
David Bertoni58c113a2019-08-02 19:53:26665 const Extension* extension =
David Bertonia0b34722019-09-30 20:51:26666 registry()->disabled_extensions().GetByID(good0);
treibb794dd52015-12-01 18:47:14667 ASSERT_TRUE(extension);
668
669 // Uninstall the extension.
Minh X. Nguyen45479012017-08-18 21:35:36670 ExtensionSyncData data(
671 *extension, false,
672 extensions::disable_reason::DISABLE_USER_ACTION |
673 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
Swapnilf6f2f1d2021-01-14 18:50:43674 false, false, extension_urls::GetWebstoreUpdateUrl());
treib65f103042015-12-03 10:21:36675 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_DELETE));
treibb794dd52015-12-01 18:47:14676
677 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
678
679 EXPECT_TRUE(processor->changes().empty());
680 }
681}
682
treib9afc6212015-10-30 18:49:58683TEST_F(ExtensionServiceSyncTest, GetSyncData) {
684 InitializeEmptyExtensionService();
685 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
David Bertoni9f897c92019-09-20 17:46:35686 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58687 ASSERT_TRUE(extension);
688
689 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36690 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11691 std::make_unique<syncer::FakeSyncChangeProcessor>(),
692 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58693
694 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16695 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58696 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22697 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58698 ExtensionSyncData::CreateFromSyncData(list[0]);
699 ASSERT_TRUE(data.get());
700 EXPECT_EQ(extension->id(), data->id());
701 EXPECT_FALSE(data->uninstalled());
702 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
703 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
704 data->incognito_enabled());
Devlin Cronin03bf2d22017-12-20 08:21:05705 EXPECT_EQ(data->version(), extension->version());
treib9afc6212015-10-30 18:49:58706 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
707 data->update_url());
708 EXPECT_EQ(extension->name(), data->name());
709}
710
treib29e1b9b12015-11-11 08:50:56711TEST_F(ExtensionServiceSyncTest, GetSyncDataDisableReasons) {
712 InitializeEmptyExtensionService();
713 const Extension* extension =
714 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
715 ASSERT_TRUE(extension);
716
treib29e1b9b12015-11-11 08:50:56717 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36718 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11719 std::make_unique<syncer::FakeSyncChangeProcessor>(),
720 std::make_unique<syncer::SyncErrorFactoryMock>());
treib29e1b9b12015-11-11 08:50:56721
722 {
723 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16724 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib29e1b9b12015-11-11 08:50:56725 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22726 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56727 ExtensionSyncData::CreateFromSyncData(list[0]);
728 ASSERT_TRUE(data.get());
729 EXPECT_TRUE(data->enabled());
730 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36731 EXPECT_EQ(extensions::disable_reason::DISABLE_NONE,
732 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56733 }
734
735 // Syncable disable reason, should propagate to sync.
Minh X. Nguyen45479012017-08-18 21:35:36736 service()->DisableExtension(good_crx,
737 extensions::disable_reason::DISABLE_USER_ACTION);
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_FALSE(data->enabled());
746 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36747 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
748 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56749 }
750 service()->EnableExtension(good_crx);
751
752 // Non-syncable disable reason. The sync data should still say "enabled".
Minh X. Nguyen45479012017-08-18 21:35:36753 service()->DisableExtension(good_crx,
754 extensions::disable_reason::DISABLE_RELOAD);
treib29e1b9b12015-11-11 08:50:56755 {
756 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16757 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib29e1b9b12015-11-11 08:50:56758 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22759 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56760 ExtensionSyncData::CreateFromSyncData(list[0]);
761 ASSERT_TRUE(data.get());
762 EXPECT_TRUE(data->enabled());
763 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36764 EXPECT_EQ(extensions::disable_reason::DISABLE_NONE,
765 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56766 }
767 service()->EnableExtension(good_crx);
768
769 // Both a syncable and a non-syncable disable reason, only the former should
770 // propagate to sync.
Minh X. Nguyen45479012017-08-18 21:35:36771 service()->DisableExtension(good_crx,
772 extensions::disable_reason::DISABLE_USER_ACTION |
773 extensions::disable_reason::DISABLE_RELOAD);
treib29e1b9b12015-11-11 08:50:56774 {
775 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16776 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib29e1b9b12015-11-11 08:50:56777 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22778 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56779 ExtensionSyncData::CreateFromSyncData(list[0]);
780 ASSERT_TRUE(data.get());
781 EXPECT_FALSE(data->enabled());
782 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36783 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
784 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56785 }
786 service()->EnableExtension(good_crx);
787}
788
treib9afc6212015-10-30 18:49:58789TEST_F(ExtensionServiceSyncTest, GetSyncDataTerminated) {
790 InitializeEmptyExtensionService();
791 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
792 TerminateExtension(good_crx);
David Bertoni9f897c92019-09-20 17:46:35793 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58794 ASSERT_TRUE(extension);
795
treib9afc6212015-10-30 18:49:58796 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36797 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11798 std::make_unique<syncer::FakeSyncChangeProcessor>(),
799 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58800
801 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16802 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58803 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22804 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58805 ExtensionSyncData::CreateFromSyncData(list[0]);
806 ASSERT_TRUE(data.get());
807 EXPECT_EQ(extension->id(), data->id());
808 EXPECT_FALSE(data->uninstalled());
809 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
810 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
811 data->incognito_enabled());
Devlin Cronin03bf2d22017-12-20 08:21:05812 EXPECT_EQ(data->version(), extension->version());
treib9afc6212015-10-30 18:49:58813 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
814 data->update_url());
815 EXPECT_EQ(extension->name(), data->name());
816}
817
818TEST_F(ExtensionServiceSyncTest, GetSyncDataFilter) {
819 InitializeEmptyExtensionService();
820 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
David Bertoni9f897c92019-09-20 17:46:35821 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58822 ASSERT_TRUE(extension);
823
treib9afc6212015-10-30 18:49:58824 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36825 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11826 std::make_unique<syncer::FakeSyncChangeProcessor>(),
827 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58828
829 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(), 0U);
832}
833
834TEST_F(ExtensionServiceSyncTest, GetSyncExtensionDataUserSettings) {
835 InitializeEmptyExtensionService();
836 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
David Bertoni9f897c92019-09-20 17:46:35837 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58838 ASSERT_TRUE(extension);
839
treib9afc6212015-10-30 18:49:58840 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36841 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11842 std::make_unique<syncer::FakeSyncChangeProcessor>(),
843 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58844
845 {
846 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16847 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58848 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22849 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58850 ExtensionSyncData::CreateFromSyncData(list[0]);
851 ASSERT_TRUE(data.get());
852 EXPECT_TRUE(data->enabled());
853 EXPECT_FALSE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58854 }
855
Minh X. Nguyen45479012017-08-18 21:35:36856 service()->DisableExtension(good_crx,
857 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:58858 {
859 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16860 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58861 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22862 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58863 ExtensionSyncData::CreateFromSyncData(list[0]);
864 ASSERT_TRUE(data.get());
865 EXPECT_FALSE(data->enabled());
866 EXPECT_FALSE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58867 }
868
869 extensions::util::SetIsIncognitoEnabled(good_crx, profile(), true);
treib9afc6212015-10-30 18:49:58870 {
871 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16872 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58873 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22874 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58875 ExtensionSyncData::CreateFromSyncData(list[0]);
876 ASSERT_TRUE(data.get());
877 EXPECT_FALSE(data->enabled());
878 EXPECT_TRUE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58879 }
880
881 service()->EnableExtension(good_crx);
treib9afc6212015-10-30 18:49:58882 {
883 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16884 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:58885 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22886 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58887 ExtensionSyncData::CreateFromSyncData(list[0]);
888 ASSERT_TRUE(data.get());
889 EXPECT_TRUE(data->enabled());
890 EXPECT_TRUE(data->incognito_enabled());
treib9afc6212015-10-30 18:49:58891 }
892}
893
894TEST_F(ExtensionServiceSyncTest, SyncForUninstalledExternalExtension) {
895 InitializeEmptyExtensionService();
Gyuyoung Kim9c82d5bb32021-03-20 01:28:01896 InstallCRX(data_dir().AppendASCII("good.crx"),
897 ManifestLocation::kExternalPref, INSTALL_NEW, Extension::NO_FLAGS);
David Bertoni9f897c92019-09-20 17:46:35898 const Extension* extension = registry()->GetInstalledExtension(good_crx);
treib9afc6212015-10-30 18:49:58899 ASSERT_TRUE(extension);
900
treib9afc6212015-10-30 18:49:58901 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36902 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11903 std::make_unique<syncer::FakeSyncChangeProcessor>(),
904 std::make_unique<syncer::SyncErrorFactoryMock>());
asargente48ab752016-03-12 00:59:20905 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:58906
Devlin Cronin6fd1cd62017-12-05 19:13:57907 UninstallExtension(good_crx);
treib9afc6212015-10-30 18:49:58908 EXPECT_TRUE(
909 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
910
911 sync_pb::EntitySpecifics specifics;
912 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
913 sync_pb::ExtensionSpecifics* extension_specifics =
914 app_specifics->mutable_extension();
915 extension_specifics->set_id(good_crx);
916 extension_specifics->set_version("1.0");
917 extension_specifics->set_enabled(true);
918
treib65f103042015-12-03 10:21:36919 SyncChangeList list =
920 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:58921
922 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
923 EXPECT_TRUE(
924 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
925}
926
927TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettings) {
928 InitializeEmptyExtensionService();
929 const Extension* app =
930 PackAndInstallCRX(data_dir().AppendASCII("app"), INSTALL_NEW);
931 ASSERT_TRUE(app);
932 ASSERT_TRUE(app->is_app());
933
treib9afc6212015-10-30 18:49:58934 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36935 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11936 std::make_unique<syncer::FakeSyncChangeProcessor>(),
937 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58938
939 syncer::StringOrdinal initial_ordinal =
940 syncer::StringOrdinal::CreateInitialOrdinal();
941 {
942 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16943 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS);
treib9afc6212015-10-30 18:49:58944 ASSERT_EQ(list.size(), 1U);
945
dchengc963c7142016-04-08 03:55:22946 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58947 ExtensionSyncData::CreateFromSyncData(list[0]);
948 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->app_launch_ordinal()));
949 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
950 }
951
deepak.m14ba69e62015-11-17 05:42:12952 AppSorting* sorting = ExtensionSystem::Get(profile())->app_sorting();
treib9afc6212015-10-30 18:49:58953 sorting->SetAppLaunchOrdinal(app->id(), initial_ordinal.CreateAfter());
954 {
955 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16956 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS);
treib9afc6212015-10-30 18:49:58957 ASSERT_EQ(list.size(), 1U);
958
dchengc963c7142016-04-08 03:55:22959 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58960 ExtensionSyncData::CreateFromSyncData(list[0]);
961 ASSERT_TRUE(app_sync_data.get());
962 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
963 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
964 }
965
966 sorting->SetPageOrdinal(app->id(), initial_ordinal.CreateAfter());
967 {
968 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:16969 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS);
treib9afc6212015-10-30 18:49:58970 ASSERT_EQ(list.size(), 1U);
971
dchengc963c7142016-04-08 03:55:22972 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58973 ExtensionSyncData::CreateFromSyncData(list[0]);
974 ASSERT_TRUE(app_sync_data.get());
975 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
976 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->page_ordinal()));
977 }
978}
979
980// TODO (rdevlin.cronin): The OnExtensionMoved() method has been removed from
981// ExtensionService, so this test probably needs a new home. Unfortunately, it
982// relies pretty heavily on things like InitializeExtension[Sync]Service() and
983// PackAndInstallCRX(). When we clean up a bit more, this should move out.
984TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettingsOnExtensionMoved) {
985 InitializeEmptyExtensionService();
986 const size_t kAppCount = 3;
987 const Extension* apps[kAppCount];
988 apps[0] = PackAndInstallCRX(data_dir().AppendASCII("app1"), INSTALL_NEW);
989 apps[1] = PackAndInstallCRX(data_dir().AppendASCII("app2"), INSTALL_NEW);
990 apps[2] = PackAndInstallCRX(data_dir().AppendASCII("app4"), INSTALL_NEW);
991 for (size_t i = 0; i < kAppCount; ++i) {
992 ASSERT_TRUE(apps[i]);
993 ASSERT_TRUE(apps[i]->is_app());
994 }
995
treib9afc6212015-10-30 18:49:58996 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36997 syncer::APPS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22998 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
999 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:581000
deepak.m14ba69e62015-11-17 05:42:121001 ExtensionSystem::Get(service()->GetBrowserContext())
treib9afc6212015-10-30 18:49:581002 ->app_sorting()
1003 ->OnExtensionMoved(apps[0]->id(), apps[1]->id(), apps[2]->id());
1004 {
1005 syncer::SyncDataList list =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:161006 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS);
treib9afc6212015-10-30 18:49:581007 ASSERT_EQ(list.size(), 3U);
1008
dchengc963c7142016-04-08 03:55:221009 std::unique_ptr<ExtensionSyncData> data[kAppCount];
treib9afc6212015-10-30 18:49:581010 for (size_t i = 0; i < kAppCount; ++i) {
1011 data[i] = ExtensionSyncData::CreateFromSyncData(list[i]);
1012 ASSERT_TRUE(data[i].get());
1013 }
1014
1015 // The sync data is not always in the same order our apps were installed in,
1016 // so we do that sorting here so we can make sure the values are changed as
1017 // expected.
1018 syncer::StringOrdinal app_launch_ordinals[kAppCount];
1019 for (size_t i = 0; i < kAppCount; ++i) {
1020 for (size_t j = 0; j < kAppCount; ++j) {
1021 if (apps[i]->id() == data[j]->id())
1022 app_launch_ordinals[i] = data[j]->app_launch_ordinal();
1023 }
1024 }
1025
1026 EXPECT_TRUE(app_launch_ordinals[1].LessThan(app_launch_ordinals[0]));
1027 EXPECT_TRUE(app_launch_ordinals[0].LessThan(app_launch_ordinals[2]));
1028 }
1029}
1030
1031TEST_F(ExtensionServiceSyncTest, GetSyncDataList) {
1032 InitializeEmptyExtensionService();
1033 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1034 InstallCRX(data_dir().AppendASCII("page_action.crx"), INSTALL_NEW);
1035 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
1036 InstallCRX(data_dir().AppendASCII("theme2.crx"), INSTALL_NEW);
1037
treib9afc6212015-10-30 18:49:581038 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361039 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111040 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1041 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581042 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361043 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111044 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1045 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581046
Minh X. Nguyen45479012017-08-18 21:35:361047 service()->DisableExtension(page_action,
1048 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:581049 TerminateExtension(theme2_crx);
1050
treib9afc6212015-10-30 18:49:581051 EXPECT_EQ(
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:161052 0u,
1053 extension_sync_service()->GetAllSyncDataForTesting(syncer::APPS).size());
1054 EXPECT_EQ(2u, extension_sync_service()
1055 ->GetAllSyncDataForTesting(syncer::EXTENSIONS)
1056 .size());
treib9afc6212015-10-30 18:49:581057}
1058
1059TEST_F(ExtensionServiceSyncTest, ProcessSyncDataUninstall) {
1060 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581061 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361062 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111063 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1064 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581065
1066 sync_pb::EntitySpecifics specifics;
1067 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1068 ext_specifics->set_id(good_crx);
1069 ext_specifics->set_version("1.0");
treib65f103042015-12-03 10:21:361070
1071 SyncChangeList list =
1072 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:581073
1074 // Should do nothing.
1075 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertoni58c113a2019-08-02 19:53:261076 EXPECT_FALSE(
David Bertonia0b34722019-09-30 20:51:261077 registry()->GetExtensionById(good_crx, ExtensionRegistry::EVERYTHING));
treib9afc6212015-10-30 18:49:581078
1079 // Install the extension.
1080 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
1081 InstallCRX(extension_path, INSTALL_NEW);
David Bertonia0b34722019-09-30 20:51:261082 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581083
1084 // Should uninstall the extension.
1085 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertoni58c113a2019-08-02 19:53:261086 EXPECT_FALSE(
David Bertonia0b34722019-09-30 20:51:261087 registry()->GetExtensionById(good_crx, ExtensionRegistry::EVERYTHING));
treib9afc6212015-10-30 18:49:581088
1089 // Should again do nothing.
1090 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertoni58c113a2019-08-02 19:53:261091 EXPECT_FALSE(
David Bertonia0b34722019-09-30 20:51:261092 registry()->GetExtensionById(good_crx, ExtensionRegistry::EVERYTHING));
treib9afc6212015-10-30 18:49:581093}
1094
1095TEST_F(ExtensionServiceSyncTest, ProcessSyncDataWrongType) {
1096 InitializeEmptyExtensionService();
asargente48ab752016-03-12 00:59:201097 StartSyncing(syncer::EXTENSIONS);
1098 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:581099
1100 // Install the extension.
1101 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
1102 InstallCRX(extension_path, INSTALL_NEW);
David Bertonia0b34722019-09-30 20:51:261103 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581104
1105 sync_pb::EntitySpecifics specifics;
1106 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
1107 sync_pb::ExtensionSpecifics* extension_specifics =
1108 app_specifics->mutable_extension();
1109 extension_specifics->set_id(good_crx);
1110 extension_specifics->set_version(
David Bertoni9f897c92019-09-20 17:46:351111 registry()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581112
1113 {
1114 extension_specifics->set_enabled(true);
treib65f103042015-12-03 10:21:361115
1116 SyncChangeList list =
1117 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:581118
1119 // Should do nothing
1120 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertonia0b34722019-09-30 20:51:261121 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581122 }
1123
1124 {
1125 extension_specifics->set_enabled(false);
treib65f103042015-12-03 10:21:361126
1127 SyncChangeList list =
1128 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581129
1130 // Should again do nothing.
1131 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
David Bertonia0b34722019-09-30 20:51:261132 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581133 }
1134}
1135
1136TEST_F(ExtensionServiceSyncTest, ProcessSyncDataSettings) {
1137 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581138 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361139 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111140 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1141 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581142
1143 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1144 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1145 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
treib9afc6212015-10-30 18:49:581146
1147 sync_pb::EntitySpecifics specifics;
1148 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1149 ext_specifics->set_id(good_crx);
1150 ext_specifics->set_version(
David Bertoni9f897c92019-09-20 17:46:351151 registry()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581152 ext_specifics->set_enabled(false);
1153
1154 {
treib65f103042015-12-03 10:21:361155 SyncChangeList list =
1156 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1157
treib9afc6212015-10-30 18:49:581158 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1159 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1160 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
treib9afc6212015-10-30 18:49:581161 }
1162
1163 {
1164 ext_specifics->set_enabled(true);
1165 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361166
1167 SyncChangeList list =
1168 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1169
treib9afc6212015-10-30 18:49:581170 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1171 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1172 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1173 }
1174
1175 {
1176 ext_specifics->set_enabled(false);
1177 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361178
1179 SyncChangeList list =
1180 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1181
treib9afc6212015-10-30 18:49:581182 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1183 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1184 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1185 }
1186
1187 {
1188 ext_specifics->set_enabled(true);
treib65f103042015-12-03 10:21:361189
1190 SyncChangeList list =
1191 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1192
treib9afc6212015-10-30 18:49:581193 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1194 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
treib9afc6212015-10-30 18:49:581195 }
1196
1197 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1198}
1199
1200TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNewExtension) {
1201 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581202 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361203 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111204 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1205 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581206
1207 const base::FilePath path = data_dir().AppendASCII("good.crx");
1208 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1209
1210 struct TestCase {
1211 const char* name; // For failure output only.
1212 bool sync_enabled; // The "enabled" flag coming in from Sync.
1213 // The disable reason(s) coming in from Sync, or -1 for "not set".
1214 int sync_disable_reasons;
1215 // The disable reason(s) that should be set on the installed extension.
1216 // This will usually be the same as |sync_disable_reasons|, but see the
1217 // "Legacy" case.
1218 int expect_disable_reasons;
1219 // Whether the extension's permissions should be auto-granted during
1220 // installation.
1221 bool expect_permissions_granted;
1222 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361223 // Standard case: Extension comes in enabled; permissions should be
1224 // granted
1225 // during installation.
1226 {"Standard", true, 0, 0, true},
1227 // If the extension comes in disabled, its permissions should still be
1228 // granted (the user already approved them on another machine).
1229 {"Disabled", false, extensions::disable_reason::DISABLE_USER_ACTION,
1230 extensions::disable_reason::DISABLE_USER_ACTION, true},
1231 // Legacy case (<M45): No disable reasons come in from Sync (see
1232 // crbug.com/484214). After installation, the reason should be set to
1233 // DISABLE_USER_ACTION (default assumption).
1234 {"Legacy", false, -1, extensions::disable_reason::DISABLE_USER_ACTION,
1235 true},
1236 // If the extension came in disabled due to a permissions increase, then
1237 // the
1238 // user has *not* approved the permissions, and they shouldn't be granted.
1239 // crbug.com/484214
1240 {"PermissionsIncrease", false,
1241 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
1242 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
treib9afc6212015-10-30 18:49:581243 };
1244
1245 for (const TestCase& test_case : test_cases) {
1246 SCOPED_TRACE(test_case.name);
1247
1248 sync_pb::EntitySpecifics specifics;
1249 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1250 ext_specifics->set_id(good_crx);
1251 ext_specifics->set_version(base::Version("1").GetString());
1252 ext_specifics->set_enabled(test_case.sync_enabled);
1253 if (test_case.sync_disable_reasons != -1)
1254 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1255
treib65f103042015-12-03 10:21:361256 SyncChangeList list =
1257 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1258
treib9afc6212015-10-30 18:49:581259 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1260
1261 ASSERT_TRUE(service()->pending_extension_manager()->IsIdPending(good_crx));
1262 UpdateExtension(good_crx, path, test_case.sync_enabled ? ENABLED
1263 : DISABLED);
1264 EXPECT_EQ(test_case.expect_disable_reasons,
1265 prefs->GetDisableReasons(good_crx));
dchengc963c7142016-04-08 03:55:221266 std::unique_ptr<const PermissionSet> permissions =
treib9afc6212015-10-30 18:49:581267 prefs->GetGrantedPermissions(good_crx);
1268 EXPECT_EQ(test_case.expect_permissions_granted, !permissions->IsEmpty());
1269 ASSERT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
Devlin Cronin7b193412017-12-14 03:46:031270 if (test_case.sync_enabled)
1271 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
1272 else
1273 EXPECT_TRUE(registry()->disabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581274
1275 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031276 UninstallExtension(good_crx);
treib9afc6212015-10-30 18:49:581277 }
1278}
1279
1280TEST_F(ExtensionServiceSyncTest, ProcessSyncDataTerminatedExtension) {
1281 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581282 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361283 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111284 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1285 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581286
1287 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1288 TerminateExtension(good_crx);
1289 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1290 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1291
1292 sync_pb::EntitySpecifics specifics;
1293 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1294 ext_specifics->set_id(good_crx);
1295 ext_specifics->set_version(
David Bertoni9f897c92019-09-20 17:46:351296 registry()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581297 ext_specifics->set_enabled(false);
1298 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361299
1300 SyncChangeList list =
1301 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581302
1303 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1304 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1305 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1306
1307 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1308}
1309
1310TEST_F(ExtensionServiceSyncTest, ProcessSyncDataVersionCheck) {
1311 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581312 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361313 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111314 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1315 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581316
1317 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1318 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1319 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1320
1321 sync_pb::EntitySpecifics specifics;
1322 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1323 ext_specifics->set_id(good_crx);
1324 ext_specifics->set_enabled(true);
1325
1326 const base::Version installed_version =
David Bertoni9f897c92019-09-20 17:46:351327 registry()->GetInstalledExtension(good_crx)->version();
treib9afc6212015-10-30 18:49:581328
1329 {
1330 ext_specifics->set_version(installed_version.GetString());
treib65f103042015-12-03 10:21:361331
1332 SyncChangeList list =
1333 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581334
1335 // Should do nothing if extension version == sync version.
1336 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1337 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1338 // Make sure the version we'll send back to sync didn't change.
1339 syncer::SyncDataList data =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:161340 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581341 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221342 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581343 ExtensionSyncData::CreateFromSyncData(data[0]);
1344 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001345 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581346 }
1347
1348 // Should do nothing if extension version > sync version.
1349 {
1350 ext_specifics->set_version("0.0.0.0");
treib65f103042015-12-03 10:21:361351
1352 SyncChangeList list =
1353 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581354
1355 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1356 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1357 // Make sure the version we'll send back to sync didn't change.
1358 syncer::SyncDataList data =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:161359 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581360 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221361 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581362 ExtensionSyncData::CreateFromSyncData(data[0]);
1363 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001364 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581365 }
1366
1367 // Should kick off an update if extension version < sync version.
1368 {
1369 const base::Version new_version("9.9.9.9");
1370 ext_specifics->set_version(new_version.GetString());
treib65f103042015-12-03 10:21:361371
1372 SyncChangeList list =
1373 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581374
1375 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1376 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1377 // Make sure that we'll send the NEW version back to sync, even though we
1378 // haven't actually updated yet. This is to prevent the data in sync from
1379 // flip-flopping back and forth until all clients are up to date.
1380 syncer::SyncDataList data =
Victor Hugo Vianna Silva08a5ad32020-03-13 12:50:161381 extension_sync_service()->GetAllSyncDataForTesting(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581382 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221383 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581384 ExtensionSyncData::CreateFromSyncData(data[0]);
1385 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001386 EXPECT_EQ(new_version, extension_data->version());
treib9afc6212015-10-30 18:49:581387 }
1388
1389 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1390}
1391
1392TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNotInstalled) {
1393 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581394 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361395 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111396 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1397 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581398
1399 sync_pb::EntitySpecifics specifics;
1400 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1401 ext_specifics->set_id(good_crx);
1402 ext_specifics->set_enabled(false);
1403 ext_specifics->set_incognito_enabled(true);
1404 ext_specifics->set_update_url("http://www.google.com/");
1405 ext_specifics->set_version("1.2.3.4");
treib65f103042015-12-03 10:21:361406
1407 SyncChangeList list =
1408 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581409
1410 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1411 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1412 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1413 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1414 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1415 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1416
1417 const extensions::PendingExtensionInfo* info;
1418 EXPECT_TRUE(
1419 (info = service()->pending_extension_manager()->GetById(good_crx)));
1420 EXPECT_EQ(ext_specifics->update_url(), info->update_url().spec());
1421 EXPECT_TRUE(info->is_from_sync());
Gyuyoung Kim5626c752021-03-18 22:58:111422 EXPECT_EQ(ManifestLocation::kInternal, info->install_source());
treib9afc6212015-10-30 18:49:581423 // TODO(akalin): Figure out a way to test |info.ShouldAllowInstall()|.
1424}
1425
1426TEST_F(ExtensionServiceSyncTest, ProcessSyncDataEnableDisable) {
1427 InitializeEmptyExtensionService();
1428 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361429 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111430 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1431 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581432
1433 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1434
1435 struct TestCase {
1436 const char* name; // For failure output only.
1437 // Set of disable reasons before any Sync data comes in. If this is != 0,
1438 // the extension is disabled.
1439 int previous_disable_reasons;
1440 bool sync_enable; // The enabled flag coming in from Sync.
1441 // The disable reason(s) coming in from Sync, or -1 for "not set".
1442 int sync_disable_reasons;
1443 // The expected set of disable reasons after processing the Sync update. The
1444 // extension should be disabled iff this is != 0.
1445 int expect_disable_reasons;
1446 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361447 {"NopEnable", 0, true, 0, 0},
1448 {"NopDisable", extensions::disable_reason::DISABLE_USER_ACTION, false,
1449 extensions::disable_reason::DISABLE_USER_ACTION,
1450 extensions::disable_reason::DISABLE_USER_ACTION},
1451 {"Enable", extensions::disable_reason::DISABLE_USER_ACTION, true, 0, 0},
1452 {"Disable", 0, false, extensions::disable_reason::DISABLE_USER_ACTION,
1453 extensions::disable_reason::DISABLE_USER_ACTION},
1454 {"AddDisableReason", extensions::disable_reason::DISABLE_REMOTE_INSTALL,
1455 false,
1456 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1457 extensions::disable_reason::DISABLE_USER_ACTION,
1458 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1459 extensions::disable_reason::DISABLE_USER_ACTION},
1460 {"RemoveDisableReason",
1461 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1462 extensions::disable_reason::DISABLE_USER_ACTION,
1463 false, extensions::disable_reason::DISABLE_USER_ACTION,
1464 extensions::disable_reason::DISABLE_USER_ACTION},
1465 {"PreserveLocalDisableReason", extensions::disable_reason::DISABLE_RELOAD,
1466 true, 0, extensions::disable_reason::DISABLE_RELOAD},
1467 {"PreserveOnlyLocalDisableReason",
1468 extensions::disable_reason::DISABLE_USER_ACTION |
1469 extensions::disable_reason::DISABLE_RELOAD,
1470 true, 0, extensions::disable_reason::DISABLE_RELOAD},
treib29e1b9b12015-11-11 08:50:561471
Minh X. Nguyen45479012017-08-18 21:35:361472 // Interaction with Chrome clients <=M44, which don't sync disable_reasons
1473 // at all (any existing reasons are preserved).
1474 {"M44Enable", extensions::disable_reason::DISABLE_USER_ACTION, true, -1,
1475 0},
1476 // An M44 client enables an extension that had been disabled on a new
1477 // client. The disable reasons are still be there, but should be ignored.
1478 {"M44ReEnable", extensions::disable_reason::DISABLE_USER_ACTION, true,
1479 extensions::disable_reason::DISABLE_USER_ACTION, 0},
1480 {"M44Disable", 0, false, -1,
1481 extensions::disable_reason::DISABLE_USER_ACTION},
1482 {"M44ReDisable", 0, false, 0,
1483 extensions::disable_reason::DISABLE_USER_ACTION},
1484 {"M44AlreadyDisabledByUser",
1485 extensions::disable_reason::DISABLE_USER_ACTION, false, -1,
1486 extensions::disable_reason::DISABLE_USER_ACTION},
1487 {"M44AlreadyDisabledWithOtherReason",
1488 extensions::disable_reason::DISABLE_REMOTE_INSTALL, false, -1,
1489 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1490 extensions::disable_reason::DISABLE_USER_ACTION},
treib9afc6212015-10-30 18:49:581491 };
1492
1493 for (const TestCase& test_case : test_cases) {
1494 SCOPED_TRACE(test_case.name);
1495
1496 std::string id;
1497 std::string version;
1498 // Don't keep |extension| around longer than necessary.
1499 {
1500 const Extension* extension =
1501 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1502 // The extension should now be installed and enabled.
1503 ASSERT_TRUE(extension);
1504 id = extension->id();
1505 version = extension->VersionString();
1506 }
1507 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1508
1509 // Disable it if the test case says so.
1510 if (test_case.previous_disable_reasons) {
1511 service()->DisableExtension(id, test_case.previous_disable_reasons);
1512 ASSERT_TRUE(registry()->disabled_extensions().Contains(id));
1513 }
1514
1515 // Now a sync update comes in.
1516 sync_pb::EntitySpecifics specifics;
1517 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1518 ext_specifics->set_id(id);
1519 ext_specifics->set_enabled(test_case.sync_enable);
1520 ext_specifics->set_version(version);
1521 if (test_case.sync_disable_reasons != -1)
1522 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1523
treib65f103042015-12-03 10:21:361524 SyncChangeList list =
1525 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1526
treib9afc6212015-10-30 18:49:581527 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1528
1529 // Check expectations.
1530 const bool expect_enabled = !test_case.expect_disable_reasons;
1531 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1532 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
1533
1534 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031535 UninstallExtension(id);
treib9afc6212015-10-30 18:49:581536 }
1537}
1538
Konstantin Ganenkoae1129c2017-09-15 16:28:591539class ExtensionServiceSyncCustomGalleryTest : public ExtensionServiceSyncTest {
1540 public:
1541 void SetUp() override {
1542 ExtensionServiceSyncTest::SetUp();
rdevlin.cronin2f1ed4c2017-06-13 16:22:131543
Konstantin Ganenkoae1129c2017-09-15 16:28:591544 // This is the update URL specified in the permissions test extension.
1545 // Setting it here is necessary to make the extension considered syncable.
1546 extension_test_util::SetGalleryUpdateURL(
1547 GURL("http://localhost/autoupdate/updates.xml"));
1548 }
1549};
1550
1551TEST_F(ExtensionServiceSyncCustomGalleryTest, ProcessSyncDataDeferredEnable) {
treib9afc6212015-10-30 18:49:581552 InitializeEmptyExtensionService();
1553 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361554 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111555 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1556 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581557
1558 base::FilePath base_path = data_dir().AppendASCII("permissions_increase");
1559 base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1560
1561 base::FilePath path = base_path.AppendASCII("v1");
1562 const Extension* extension = PackAndInstallCRX(path, pem_path, INSTALL_NEW);
1563 // The extension must now be installed and enabled.
1564 ASSERT_TRUE(extension);
1565 ASSERT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
1566
1567 // Save the id, as the extension object will be destroyed during updating.
1568 std::string id = extension->id();
1569
1570 // Update to a new version with increased permissions.
1571 path = base_path.AppendASCII("v2");
1572 PackCRXAndUpdateExtension(id, path, pem_path, DISABLED);
1573
1574 // Now a sync update comes in, telling us to re-enable a *newer* version.
1575 sync_pb::EntitySpecifics specifics;
1576 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1577 ext_specifics->set_id(id);
1578 ext_specifics->set_version("3");
1579 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:361580 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:581581
treib65f103042015-12-03 10:21:361582 SyncChangeList list =
1583 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1584
treib9afc6212015-10-30 18:49:581585 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1586
1587 // Since the version didn't match, the extension should still be disabled.
1588 EXPECT_TRUE(registry()->disabled_extensions().Contains(id));
1589
1590 // After we update to the matching version, the extension should get enabled.
1591 path = base_path.AppendASCII("v3");
1592 PackCRXAndUpdateExtension(id, path, pem_path, ENABLED);
1593}
1594
atuchin2eb18eb2017-03-02 07:22:151595TEST_F(ExtensionServiceSyncCustomGalleryTest,
David Bienvenuc44ffd8a2021-04-26 22:27:001596 ProcessSyncDataPermissionApproval) {
treib9afc6212015-10-30 18:49:581597 InitializeEmptyExtensionService();
1598 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361599 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111600 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1601 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581602
1603 const base::FilePath base_path =
1604 data_dir().AppendASCII("permissions_increase");
1605 const base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1606 const base::FilePath path_v1 = base_path.AppendASCII("v1");
1607 const base::FilePath path_v2 = base_path.AppendASCII("v2");
1608
1609 base::ScopedTempDir crx_dir;
1610 ASSERT_TRUE(crx_dir.CreateUniqueTempDir());
vabr9142fe22016-09-08 13:19:221611 const base::FilePath crx_path_v1 = crx_dir.GetPath().AppendASCII("temp1.crx");
treib9afc6212015-10-30 18:49:581612 PackCRX(path_v1, pem_path, crx_path_v1);
vabr9142fe22016-09-08 13:19:221613 const base::FilePath crx_path_v2 = crx_dir.GetPath().AppendASCII("temp2.crx");
treib9afc6212015-10-30 18:49:581614 PackCRX(path_v2, pem_path, crx_path_v2);
1615
1616 const std::string v1("1");
1617 const std::string v2("2");
1618
1619 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1620
1621 struct TestCase {
1622 const char* name; // For failure output only.
1623 const std::string& sync_version; // The version coming in from Sync.
1624 // The disable reason(s) coming in from Sync, or -1 for "not set".
1625 int sync_disable_reasons;
1626 // The expected set of disable reasons after processing the Sync update. The
1627 // extension should be enabled iff this is 0.
1628 int expect_disable_reasons;
1629 // Whether the extension's permissions should be auto-granted.
1630 bool expect_permissions_granted;
1631 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361632 // Sync tells us to re-enable an older version. No permissions should be
1633 // granted, since we can't be sure if the user actually approved the right
1634 // set of permissions.
1635 {"OldVersion", v1, 0,
1636 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
1637 // Legacy case: Sync tells us to re-enable the extension, but doesn't
1638 // specify disable reasons. No permissions should be granted.
1639 {"Legacy", v2, -1,
1640 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
1641 // Sync tells us to re-enable the extension and explicitly removes the
1642 // disable reasons. Now the extension should have its permissions granted.
1643 {"GrantPermissions", v2, 0, extensions::disable_reason::DISABLE_NONE,
1644 true},
treib9afc6212015-10-30 18:49:581645 };
1646
1647 for (const TestCase& test_case : test_cases) {
1648 SCOPED_TRACE(test_case.name);
1649
1650 std::string id;
1651 // Don't keep |extension| around longer than necessary (it'll be destroyed
1652 // during updating).
1653 {
1654 const Extension* extension = InstallCRX(crx_path_v1, INSTALL_NEW);
1655 // The extension should now be installed and enabled.
1656 ASSERT_TRUE(extension);
1657 ASSERT_EQ(v1, extension->VersionString());
1658 id = extension->id();
1659 }
1660 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1661
dchengc963c7142016-04-08 03:55:221662 std::unique_ptr<const PermissionSet> granted_permissions_v1 =
treib9afc6212015-10-30 18:49:581663 prefs->GetGrantedPermissions(id);
1664
1665 // Update to a new version with increased permissions.
1666 UpdateExtension(id, crx_path_v2, DISABLED);
1667
1668 // Now the extension should be disabled due to a permissions increase.
1669 {
1670 const Extension* extension =
1671 registry()->disabled_extensions().GetByID(id);
1672 ASSERT_TRUE(extension);
1673 ASSERT_EQ(v2, extension->VersionString());
1674 }
1675 ASSERT_TRUE(prefs->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:361676 id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE));
treib9afc6212015-10-30 18:49:581677
1678 // No new permissions should have been granted.
dchengc963c7142016-04-08 03:55:221679 std::unique_ptr<const PermissionSet> granted_permissions_v2 =
treib9afc6212015-10-30 18:49:581680 prefs->GetGrantedPermissions(id);
1681 ASSERT_EQ(*granted_permissions_v1, *granted_permissions_v2);
1682
1683 // Now a sync update comes in.
1684 sync_pb::EntitySpecifics specifics;
1685 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1686 ext_specifics->set_id(id);
1687 ext_specifics->set_enabled(true);
1688 ext_specifics->set_version(test_case.sync_version);
1689 if (test_case.sync_disable_reasons != -1)
1690 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1691
treib65f103042015-12-03 10:21:361692 SyncChangeList list =
1693 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1694
treib9afc6212015-10-30 18:49:581695 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1696
1697 // Check expectations.
1698 const bool expect_enabled = !test_case.expect_disable_reasons;
1699 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1700 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
dchengc963c7142016-04-08 03:55:221701 std::unique_ptr<const PermissionSet> granted_permissions =
treib9afc6212015-10-30 18:49:581702 prefs->GetGrantedPermissions(id);
1703 if (test_case.expect_permissions_granted) {
dchengc963c7142016-04-08 03:55:221704 std::unique_ptr<const PermissionSet> active_permissions =
treib9afc6212015-10-30 18:49:581705 prefs->GetActivePermissions(id);
1706 EXPECT_EQ(*granted_permissions, *active_permissions);
1707 } else {
1708 EXPECT_EQ(*granted_permissions, *granted_permissions_v1);
1709 }
1710
1711 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031712 UninstallExtension(id);
treib9afc6212015-10-30 18:49:581713 }
1714}
1715
treib227b2582015-12-09 09:28:261716// Regression test for crbug.com/558299
1717TEST_F(ExtensionServiceSyncTest, DontSyncThemes) {
1718 InitializeEmptyExtensionService();
1719
1720 // The user has enabled sync.
Victor Hugo Vianna Silvaff4e5f6e2021-06-01 20:12:141721 SyncServiceFactory::GetForProfile(profile())
Marc Treib9948a682018-11-20 08:01:371722 ->GetUserSettings()
Tanmoy Mollik0960d702019-09-11 15:14:471723 ->SetFirstSetupComplete(kSetSourceFromTest);
treib227b2582015-12-09 09:28:261724 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
1725 extension_sync_service();
1726
1727 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:021728 ASSERT_TRUE(extension_system()->is_ready());
treib227b2582015-12-09 09:28:261729
1730 syncer::FakeSyncChangeProcessor* processor =
1731 new syncer::FakeSyncChangeProcessor;
1732 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:221733 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
1734 base::WrapUnique(new syncer::SyncErrorFactoryMock));
treib227b2582015-12-09 09:28:261735
1736 processor->changes().clear();
1737
1738 // Sanity check: Installing an extension should result in a sync change.
1739 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1740 EXPECT_EQ(1u, processor->changes().size());
1741
1742 processor->changes().clear();
1743
1744 // Installing a theme should not result in a sync change (themes are handled
1745 // separately by ThemeSyncableService).
Tommy Steimel2dffd3c2021-03-10 23:27:211746 test::ThemeServiceChangedWaiter waiter(
1747 ThemeServiceFactory::GetForProfile(profile()));
treib227b2582015-12-09 09:28:261748 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
Tommy Steimel2dffd3c2021-03-10 23:27:211749 waiter.WaitForThemeChanged();
treib227b2582015-12-09 09:28:261750 EXPECT_TRUE(processor->changes().empty());
1751}
1752
Toby Huang63a8d712019-11-27 20:07:321753// Tests sync behavior in the case of an item that starts out as an app and gets
1754// updated to become an extension.
asargente48ab752016-03-12 00:59:201755TEST_F(ExtensionServiceSyncTest, AppToExtension) {
1756 InitializeEmptyExtensionService();
1757 service()->Init();
Ghazale Hosseinabadi1d810e92020-06-01 20:43:021758 ASSERT_TRUE(extension_system()->is_ready());
asargente48ab752016-03-12 00:59:201759
1760 // Install v1, which is an app.
1761 const Extension* v1 =
1762 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v1.crx"),
1763 INSTALL_NEW);
1764 EXPECT_TRUE(v1->is_app());
1765 EXPECT_FALSE(v1->is_extension());
1766 std::string id = v1->id();
1767
1768 StatefulChangeProcessor extensions_processor(syncer::ModelType::EXTENSIONS);
1769 StatefulChangeProcessor apps_processor(syncer::ModelType::APPS);
1770 extension_sync_service()->MergeDataAndStartSyncing(
1771 syncer::EXTENSIONS, syncer::SyncDataList(),
1772 extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221773 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201774 extension_sync_service()->MergeDataAndStartSyncing(
1775 syncer::APPS, syncer::SyncDataList(), apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221776 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201777
1778 // Check the app/extension change processors to be sure the right data was
1779 // added.
1780 EXPECT_TRUE(extensions_processor.changes().empty());
1781 EXPECT_TRUE(extensions_processor.data().empty());
1782 EXPECT_EQ(1u, apps_processor.data().size());
1783 ASSERT_EQ(1u, apps_processor.changes().size());
1784 const SyncChange& app_change = apps_processor.changes()[0];
1785 EXPECT_EQ(SyncChange::ACTION_ADD, app_change.change_type());
dchengc963c7142016-04-08 03:55:221786 std::unique_ptr<ExtensionSyncData> app_data =
asargente48ab752016-03-12 00:59:201787 ExtensionSyncData::CreateFromSyncData(app_change.sync_data());
1788 EXPECT_TRUE(app_data->is_app());
1789 EXPECT_EQ(id, app_data->id());
Devlin Cronin03bf2d22017-12-20 08:21:051790 EXPECT_EQ(v1->version(), app_data->version());
asargente48ab752016-03-12 00:59:201791
1792 // Update the app to v2, which is an extension.
1793 const Extension* v2 =
1794 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v2.crx"),
1795 INSTALL_UPDATED);
1796 EXPECT_FALSE(v2->is_app());
1797 EXPECT_TRUE(v2->is_extension());
1798 EXPECT_EQ(id, v2->id());
1799
1800 // Make sure we saw an extension item added.
1801 ASSERT_EQ(1u, extensions_processor.changes().size());
1802 const SyncChange& extension_change = extensions_processor.changes()[0];
1803 EXPECT_EQ(SyncChange::ACTION_ADD, extension_change.change_type());
dchengc963c7142016-04-08 03:55:221804 std::unique_ptr<ExtensionSyncData> extension_data =
asargente48ab752016-03-12 00:59:201805 ExtensionSyncData::CreateFromSyncData(extension_change.sync_data());
1806 EXPECT_FALSE(extension_data->is_app());
1807 EXPECT_EQ(id, extension_data->id());
Devlin Cronin03bf2d22017-12-20 08:21:051808 EXPECT_EQ(v2->version(), extension_data->version());
asargente48ab752016-03-12 00:59:201809
1810 // Get the current data from the change processors to use as the input to
1811 // the following call to MergeDataAndStartSyncing. This simulates what should
1812 // happen with sync.
Mikel Astiz3001dd82021-07-19 12:40:001813 syncer::SyncDataList extensions_data = extensions_processor.data();
1814 syncer::SyncDataList apps_data = apps_processor.data();
asargente48ab752016-03-12 00:59:201815
1816 // Stop syncing, then start again.
1817 extension_sync_service()->StopSyncing(syncer::EXTENSIONS);
1818 extension_sync_service()->StopSyncing(syncer::APPS);
1819 extension_sync_service()->MergeDataAndStartSyncing(
1820 syncer::EXTENSIONS, extensions_data, extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221821 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201822 extension_sync_service()->MergeDataAndStartSyncing(
1823 syncer::APPS, apps_data, apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:221824 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:201825
1826 // Make sure we saw an app item deleted.
1827 bool found_delete = false;
1828 for (const auto& change : apps_processor.changes()) {
1829 if (change.change_type() == SyncChange::ACTION_DELETE) {
dchengc963c7142016-04-08 03:55:221830 std::unique_ptr<ExtensionSyncData> data =
asargente48ab752016-03-12 00:59:201831 ExtensionSyncData::CreateFromSyncChange(change);
1832 if (data->id() == id) {
1833 found_delete = true;
1834 break;
1835 }
1836 }
1837 }
1838 EXPECT_TRUE(found_delete);
1839
1840 // Make sure there is one extension, and there are no more apps.
1841 EXPECT_EQ(1u, extensions_processor.data().size());
1842 EXPECT_TRUE(apps_processor.data().empty());
1843}
proberge901ecab2017-08-31 19:24:281844
[email protected]950f2952020-07-10 03:35:501845class BlocklistedExtensionSyncServiceTest : public ExtensionServiceSyncTest {
proberge901ecab2017-08-31 19:24:281846 public:
[email protected]950f2952020-07-10 03:35:501847 BlocklistedExtensionSyncServiceTest() {}
proberge901ecab2017-08-31 19:24:281848
1849 void SetUp() override {
1850 ExtensionServiceSyncTest::SetUp();
1851
1852 InitializeEmptyExtensionService();
1853
1854 // Enable sync.
Marc Treib5a78e9c2019-02-19 16:47:011855 syncer::SyncService* sync_service =
Victor Hugo Vianna Silvaff4e5f6e2021-06-01 20:12:141856 SyncServiceFactory::GetForProfile(profile());
Tanmoy Mollik0960d702019-09-11 15:14:471857 sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
proberge901ecab2017-08-31 19:24:281858
[email protected]950f2952020-07-10 03:35:501859 test_blocklist_.Attach(service()->blocklist_);
proberge901ecab2017-08-31 19:24:281860 service()->Init();
1861
1862 // Load up a simple extension.
1863 extensions::ChromeTestExtensionLoader extension_loader(profile());
1864 extension_loader.set_pack_extension(true);
1865 extension_ = extension_loader.LoadExtension(
1866 data_dir().AppendASCII("simple_with_file"));
1867 ASSERT_TRUE(extension_);
1868 extension_id_ = extension_->id();
1869 ASSERT_TRUE(registry()->enabled_extensions().GetByID(extension_id_));
1870
1871 {
Jinho Bangb5216cec2018-01-17 19:43:111872 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
proberge901ecab2017-08-31 19:24:281873 processor_raw_ = processor.get();
1874 extension_sync_service()->MergeDataAndStartSyncing(
1875 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:111876 std::make_unique<syncer::SyncErrorFactoryMock>());
proberge901ecab2017-08-31 19:24:281877 }
1878 processor_raw_->changes().clear();
1879 }
1880
[email protected]950f2952020-07-10 03:35:501881 void ForceBlocklistUpdate() {
1882 service()->OnBlocklistUpdated();
Gabriel Charette01507a22017-09-27 21:30:081883 content::RunAllTasksUntilIdle();
proberge901ecab2017-08-31 19:24:281884 }
1885
1886 syncer::FakeSyncChangeProcessor* processor() { return processor_raw_; }
1887
1888 const Extension* extension() { return extension_.get(); }
1889
1890 std::string& extension_id() { return extension_id_; }
1891
[email protected]950f2952020-07-10 03:35:501892 extensions::TestBlocklist& test_blocklist() { return test_blocklist_; }
proberge901ecab2017-08-31 19:24:281893
1894 private:
1895 syncer::FakeSyncChangeProcessor* processor_raw_;
1896 scoped_refptr<const Extension> extension_;
1897 std::string extension_id_;
[email protected]950f2952020-07-10 03:35:501898 extensions::TestBlocklist test_blocklist_;
proberge901ecab2017-08-31 19:24:281899
[email protected]950f2952020-07-10 03:35:501900 DISALLOW_COPY_AND_ASSIGN(BlocklistedExtensionSyncServiceTest);
proberge901ecab2017-08-31 19:24:281901};
1902
[email protected]950f2952020-07-10 03:35:501903// Test that sync cannot enable blocklisted extensions.
1904TEST_F(BlocklistedExtensionSyncServiceTest, SyncBlocklistedExtension) {
proberge901ecab2017-08-31 19:24:281905 std::string& extension_id = this->extension_id();
1906
[email protected]950f2952020-07-10 03:35:501907 // Blocklist the extension.
1908 test_blocklist().SetBlocklistState(extension_id,
[email protected]321b9292020-06-26 01:20:461909 extensions::BLOCKLISTED_MALWARE, true);
[email protected]950f2952020-07-10 03:35:501910 ForceBlocklistUpdate();
proberge901ecab2017-08-31 19:24:281911
1912 // Try enabling the extension via sync.
1913 EnableExtensionFromSync(*extension());
1914
1915 // The extension should not be enabled.
1916 EXPECT_FALSE(registry()->enabled_extensions().GetByID(extension_id));
1917 EXPECT_TRUE(processor()->changes().empty());
1918}
1919
1920// Test that some greylisted extensions can be enabled through sync.
[email protected]950f2952020-07-10 03:35:501921TEST_F(BlocklistedExtensionSyncServiceTest, SyncAllowedGreylistedExtension) {
proberge901ecab2017-08-31 19:24:281922 std::string& extension_id = this->extension_id();
1923
1924 // Greylist the extension.
[email protected]950f2952020-07-10 03:35:501925 test_blocklist().SetBlocklistState(
[email protected]321b9292020-06-26 01:20:461926 extension_id, extensions::BLOCKLISTED_POTENTIALLY_UNWANTED, true);
[email protected]950f2952020-07-10 03:35:501927 ForceBlocklistUpdate();
proberge901ecab2017-08-31 19:24:281928
1929 EXPECT_FALSE(registry()->enabled_extensions().GetByID(extension_id));
1930 {
1931 ASSERT_EQ(1u, processor()->changes().size());
1932 const SyncChange& change = processor()->changes()[0];
1933 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
1934 std::unique_ptr<ExtensionSyncData> data =
1935 ExtensionSyncData::CreateFromSyncData(change.sync_data());
1936 EXPECT_EQ(extension_id, data->id());
1937 EXPECT_EQ(extensions::disable_reason::DISABLE_GREYLIST,
1938 data->disable_reasons());
1939 EXPECT_FALSE(data->enabled());
1940 }
1941 processor()->changes().clear();
1942
1943 // Manually re-enabling the extension should work.
1944 service()->EnableExtension(extension_id);
1945 EXPECT_TRUE(registry()->enabled_extensions().GetByID(extension_id));
1946 {
1947 ASSERT_EQ(1u, processor()->changes().size());
1948 const SyncChange& change = processor()->changes()[0];
1949 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
1950 std::unique_ptr<ExtensionSyncData> data =
1951 ExtensionSyncData::CreateFromSyncData(change.sync_data());
1952 EXPECT_EQ(extension_id, data->id());
1953 EXPECT_EQ(0, data->disable_reasons());
1954 EXPECT_TRUE(data->enabled());
1955 }
1956 processor()->changes().clear();
1957}