blob: fce18695b1a5bddbafac5fb2e946c309c0c4cc17 [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"
avia2f4804a2015-12-24 23:11:1315#include "base/macros.h"
dchengc963c7142016-04-08 03:55:2216#include "base/memory/ptr_util.h"
treib9afc6212015-10-30 18:49:5817#include "base/memory/weak_ptr.h"
18#include "base/metrics/field_trial.h"
19#include "base/test/mock_entropy_provider.h"
asvitkineb1db8262016-11-08 09:48:2020#include "base/test/scoped_feature_list.h"
Evan Stade46d716d2017-06-02 20:50:0921#include "chrome/browser/chrome_notification_types.h"
mamirf7715a2a2016-07-04 13:05:0822#include "chrome/browser/extensions/api/webstore_private/webstore_private_api.h"
rdevlin.cronin2f1ed4c2017-06-13 16:22:1323#include "chrome/browser/extensions/chrome_test_extension_loader.h"
treib9afc6212015-10-30 18:49:5824#include "chrome/browser/extensions/component_loader.h"
25#include "chrome/browser/extensions/extension_service.h"
26#include "chrome/browser/extensions/extension_service_test_with_install.h"
27#include "chrome/browser/extensions/extension_sync_data.h"
28#include "chrome/browser/extensions/extension_sync_service.h"
29#include "chrome/browser/extensions/extension_util.h"
rdevlin.cronind01837b2016-08-17 01:37:1830#include "chrome/browser/extensions/scripting_permissions_modifier.h"
proberge901ecab2017-08-31 19:24:2831#include "chrome/browser/extensions/test_blacklist.h"
treib9afc6212015-10-30 18:49:5832#include "chrome/browser/extensions/updater/extension_updater.h"
treib9afc6212015-10-30 18:49:5833#include "chrome/browser/sync/profile_sync_service_factory.h"
Evan Stade46d716d2017-06-02 20:50:0934#include "chrome/browser/themes/theme_service.h"
35#include "chrome/browser/themes/theme_service_factory.h"
treib9afc6212015-10-30 18:49:5836#include "chrome/common/chrome_constants.h"
Konstantin Ganenkoae1129c2017-09-15 16:28:5937#include "chrome/common/extensions/extension_test_util.h"
treib9afc6212015-10-30 18:49:5838#include "chrome/common/extensions/sync_helper.h"
brettw9e85ef42016-11-01 21:01:2439#include "chrome/common/features.h"
treib9afc6212015-10-30 18:49:5840#include "chrome/test/base/testing_profile.h"
maxbogue26f40222016-09-16 20:22:1841#include "components/browser_sync/profile_sync_service.h"
rdevlin.cronin738501d2015-11-05 21:51:3642#include "components/crx_file/id_util.h"
skym71603842016-10-10 18:17:3143#include "components/sync/model/fake_sync_change_processor.h"
44#include "components/sync/model/sync_change_processor_wrapper_for_test.h"
45#include "components/sync/model/sync_data.h"
46#include "components/sync/model/sync_error_factory_mock.h"
treibb6af28cd2015-12-01 11:19:4647#include "components/variations/variations_associated_data.h"
mamirf7715a2a2016-07-04 13:05:0848#include "extensions/browser/api_test_utils.h"
treib9afc6212015-10-30 18:49:5849#include "extensions/browser/app_sorting.h"
Devlin Croninbffe949eb2018-01-12 03:03:4050#include "extensions/browser/disable_reason.h"
treib9afc6212015-10-30 18:49:5851#include "extensions/browser/extension_prefs.h"
52#include "extensions/browser/extension_registry.h"
53#include "extensions/browser/extension_system.h"
karandeepb810e33402017-04-05 23:41:2254#include "extensions/browser/extension_util.h"
treib9afc6212015-10-30 18:49:5855#include "extensions/browser/management_policy.h"
56#include "extensions/browser/test_management_policy.h"
rdevlin.cronin738501d2015-11-05 21:51:3657#include "extensions/common/extension_builder.h"
treib9afc6212015-10-30 18:49:5858#include "extensions/common/manifest_url_handlers.h"
59#include "extensions/common/permissions/permission_set.h"
treib9afc6212015-10-30 18:49:5860#include "testing/gtest/include/gtest/gtest.h"
61
brettw9e85ef42016-11-01 21:01:2462#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
treib9afc6212015-10-30 18:49:5863#include "chrome/browser/supervised_user/permission_request_creator.h"
64#include "chrome/browser/supervised_user/supervised_user_constants.h"
mamire9609642016-06-28 22:17:5465#include "chrome/browser/supervised_user/supervised_user_features.h"
treib9afc6212015-10-30 18:49:5866#include "chrome/browser/supervised_user/supervised_user_service.h"
67#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
mamire9609642016-06-28 22:17:5468#include "chrome/browser/supervised_user/supervised_user_settings_service.h"
69#include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
70#include "chrome/common/pref_names.h"
treib9afc6212015-10-30 18:49:5871#endif
72
mamirf7715a2a2016-07-04 13:05:0873using extensions::api_test_utils::RunFunctionAndReturnSingleResult;
treib9afc6212015-10-30 18:49:5874using extensions::AppSorting;
75using extensions::Extension;
76using extensions::ExtensionPrefs;
77using extensions::ExtensionSyncData;
78using extensions::ExtensionSystem;
79using extensions::Manifest;
80using extensions::PermissionSet;
rdevlin.cronind01837b2016-08-17 01:37:1881using extensions::ScriptingPermissionsModifier;
mamirf7715a2a2016-07-04 13:05:0882using extensions::WebstorePrivateIsPendingCustodianApprovalFunction;
treib65f103042015-12-03 10:21:3683using syncer::SyncChange;
84using syncer::SyncChangeList;
mamire9609642016-06-28 22:17:5485using testing::Mock;
treib65f103042015-12-03 10:21:3686
87namespace {
treib9afc6212015-10-30 18:49:5888
mamir192d7882016-06-22 17:10:1689const char autoupdate[] = "ogjcoiohnmldgjemafoockdghcjciccf";
treib9afc6212015-10-30 18:49:5890const char good0[] = "behllobkkfkfnphdnhnkndlbkcpglgmj";
91const char good2[] = "bjafgdebaacbbbecmhlhpofkepfkgcpa";
mamir192d7882016-06-22 17:10:1692const char good2048[] = "nmgjhmhbleinmjpbdhgajfjkbijcmgbh";
treib9afc6212015-10-30 18:49:5893const char good_crx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
94const char page_action[] = "obcimlgaoabeegjmmpldobjndiealpln";
mamir192d7882016-06-22 17:10:1695const char permissions_increase[] = "pgdpcfcocojkjfbgpiianjngphoopgmo";
treib9afc6212015-10-30 18:49:5896const char theme2_crx[] = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf";
97
rdevlin.cronin2f1ed4c2017-06-13 16:22:1398ExtensionSyncData GetDisableSyncData(const Extension& extension,
99 int disable_reasons) {
100 bool enabled = false;
101 bool incognito_enabled = false;
102 bool remote_install = false;
103 bool installed_by_custodian = false;
104 ExtensionSyncData::OptionalBoolean has_all_urls =
105 ExtensionSyncData::BOOLEAN_UNSET;
106 return ExtensionSyncData(extension, enabled, disable_reasons,
107 incognito_enabled, remote_install, has_all_urls,
108 installed_by_custodian);
109}
110
111ExtensionSyncData GetEnableSyncData(const Extension& extension) {
112 bool enabled = true;
113 bool incognito_enabled = false;
114 bool remote_install = false;
115 bool installed_by_custodian = false;
116 ExtensionSyncData::OptionalBoolean has_all_urls =
117 ExtensionSyncData::BOOLEAN_UNSET;
Minh X. Nguyen45479012017-08-18 21:35:36118 return ExtensionSyncData(
119 extension, enabled, extensions::disable_reason::DISABLE_NONE,
120 incognito_enabled, remote_install, has_all_urls, installed_by_custodian);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13121}
122
treib65f103042015-12-03 10:21:36123SyncChangeList MakeSyncChangeList(const std::string& id,
124 const sync_pb::EntitySpecifics& specifics,
125 SyncChange::SyncChangeType change_type) {
126 syncer::SyncData sync_data =
127 syncer::SyncData::CreateLocalData(id, "Name", specifics);
128 return SyncChangeList(1, SyncChange(FROM_HERE, change_type, sync_data));
129}
130
asargente48ab752016-03-12 00:59:20131// This is a FakeSyncChangeProcessor specialization that maintains a store of
132// SyncData items in the superclass' data_ member variable, treating it like a
133// map keyed by the extension id from the SyncData. Each instance of this class
134// should only be used for one model type (which should be either extensions or
135// apps) to match how the real sync system handles things.
136class StatefulChangeProcessor : public syncer::FakeSyncChangeProcessor {
137 public:
138 explicit StatefulChangeProcessor(syncer::ModelType expected_type)
139 : expected_type_(expected_type) {
140 EXPECT_TRUE(expected_type == syncer::ModelType::EXTENSIONS ||
141 expected_type == syncer::ModelType::APPS);
142 }
143
144 ~StatefulChangeProcessor() override {}
145
146 // We let our parent class, FakeSyncChangeProcessor, handle saving the
147 // changes for us, but in addition we "apply" these changes by treating
148 // the FakeSyncChangeProcessor's SyncDataList as a map keyed by extension
149 // id.
150 syncer::SyncError ProcessSyncChanges(
Brett Wilsone1a70422017-09-12 05:10:09151 const base::Location& from_here,
asargente48ab752016-03-12 00:59:20152 const syncer::SyncChangeList& change_list) override {
153 syncer::FakeSyncChangeProcessor::ProcessSyncChanges(from_here, change_list);
154 for (const auto& change : change_list) {
155 syncer::SyncData sync_data = change.sync_data();
156 EXPECT_EQ(expected_type_, sync_data.GetDataType());
157
dchengc963c7142016-04-08 03:55:22158 std::unique_ptr<ExtensionSyncData> modified =
asargente48ab752016-03-12 00:59:20159 ExtensionSyncData::CreateFromSyncData(sync_data);
160
161 // Start by removing any existing entry for this extension id.
162 syncer::SyncDataList& data_list = data();
163 for (auto iter = data_list.begin(); iter != data_list.end(); ++iter) {
dchengc963c7142016-04-08 03:55:22164 std::unique_ptr<ExtensionSyncData> existing =
asargente48ab752016-03-12 00:59:20165 ExtensionSyncData::CreateFromSyncData(*iter);
166 if (existing->id() == modified->id()) {
167 data_list.erase(iter);
168 break;
169 }
170 }
171
172 // Now add in the new data for this id, if appropriate.
173 if (change.change_type() == SyncChange::ACTION_ADD ||
174 change.change_type() == SyncChange::ACTION_UPDATE) {
175 data_list.push_back(sync_data);
176 } else if (change.change_type() != SyncChange::ACTION_DELETE) {
177 ADD_FAILURE() << "Unexpected change type " << change.change_type();
178 }
179 }
180 return syncer::SyncError();
181 }
182
183 // We override this to help catch the error of trying to use a single
184 // StatefulChangeProcessor to process changes for both extensions and apps
185 // sync data.
186 syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override {
187 EXPECT_EQ(expected_type_, type);
188 return FakeSyncChangeProcessor::GetAllSyncData(type);
189 }
190
191 // This is a helper to vend a wrapped version of this object suitable for
192 // passing in to MergeDataAndStartSyncing, which takes a
dchengc963c7142016-04-08 03:55:22193 // std::unique_ptr<SyncChangeProcessor>, since in tests we typically don't
194 // want to
asargente48ab752016-03-12 00:59:20195 // give up ownership of a local change processor.
dchengc963c7142016-04-08 03:55:22196 std::unique_ptr<syncer::SyncChangeProcessor> GetWrapped() {
Jinho Bangb5216cec2018-01-17 19:43:11197 return std::make_unique<syncer::SyncChangeProcessorWrapperForTest>(this);
asargente48ab752016-03-12 00:59:20198 }
199
200 protected:
201 // The expected ModelType of changes that this processor will see.
202 syncer::ModelType expected_type_;
203
204 DISALLOW_COPY_AND_ASSIGN(StatefulChangeProcessor);
205};
206
treib65f103042015-12-03 10:21:36207} // namespace
208
treib9afc6212015-10-30 18:49:58209class ExtensionServiceSyncTest
210 : public extensions::ExtensionServiceTestWithInstall {
211 public:
212 void MockSyncStartFlare(bool* was_called,
213 syncer::ModelType* model_type_passed_in,
214 syncer::ModelType model_type) {
215 *was_called = true;
216 *model_type_passed_in = model_type;
217 }
218
asargente48ab752016-03-12 00:59:20219 // Helper to call MergeDataAndStartSyncing with no server data and dummy
220 // change processor / error factory.
221 void StartSyncing(syncer::ModelType type) {
222 ASSERT_TRUE(type == syncer::EXTENSIONS || type == syncer::APPS);
223 extension_sync_service()->MergeDataAndStartSyncing(
224 type, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11225 std::make_unique<syncer::FakeSyncChangeProcessor>(),
226 std::make_unique<syncer::SyncErrorFactoryMock>());
asargente48ab752016-03-12 00:59:20227 }
228
rdevlin.cronin2f1ed4c2017-06-13 16:22:13229 void DisableExtensionFromSync(const Extension& extension,
230 int disable_reasons) {
Minh X. Nguyen45479012017-08-18 21:35:36231 ExtensionSyncData disable_extension = GetDisableSyncData(
232 extension, extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13233 SyncChangeList list(
234 1, disable_extension.GetSyncChange(SyncChange::ACTION_UPDATE));
235 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
236 }
237
238 void EnableExtensionFromSync(const Extension& extension) {
239 ExtensionSyncData enable_extension = GetEnableSyncData(extension);
240 SyncChangeList list(
241 1, enable_extension.GetSyncChange(SyncChange::ACTION_UPDATE));
242 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
243 }
244
treib9afc6212015-10-30 18:49:58245 protected:
246 // Paths to some of the fake extensions.
247 base::FilePath good0_path() {
248 return data_dir()
249 .AppendASCII("good")
250 .AppendASCII("Extensions")
251 .AppendASCII(good0)
252 .AppendASCII("1.0.0.0");
253 }
254
255 ExtensionSyncService* extension_sync_service() {
256 return ExtensionSyncService::Get(profile());
257 }
258};
259
260TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledComponent) {
261 InitializeEmptyExtensionService();
262
263 bool flare_was_called = false;
264 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
265 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
266 extension_sync_service()->SetSyncStartFlareForTesting(
267 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
268 factory.GetWeakPtr(),
269 &flare_was_called, // Safe due to WeakPtrFactory scope.
270 &triggered_type)); // Safe due to WeakPtrFactory scope.
271
272 // Install a component extension.
273 std::string manifest;
274 ASSERT_TRUE(base::ReadFileToString(
275 good0_path().Append(extensions::kManifestFilename), &manifest));
276 service()->component_loader()->Add(manifest, good0_path());
277 ASSERT_FALSE(service()->is_ready());
278 service()->Init();
279 ASSERT_TRUE(service()->is_ready());
280
281 // Extensions added before service is_ready() don't trigger sync startup.
282 EXPECT_FALSE(flare_was_called);
283 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
284}
285
286TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledNormal) {
287 InitializeGoodInstalledExtensionService();
288
289 bool flare_was_called = false;
290 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
291 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
292 extension_sync_service()->SetSyncStartFlareForTesting(
293 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
294 factory.GetWeakPtr(),
295 &flare_was_called, // Safe due to WeakPtrFactory scope.
296 &triggered_type)); // Safe due to WeakPtrFactory scope.
297
298 ASSERT_FALSE(service()->is_ready());
299 service()->Init();
300 ASSERT_EQ(3u, loaded_.size());
301 ASSERT_TRUE(service()->is_ready());
302
303 // Extensions added before service is_ready() don't trigger sync startup.
304 EXPECT_FALSE(flare_was_called);
305 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
306}
307
308TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupOnInstall) {
309 InitializeEmptyExtensionService();
310 service()->Init();
311 ASSERT_TRUE(service()->is_ready());
312
313 bool flare_was_called = false;
314 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
315 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
316 extension_sync_service()->SetSyncStartFlareForTesting(
317 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
318 factory.GetWeakPtr(),
319 &flare_was_called, // Safe due to WeakPtrFactory scope.
320 &triggered_type)); // Safe due to WeakPtrFactory scope.
321
322 base::FilePath path = data_dir().AppendASCII("good.crx");
323 InstallCRX(path, INSTALL_NEW);
324
325 EXPECT_TRUE(flare_was_called);
326 EXPECT_EQ(syncer::EXTENSIONS, triggered_type);
327
328 // Reset.
329 flare_was_called = false;
330 triggered_type = syncer::UNSPECIFIED;
331
332 // Once sync starts, flare should no longer be invoked.
333 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36334 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11335 std::make_unique<syncer::FakeSyncChangeProcessor>(),
336 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58337 path = data_dir().AppendASCII("page_action.crx");
338 InstallCRX(path, INSTALL_NEW);
339 EXPECT_FALSE(flare_was_called);
340 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
341}
342
343TEST_F(ExtensionServiceSyncTest, DisableExtensionFromSync) {
344 // Start the extensions service with one external extension already installed.
345 base::FilePath source_install_dir =
346 data_dir().AppendASCII("good").AppendASCII("Extensions");
347 base::FilePath pref_path =
348 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
349
350 InitializeInstalledExtensionService(pref_path, source_install_dir);
351
352 // The user has enabled sync.
maxbogue0a379452016-09-22 21:35:05353 browser_sync::ProfileSyncService* sync_service =
treib9afc6212015-10-30 18:49:58354 ProfileSyncServiceFactory::GetForProfile(profile());
maxboguefe00952a2016-01-19 19:02:01355 sync_service->SetFirstSetupComplete();
treib9afc6212015-10-30 18:49:58356
357 service()->Init();
358 ASSERT_TRUE(service()->is_ready());
359
360 ASSERT_EQ(3u, loaded_.size());
361
362 // We start enabled.
363 const Extension* extension = service()->GetExtensionById(good0, true);
364 ASSERT_TRUE(extension);
365 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
366
367 // Sync starts up.
368 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36369 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11370 std::make_unique<syncer::FakeSyncChangeProcessor>(),
371 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58372
373 // Then sync data arrives telling us to disable |good0|.
Minh X. Nguyen45479012017-08-18 21:35:36374 ExtensionSyncData disable_good_crx(
375 *extension, false, extensions::disable_reason::DISABLE_USER_ACTION, false,
376 false, ExtensionSyncData::BOOLEAN_UNSET, false);
treib65f103042015-12-03 10:21:36377 SyncChangeList list(
378 1, disable_good_crx.GetSyncChange(SyncChange::ACTION_UPDATE));
treib9afc6212015-10-30 18:49:58379 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
380
381 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
382}
383
rdevlin.cronin2f1ed4c2017-06-13 16:22:13384// Test that sync can enable and disable installed extensions.
385TEST_F(ExtensionServiceSyncTest, ReenableDisabledExtensionFromSync) {
386 InitializeEmptyExtensionService();
387
388 // Enable sync.
389 browser_sync::ProfileSyncService* sync_service =
390 ProfileSyncServiceFactory::GetForProfile(profile());
391 sync_service->SetFirstSetupComplete();
392
393 service()->Init();
394
395 // Load up a simple extension.
396 extensions::ChromeTestExtensionLoader extension_loader(profile());
397 extension_loader.set_pack_extension(true);
398 scoped_refptr<const Extension> extension = extension_loader.LoadExtension(
399 data_dir().AppendASCII("simple_with_file"));
400 ASSERT_TRUE(extension);
401 const std::string kExtensionId = extension->id();
402 ASSERT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
403
404 syncer::FakeSyncChangeProcessor* processor_raw = nullptr;
405 {
Jinho Bangb5216cec2018-01-17 19:43:11406 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
rdevlin.cronin2f1ed4c2017-06-13 16:22:13407 processor_raw = processor.get();
408 extension_sync_service()->MergeDataAndStartSyncing(
409 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:11410 std::make_unique<syncer::SyncErrorFactoryMock>());
rdevlin.cronin2f1ed4c2017-06-13 16:22:13411 }
412 processor_raw->changes().clear();
413
Minh X. Nguyen45479012017-08-18 21:35:36414 DisableExtensionFromSync(*extension,
415 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13416
417 // The extension should be disabled.
418 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
Minh X. Nguyen45479012017-08-18 21:35:36419 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
rdevlin.cronin2f1ed4c2017-06-13 16:22:13420 ExtensionPrefs::Get(profile())->GetDisableReasons(kExtensionId));
421 EXPECT_TRUE(processor_raw->changes().empty());
422
423 // Enable the extension. Sync should push the new state.
424 service()->EnableExtension(kExtensionId);
425 {
426 ASSERT_EQ(1u, processor_raw->changes().size());
427 const SyncChange& change = processor_raw->changes()[0];
428 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
429 std::unique_ptr<ExtensionSyncData> data =
430 ExtensionSyncData::CreateFromSyncData(change.sync_data());
431 EXPECT_EQ(kExtensionId, data->id());
432 EXPECT_EQ(0, data->disable_reasons());
433 EXPECT_TRUE(data->enabled());
434 }
435
436 // Disable the extension again. Sync should push the new state.
437 processor_raw->changes().clear();
Minh X. Nguyen45479012017-08-18 21:35:36438 service()->DisableExtension(kExtensionId,
439 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13440 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
441 {
442 ASSERT_EQ(1u, processor_raw->changes().size());
443 const SyncChange& change = processor_raw->changes()[0];
444 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
445 std::unique_ptr<ExtensionSyncData> data =
446 ExtensionSyncData::CreateFromSyncData(change.sync_data());
447 EXPECT_EQ(kExtensionId, data->id());
Minh X. Nguyen45479012017-08-18 21:35:36448 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
449 data->disable_reasons());
rdevlin.cronin2f1ed4c2017-06-13 16:22:13450 EXPECT_FALSE(data->enabled());
451 }
452 processor_raw->changes().clear();
453
454 // Enable the extension via sync.
455 EnableExtensionFromSync(*extension);
456
457 // The extension should be enabled.
458 EXPECT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
459 EXPECT_TRUE(processor_raw->changes().empty());
460}
461
462// Tests that default-installed extensions won't be affected by incoming sync
463// data. (It's feasible to have a sync entry for an extension that could be
464// default installed, since one installation may be default-installed while
465// another may not be).
466TEST_F(ExtensionServiceSyncTest,
467 DefaultInstalledExtensionsAreNotReenabledOrDisabledBySync) {
468 InitializeEmptyExtensionService();
469
470 // Enable sync.
471 browser_sync::ProfileSyncService* sync_service =
472 ProfileSyncServiceFactory::GetForProfile(profile());
473 sync_service->SetFirstSetupComplete();
474
475 service()->Init();
476
477 // Load up an extension that's considered default installed.
478 extensions::ChromeTestExtensionLoader extension_loader(profile());
479 extension_loader.set_pack_extension(true);
480 extension_loader.add_creation_flag(Extension::WAS_INSTALLED_BY_DEFAULT);
481 scoped_refptr<const Extension> extension = extension_loader.LoadExtension(
482 data_dir().AppendASCII("simple_with_file"));
483 ASSERT_TRUE(extension);
484
485 // The extension shouldn't sync.
486 EXPECT_FALSE(extensions::util::ShouldSync(extension.get(), profile()));
487 const std::string kExtensionId = extension->id();
488 ASSERT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
489
490 syncer::FakeSyncChangeProcessor* processor_raw = nullptr;
491 {
Jinho Bangb5216cec2018-01-17 19:43:11492 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
rdevlin.cronin2f1ed4c2017-06-13 16:22:13493 processor_raw = processor.get();
494 extension_sync_service()->MergeDataAndStartSyncing(
495 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:11496 std::make_unique<syncer::SyncErrorFactoryMock>());
rdevlin.cronin2f1ed4c2017-06-13 16:22:13497 }
498 processor_raw->changes().clear();
499
500 // Sync state says the extension is disabled (e.g. on another machine).
Minh X. Nguyen45479012017-08-18 21:35:36501 DisableExtensionFromSync(*extension,
502 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13503
504 // The extension should still be enabled, since it's default-installed.
505 EXPECT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
506 EXPECT_TRUE(processor_raw->changes().empty());
507
508 // Now disable the extension locally. Sync should *not* push new state.
Minh X. Nguyen45479012017-08-18 21:35:36509 service()->DisableExtension(kExtensionId,
510 extensions::disable_reason::DISABLE_USER_ACTION);
rdevlin.cronin2f1ed4c2017-06-13 16:22:13511 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
512 EXPECT_TRUE(processor_raw->changes().empty());
513
514 // Sync state says the extension is enabled.
515 EnableExtensionFromSync(*extension);
516
517 // As above, the extension should not have been affected by sync.
518 EXPECT_TRUE(registry()->disabled_extensions().GetByID(kExtensionId));
519 EXPECT_TRUE(processor_raw->changes().empty());
520
521 // And re-enabling the extension should not push new state to sync.
522 service()->EnableExtension(kExtensionId);
523 EXPECT_TRUE(registry()->enabled_extensions().GetByID(kExtensionId));
524 EXPECT_TRUE(processor_raw->changes().empty());
525}
526
treib9afc6212015-10-30 18:49:58527TEST_F(ExtensionServiceSyncTest, IgnoreSyncChangesWhenLocalStateIsMoreRecent) {
528 // Start the extension service with three extensions already installed.
529 base::FilePath source_install_dir =
530 data_dir().AppendASCII("good").AppendASCII("Extensions");
531 base::FilePath pref_path =
532 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
533
534 InitializeInstalledExtensionService(pref_path, source_install_dir);
535
536 // The user has enabled sync.
maxbogue0a379452016-09-22 21:35:05537 browser_sync::ProfileSyncService* sync_service =
treib9afc6212015-10-30 18:49:58538 ProfileSyncServiceFactory::GetForProfile(profile());
maxboguefe00952a2016-01-19 19:02:01539 sync_service->SetFirstSetupComplete();
treib9afc6212015-10-30 18:49:58540 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
541 extension_sync_service();
542
543 service()->Init();
544 ASSERT_TRUE(service()->is_ready());
545 ASSERT_EQ(3u, loaded_.size());
546
547 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
548 ASSERT_TRUE(service()->IsExtensionEnabled(good2));
549
550 // Disable and re-enable good0 before first sync data arrives.
Minh X. Nguyen45479012017-08-18 21:35:36551 service()->DisableExtension(good0,
552 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:58553 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
554 service()->EnableExtension(good0);
555 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
556 // Disable good2 before first sync data arrives (good1 is considered
557 // non-syncable because it has plugin permission).
Minh X. Nguyen45479012017-08-18 21:35:36558 service()->DisableExtension(good2,
559 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:58560 ASSERT_FALSE(service()->IsExtensionEnabled(good2));
561
562 const Extension* extension0 = service()->GetExtensionById(good0, true);
563 const Extension* extension2 = service()->GetExtensionById(good2, true);
564 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension0));
565 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension2));
566
567 // Now sync data comes in that says to disable good0 and enable good2.
Minh X. Nguyen45479012017-08-18 21:35:36568 ExtensionSyncData disable_good0(
569 *extension0, false, extensions::disable_reason::DISABLE_USER_ACTION,
570 false, false, ExtensionSyncData::BOOLEAN_UNSET, false);
571 ExtensionSyncData enable_good2(
572 *extension2, true, extensions::disable_reason::DISABLE_NONE, false, false,
573 ExtensionSyncData::BOOLEAN_UNSET, false);
treib9afc6212015-10-30 18:49:58574 syncer::SyncDataList sync_data;
575 sync_data.push_back(disable_good0.GetSyncData());
576 sync_data.push_back(enable_good2.GetSyncData());
577 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:22578 syncer::EXTENSIONS, sync_data,
Jinho Bangb5216cec2018-01-17 19:43:11579 std::make_unique<syncer::FakeSyncChangeProcessor>(),
580 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58581
582 // Both sync changes should be ignored, since the local state was changed
583 // before sync started, and so the local state is considered more recent.
584 EXPECT_TRUE(service()->IsExtensionEnabled(good0));
585 EXPECT_FALSE(service()->IsExtensionEnabled(good2));
586}
587
treibb794dd52015-12-01 18:47:14588TEST_F(ExtensionServiceSyncTest, DontSelfNotify) {
589 // Start the extension service with three extensions already installed.
590 base::FilePath source_install_dir =
591 data_dir().AppendASCII("good").AppendASCII("Extensions");
592 base::FilePath pref_path =
593 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
594
595 InitializeInstalledExtensionService(pref_path, source_install_dir);
596
597 // The user has enabled sync.
maxboguefe00952a2016-01-19 19:02:01598 ProfileSyncServiceFactory::GetForProfile(profile())->SetFirstSetupComplete();
treibb794dd52015-12-01 18:47:14599 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
600 extension_sync_service();
601
602 service()->Init();
603 ASSERT_TRUE(service()->is_ready());
604 ASSERT_EQ(3u, loaded_.size());
605 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
606
607 syncer::FakeSyncChangeProcessor* processor =
608 new syncer::FakeSyncChangeProcessor;
609 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:22610 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
Jinho Bangb5216cec2018-01-17 19:43:11611 std::make_unique<syncer::SyncErrorFactoryMock>());
treibb794dd52015-12-01 18:47:14612
613 processor->changes().clear();
614
615 // Simulate various incoming sync changes, and make sure they don't result in
616 // any outgoing changes.
617
618 {
619 const Extension* extension = service()->GetExtensionById(good0, true);
620 ASSERT_TRUE(extension);
621
622 // Disable the extension.
Minh X. Nguyen45479012017-08-18 21:35:36623 ExtensionSyncData data(
624 *extension, false, extensions::disable_reason::DISABLE_USER_ACTION,
625 false, false, ExtensionSyncData::BOOLEAN_UNSET, false);
treib65f103042015-12-03 10:21:36626 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14627
628 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
629
630 EXPECT_TRUE(processor->changes().empty());
631 }
632
633 {
634 const Extension* extension = service()->GetExtensionById(good0, true);
635 ASSERT_TRUE(extension);
636
637 // Set incognito enabled to true.
Minh X. Nguyen45479012017-08-18 21:35:36638 ExtensionSyncData data(*extension, false,
639 extensions::disable_reason::DISABLE_NONE, true,
mamir192d7882016-06-22 17:10:16640 false, ExtensionSyncData::BOOLEAN_UNSET, false);
treib65f103042015-12-03 10:21:36641 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14642
643 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
644
645 EXPECT_TRUE(processor->changes().empty());
646 }
647
648 {
649 const Extension* extension = service()->GetExtensionById(good0, true);
650 ASSERT_TRUE(extension);
651
652 // Add another disable reason.
Minh X. Nguyen45479012017-08-18 21:35:36653 ExtensionSyncData data(
654 *extension, false,
655 extensions::disable_reason::DISABLE_USER_ACTION |
656 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
657 false, false, ExtensionSyncData::BOOLEAN_UNSET, false);
treib65f103042015-12-03 10:21:36658 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14659
660 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
661
662 EXPECT_TRUE(processor->changes().empty());
663 }
664
665 {
666 const Extension* extension = service()->GetExtensionById(good0, true);
667 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,
674 false, false, ExtensionSyncData::BOOLEAN_UNSET, false);
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);
686 const Extension* extension = service()->GetInstalledExtension(good_crx);
687 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 =
695 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
696 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());
705 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
Devlin Cronin03bf2d22017-12-20 08:21:05706 EXPECT_EQ(data->version(), extension->version());
treib9afc6212015-10-30 18:49:58707 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
708 data->update_url());
709 EXPECT_EQ(extension->name(), data->name());
710}
711
treib29e1b9b12015-11-11 08:50:56712TEST_F(ExtensionServiceSyncTest, GetSyncDataDisableReasons) {
713 InitializeEmptyExtensionService();
714 const Extension* extension =
715 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
716 ASSERT_TRUE(extension);
717
treib29e1b9b12015-11-11 08:50:56718 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36719 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11720 std::make_unique<syncer::FakeSyncChangeProcessor>(),
721 std::make_unique<syncer::SyncErrorFactoryMock>());
treib29e1b9b12015-11-11 08:50:56722
723 {
724 syncer::SyncDataList list =
725 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
726 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22727 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56728 ExtensionSyncData::CreateFromSyncData(list[0]);
729 ASSERT_TRUE(data.get());
730 EXPECT_TRUE(data->enabled());
731 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36732 EXPECT_EQ(extensions::disable_reason::DISABLE_NONE,
733 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56734 }
735
736 // Syncable disable reason, should propagate to sync.
Minh X. Nguyen45479012017-08-18 21:35:36737 service()->DisableExtension(good_crx,
738 extensions::disable_reason::DISABLE_USER_ACTION);
treib29e1b9b12015-11-11 08:50:56739 {
740 syncer::SyncDataList list =
741 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
742 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22743 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56744 ExtensionSyncData::CreateFromSyncData(list[0]);
745 ASSERT_TRUE(data.get());
746 EXPECT_FALSE(data->enabled());
747 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36748 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
749 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56750 }
751 service()->EnableExtension(good_crx);
752
753 // Non-syncable disable reason. The sync data should still say "enabled".
Minh X. Nguyen45479012017-08-18 21:35:36754 service()->DisableExtension(good_crx,
755 extensions::disable_reason::DISABLE_RELOAD);
treib29e1b9b12015-11-11 08:50:56756 {
757 syncer::SyncDataList list =
758 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
759 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22760 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56761 ExtensionSyncData::CreateFromSyncData(list[0]);
762 ASSERT_TRUE(data.get());
763 EXPECT_TRUE(data->enabled());
764 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36765 EXPECT_EQ(extensions::disable_reason::DISABLE_NONE,
766 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56767 }
768 service()->EnableExtension(good_crx);
769
770 // Both a syncable and a non-syncable disable reason, only the former should
771 // propagate to sync.
Minh X. Nguyen45479012017-08-18 21:35:36772 service()->DisableExtension(good_crx,
773 extensions::disable_reason::DISABLE_USER_ACTION |
774 extensions::disable_reason::DISABLE_RELOAD);
treib29e1b9b12015-11-11 08:50:56775 {
776 syncer::SyncDataList list =
777 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
778 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22779 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56780 ExtensionSyncData::CreateFromSyncData(list[0]);
781 ASSERT_TRUE(data.get());
782 EXPECT_FALSE(data->enabled());
783 EXPECT_TRUE(data->supports_disable_reasons());
Minh X. Nguyen45479012017-08-18 21:35:36784 EXPECT_EQ(extensions::disable_reason::DISABLE_USER_ACTION,
785 data->disable_reasons());
treib29e1b9b12015-11-11 08:50:56786 }
787 service()->EnableExtension(good_crx);
788}
789
treib9afc6212015-10-30 18:49:58790TEST_F(ExtensionServiceSyncTest, GetSyncDataTerminated) {
791 InitializeEmptyExtensionService();
792 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
793 TerminateExtension(good_crx);
794 const Extension* extension = service()->GetInstalledExtension(good_crx);
795 ASSERT_TRUE(extension);
796
treib9afc6212015-10-30 18:49:58797 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36798 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11799 std::make_unique<syncer::FakeSyncChangeProcessor>(),
800 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58801
802 syncer::SyncDataList list =
803 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
804 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22805 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58806 ExtensionSyncData::CreateFromSyncData(list[0]);
807 ASSERT_TRUE(data.get());
808 EXPECT_EQ(extension->id(), data->id());
809 EXPECT_FALSE(data->uninstalled());
810 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
811 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
812 data->incognito_enabled());
813 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
Devlin Cronin03bf2d22017-12-20 08:21:05814 EXPECT_EQ(data->version(), extension->version());
treib9afc6212015-10-30 18:49:58815 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
816 data->update_url());
817 EXPECT_EQ(extension->name(), data->name());
818}
819
820TEST_F(ExtensionServiceSyncTest, GetSyncDataFilter) {
821 InitializeEmptyExtensionService();
822 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
823 const Extension* extension = service()->GetInstalledExtension(good_crx);
824 ASSERT_TRUE(extension);
825
treib9afc6212015-10-30 18:49:58826 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36827 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11828 std::make_unique<syncer::FakeSyncChangeProcessor>(),
829 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58830
831 syncer::SyncDataList list =
832 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
833 ASSERT_EQ(list.size(), 0U);
834}
835
836TEST_F(ExtensionServiceSyncTest, GetSyncExtensionDataUserSettings) {
837 InitializeEmptyExtensionService();
838 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
839 const Extension* extension = service()->GetInstalledExtension(good_crx);
840 ASSERT_TRUE(extension);
841
treib9afc6212015-10-30 18:49:58842 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36843 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11844 std::make_unique<syncer::FakeSyncChangeProcessor>(),
845 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58846
847 {
848 syncer::SyncDataList list =
849 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
850 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22851 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58852 ExtensionSyncData::CreateFromSyncData(list[0]);
853 ASSERT_TRUE(data.get());
854 EXPECT_TRUE(data->enabled());
855 EXPECT_FALSE(data->incognito_enabled());
856 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
857 }
858
Minh X. Nguyen45479012017-08-18 21:35:36859 service()->DisableExtension(good_crx,
860 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:58861 {
862 syncer::SyncDataList list =
863 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
864 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22865 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58866 ExtensionSyncData::CreateFromSyncData(list[0]);
867 ASSERT_TRUE(data.get());
868 EXPECT_FALSE(data->enabled());
869 EXPECT_FALSE(data->incognito_enabled());
870 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
871 }
872
873 extensions::util::SetIsIncognitoEnabled(good_crx, profile(), true);
rdevlin.cronind01837b2016-08-17 01:37:18874 ScriptingPermissionsModifier permissions_modifier(
875 profile(), registry()->GetExtensionById(
876 good_crx, extensions::ExtensionRegistry::EVERYTHING));
877 permissions_modifier.SetAllowedOnAllUrls(false);
treib9afc6212015-10-30 18:49:58878 {
879 syncer::SyncDataList list =
880 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
881 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22882 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58883 ExtensionSyncData::CreateFromSyncData(list[0]);
884 ASSERT_TRUE(data.get());
885 EXPECT_FALSE(data->enabled());
886 EXPECT_TRUE(data->incognito_enabled());
887 EXPECT_EQ(ExtensionSyncData::BOOLEAN_FALSE, data->all_urls_enabled());
888 }
889
890 service()->EnableExtension(good_crx);
rdevlin.cronind01837b2016-08-17 01:37:18891 permissions_modifier.SetAllowedOnAllUrls(true);
treib9afc6212015-10-30 18:49:58892 {
893 syncer::SyncDataList list =
894 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
895 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22896 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58897 ExtensionSyncData::CreateFromSyncData(list[0]);
898 ASSERT_TRUE(data.get());
899 EXPECT_TRUE(data->enabled());
900 EXPECT_TRUE(data->incognito_enabled());
901 EXPECT_EQ(ExtensionSyncData::BOOLEAN_TRUE, data->all_urls_enabled());
902 }
903}
904
905TEST_F(ExtensionServiceSyncTest, SyncForUninstalledExternalExtension) {
906 InitializeEmptyExtensionService();
catmullings22bc2372016-11-02 19:59:35907 InstallCRX(data_dir().AppendASCII("good.crx"), Manifest::EXTERNAL_PREF,
908 INSTALL_NEW, Extension::NO_FLAGS);
treib9afc6212015-10-30 18:49:58909 const Extension* extension = service()->GetInstalledExtension(good_crx);
910 ASSERT_TRUE(extension);
911
treib9afc6212015-10-30 18:49:58912 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36913 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11914 std::make_unique<syncer::FakeSyncChangeProcessor>(),
915 std::make_unique<syncer::SyncErrorFactoryMock>());
asargente48ab752016-03-12 00:59:20916 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:58917
Devlin Cronin6fd1cd62017-12-05 19:13:57918 UninstallExtension(good_crx);
treib9afc6212015-10-30 18:49:58919 EXPECT_TRUE(
920 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
921
922 sync_pb::EntitySpecifics specifics;
923 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
924 sync_pb::ExtensionSpecifics* extension_specifics =
925 app_specifics->mutable_extension();
926 extension_specifics->set_id(good_crx);
927 extension_specifics->set_version("1.0");
928 extension_specifics->set_enabled(true);
929
treib65f103042015-12-03 10:21:36930 SyncChangeList list =
931 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:58932
933 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
934 EXPECT_TRUE(
935 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
936}
937
938TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettings) {
939 InitializeEmptyExtensionService();
940 const Extension* app =
941 PackAndInstallCRX(data_dir().AppendASCII("app"), INSTALL_NEW);
942 ASSERT_TRUE(app);
943 ASSERT_TRUE(app->is_app());
944
treib9afc6212015-10-30 18:49:58945 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36946 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:11947 std::make_unique<syncer::FakeSyncChangeProcessor>(),
948 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58949
950 syncer::StringOrdinal initial_ordinal =
951 syncer::StringOrdinal::CreateInitialOrdinal();
952 {
953 syncer::SyncDataList list =
954 extension_sync_service()->GetAllSyncData(syncer::APPS);
955 ASSERT_EQ(list.size(), 1U);
956
dchengc963c7142016-04-08 03:55:22957 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58958 ExtensionSyncData::CreateFromSyncData(list[0]);
959 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->app_launch_ordinal()));
960 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
961 }
962
deepak.m14ba69e62015-11-17 05:42:12963 AppSorting* sorting = ExtensionSystem::Get(profile())->app_sorting();
treib9afc6212015-10-30 18:49:58964 sorting->SetAppLaunchOrdinal(app->id(), initial_ordinal.CreateAfter());
965 {
966 syncer::SyncDataList list =
967 extension_sync_service()->GetAllSyncData(syncer::APPS);
968 ASSERT_EQ(list.size(), 1U);
969
dchengc963c7142016-04-08 03:55:22970 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58971 ExtensionSyncData::CreateFromSyncData(list[0]);
972 ASSERT_TRUE(app_sync_data.get());
973 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
974 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
975 }
976
977 sorting->SetPageOrdinal(app->id(), initial_ordinal.CreateAfter());
978 {
979 syncer::SyncDataList list =
980 extension_sync_service()->GetAllSyncData(syncer::APPS);
981 ASSERT_EQ(list.size(), 1U);
982
dchengc963c7142016-04-08 03:55:22983 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58984 ExtensionSyncData::CreateFromSyncData(list[0]);
985 ASSERT_TRUE(app_sync_data.get());
986 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
987 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->page_ordinal()));
988 }
989}
990
991// TODO (rdevlin.cronin): The OnExtensionMoved() method has been removed from
992// ExtensionService, so this test probably needs a new home. Unfortunately, it
993// relies pretty heavily on things like InitializeExtension[Sync]Service() and
994// PackAndInstallCRX(). When we clean up a bit more, this should move out.
995TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettingsOnExtensionMoved) {
996 InitializeEmptyExtensionService();
997 const size_t kAppCount = 3;
998 const Extension* apps[kAppCount];
999 apps[0] = PackAndInstallCRX(data_dir().AppendASCII("app1"), INSTALL_NEW);
1000 apps[1] = PackAndInstallCRX(data_dir().AppendASCII("app2"), INSTALL_NEW);
1001 apps[2] = PackAndInstallCRX(data_dir().AppendASCII("app4"), INSTALL_NEW);
1002 for (size_t i = 0; i < kAppCount; ++i) {
1003 ASSERT_TRUE(apps[i]);
1004 ASSERT_TRUE(apps[i]->is_app());
1005 }
1006
treib9afc6212015-10-30 18:49:581007 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361008 syncer::APPS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:221009 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
1010 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:581011
deepak.m14ba69e62015-11-17 05:42:121012 ExtensionSystem::Get(service()->GetBrowserContext())
treib9afc6212015-10-30 18:49:581013 ->app_sorting()
1014 ->OnExtensionMoved(apps[0]->id(), apps[1]->id(), apps[2]->id());
1015 {
1016 syncer::SyncDataList list =
1017 extension_sync_service()->GetAllSyncData(syncer::APPS);
1018 ASSERT_EQ(list.size(), 3U);
1019
dchengc963c7142016-04-08 03:55:221020 std::unique_ptr<ExtensionSyncData> data[kAppCount];
treib9afc6212015-10-30 18:49:581021 for (size_t i = 0; i < kAppCount; ++i) {
1022 data[i] = ExtensionSyncData::CreateFromSyncData(list[i]);
1023 ASSERT_TRUE(data[i].get());
1024 }
1025
1026 // The sync data is not always in the same order our apps were installed in,
1027 // so we do that sorting here so we can make sure the values are changed as
1028 // expected.
1029 syncer::StringOrdinal app_launch_ordinals[kAppCount];
1030 for (size_t i = 0; i < kAppCount; ++i) {
1031 for (size_t j = 0; j < kAppCount; ++j) {
1032 if (apps[i]->id() == data[j]->id())
1033 app_launch_ordinals[i] = data[j]->app_launch_ordinal();
1034 }
1035 }
1036
1037 EXPECT_TRUE(app_launch_ordinals[1].LessThan(app_launch_ordinals[0]));
1038 EXPECT_TRUE(app_launch_ordinals[0].LessThan(app_launch_ordinals[2]));
1039 }
1040}
1041
1042TEST_F(ExtensionServiceSyncTest, GetSyncDataList) {
1043 InitializeEmptyExtensionService();
1044 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1045 InstallCRX(data_dir().AppendASCII("page_action.crx"), INSTALL_NEW);
1046 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
1047 InstallCRX(data_dir().AppendASCII("theme2.crx"), INSTALL_NEW);
1048
treib9afc6212015-10-30 18:49:581049 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361050 syncer::APPS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111051 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1052 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581053 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361054 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111055 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1056 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581057
Minh X. Nguyen45479012017-08-18 21:35:361058 service()->DisableExtension(page_action,
1059 extensions::disable_reason::DISABLE_USER_ACTION);
treib9afc6212015-10-30 18:49:581060 TerminateExtension(theme2_crx);
1061
1062 EXPECT_EQ(0u, extension_sync_service()->GetAllSyncData(syncer::APPS).size());
1063 EXPECT_EQ(
1064 2u, extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS).size());
1065}
1066
1067TEST_F(ExtensionServiceSyncTest, ProcessSyncDataUninstall) {
1068 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581069 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361070 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111071 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1072 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581073
1074 sync_pb::EntitySpecifics specifics;
1075 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1076 ext_specifics->set_id(good_crx);
1077 ext_specifics->set_version("1.0");
treib65f103042015-12-03 10:21:361078
1079 SyncChangeList list =
1080 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:581081
1082 // Should do nothing.
1083 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1084 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
1085
1086 // Install the extension.
1087 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
1088 InstallCRX(extension_path, INSTALL_NEW);
1089 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
1090
1091 // Should uninstall the extension.
1092 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1093 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
1094
1095 // Should again do nothing.
1096 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1097 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
1098}
1099
1100TEST_F(ExtensionServiceSyncTest, ProcessSyncDataWrongType) {
1101 InitializeEmptyExtensionService();
asargente48ab752016-03-12 00:59:201102 StartSyncing(syncer::EXTENSIONS);
1103 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:581104
1105 // Install the extension.
1106 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
1107 InstallCRX(extension_path, INSTALL_NEW);
1108 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
1109
1110 sync_pb::EntitySpecifics specifics;
1111 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
1112 sync_pb::ExtensionSpecifics* extension_specifics =
1113 app_specifics->mutable_extension();
1114 extension_specifics->set_id(good_crx);
1115 extension_specifics->set_version(
Devlin Cronin03bf2d22017-12-20 08:21:051116 service()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581117
1118 {
1119 extension_specifics->set_enabled(true);
treib65f103042015-12-03 10:21:361120
1121 SyncChangeList list =
1122 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:581123
1124 // Should do nothing
1125 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1126 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
1127 }
1128
1129 {
1130 extension_specifics->set_enabled(false);
treib65f103042015-12-03 10:21:361131
1132 SyncChangeList list =
1133 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581134
1135 // Should again do nothing.
1136 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1137 EXPECT_TRUE(service()->GetExtensionById(good_crx, false));
1138 }
1139}
1140
1141TEST_F(ExtensionServiceSyncTest, ProcessSyncDataSettings) {
1142 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581143 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361144 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111145 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1146 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581147
1148 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1149 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1150 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
rdevlin.cronind01837b2016-08-17 01:37:181151 // Returns a ScriptingPermissionsModifier for the extension. We use this
1152 // because various parts of this test reload the extension, making keeping a
1153 // ptr to it inviable.
1154 auto get_permissions_modifier = [this]() {
1155 const Extension* extension = registry()->GetExtensionById(
1156 good_crx, extensions::ExtensionRegistry::EVERYTHING);
Jinho Bangb5216cec2018-01-17 19:43:111157 return std::make_unique<ScriptingPermissionsModifier>(profile(), extension);
rdevlin.cronind01837b2016-08-17 01:37:181158 };
1159 EXPECT_FALSE(get_permissions_modifier()->HasSetAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:581160 const bool kDefaultAllowedScripting =
rdevlin.cronind01837b2016-08-17 01:37:181161 ScriptingPermissionsModifier::DefaultAllowedOnAllUrls();
treib9afc6212015-10-30 18:49:581162 EXPECT_EQ(kDefaultAllowedScripting,
rdevlin.cronind01837b2016-08-17 01:37:181163 get_permissions_modifier()->IsAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:581164
1165 sync_pb::EntitySpecifics specifics;
1166 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1167 ext_specifics->set_id(good_crx);
1168 ext_specifics->set_version(
Devlin Cronin03bf2d22017-12-20 08:21:051169 service()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581170 ext_specifics->set_enabled(false);
1171
1172 {
treib65f103042015-12-03 10:21:361173 SyncChangeList list =
1174 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1175
treib9afc6212015-10-30 18:49:581176 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1177 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1178 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
rdevlin.cronind01837b2016-08-17 01:37:181179 EXPECT_FALSE(get_permissions_modifier()->HasSetAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:581180 EXPECT_EQ(kDefaultAllowedScripting,
rdevlin.cronind01837b2016-08-17 01:37:181181 get_permissions_modifier()->IsAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:581182 }
1183
1184 {
1185 ext_specifics->set_enabled(true);
1186 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361187
1188 SyncChangeList list =
1189 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1190
treib9afc6212015-10-30 18:49:581191 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1192 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1193 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1194 }
1195
1196 {
1197 ext_specifics->set_enabled(false);
1198 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361199
1200 SyncChangeList list =
1201 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1202
treib9afc6212015-10-30 18:49:581203 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1204 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1205 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1206 }
1207
1208 {
1209 ext_specifics->set_enabled(true);
1210 ext_specifics->set_all_urls_enabled(!kDefaultAllowedScripting);
treib65f103042015-12-03 10:21:361211
1212 SyncChangeList list =
1213 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1214
treib9afc6212015-10-30 18:49:581215 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1216 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
rdevlin.cronind01837b2016-08-17 01:37:181217 EXPECT_TRUE(get_permissions_modifier()->HasSetAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:581218 EXPECT_EQ(!kDefaultAllowedScripting,
rdevlin.cronind01837b2016-08-17 01:37:181219 get_permissions_modifier()->IsAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:581220 }
1221
1222 {
1223 ext_specifics->set_all_urls_enabled(kDefaultAllowedScripting);
treib65f103042015-12-03 10:21:361224
1225 SyncChangeList list =
1226 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1227
treib9afc6212015-10-30 18:49:581228 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1229 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
rdevlin.cronind01837b2016-08-17 01:37:181230 EXPECT_TRUE(get_permissions_modifier()->HasSetAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:581231 EXPECT_EQ(kDefaultAllowedScripting,
rdevlin.cronind01837b2016-08-17 01:37:181232 get_permissions_modifier()->IsAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:581233 }
1234
1235 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1236}
1237
1238TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNewExtension) {
1239 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581240 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361241 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111242 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1243 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581244
1245 const base::FilePath path = data_dir().AppendASCII("good.crx");
1246 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1247
1248 struct TestCase {
1249 const char* name; // For failure output only.
1250 bool sync_enabled; // The "enabled" flag coming in from Sync.
1251 // The disable reason(s) coming in from Sync, or -1 for "not set".
1252 int sync_disable_reasons;
1253 // The disable reason(s) that should be set on the installed extension.
1254 // This will usually be the same as |sync_disable_reasons|, but see the
1255 // "Legacy" case.
1256 int expect_disable_reasons;
1257 // Whether the extension's permissions should be auto-granted during
1258 // installation.
1259 bool expect_permissions_granted;
1260 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361261 // Standard case: Extension comes in enabled; permissions should be
1262 // granted
1263 // during installation.
1264 {"Standard", true, 0, 0, true},
1265 // If the extension comes in disabled, its permissions should still be
1266 // granted (the user already approved them on another machine).
1267 {"Disabled", false, extensions::disable_reason::DISABLE_USER_ACTION,
1268 extensions::disable_reason::DISABLE_USER_ACTION, true},
1269 // Legacy case (<M45): No disable reasons come in from Sync (see
1270 // crbug.com/484214). After installation, the reason should be set to
1271 // DISABLE_USER_ACTION (default assumption).
1272 {"Legacy", false, -1, extensions::disable_reason::DISABLE_USER_ACTION,
1273 true},
1274 // If the extension came in disabled due to a permissions increase, then
1275 // the
1276 // user has *not* approved the permissions, and they shouldn't be granted.
1277 // crbug.com/484214
1278 {"PermissionsIncrease", false,
1279 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE,
1280 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
treib9afc6212015-10-30 18:49:581281 };
1282
1283 for (const TestCase& test_case : test_cases) {
1284 SCOPED_TRACE(test_case.name);
1285
1286 sync_pb::EntitySpecifics specifics;
1287 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1288 ext_specifics->set_id(good_crx);
1289 ext_specifics->set_version(base::Version("1").GetString());
1290 ext_specifics->set_enabled(test_case.sync_enabled);
1291 if (test_case.sync_disable_reasons != -1)
1292 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1293
treib65f103042015-12-03 10:21:361294 SyncChangeList list =
1295 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1296
treib9afc6212015-10-30 18:49:581297 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1298
1299 ASSERT_TRUE(service()->pending_extension_manager()->IsIdPending(good_crx));
1300 UpdateExtension(good_crx, path, test_case.sync_enabled ? ENABLED
1301 : DISABLED);
1302 EXPECT_EQ(test_case.expect_disable_reasons,
1303 prefs->GetDisableReasons(good_crx));
dchengc963c7142016-04-08 03:55:221304 std::unique_ptr<const PermissionSet> permissions =
treib9afc6212015-10-30 18:49:581305 prefs->GetGrantedPermissions(good_crx);
1306 EXPECT_EQ(test_case.expect_permissions_granted, !permissions->IsEmpty());
1307 ASSERT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
Devlin Cronin7b193412017-12-14 03:46:031308 if (test_case.sync_enabled)
1309 EXPECT_TRUE(registry()->enabled_extensions().GetByID(good_crx));
1310 else
1311 EXPECT_TRUE(registry()->disabled_extensions().GetByID(good_crx));
treib9afc6212015-10-30 18:49:581312
1313 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031314 UninstallExtension(good_crx);
treib9afc6212015-10-30 18:49:581315 }
1316}
1317
1318TEST_F(ExtensionServiceSyncTest, ProcessSyncDataTerminatedExtension) {
1319 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581320 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361321 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111322 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1323 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581324
1325 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1326 TerminateExtension(good_crx);
1327 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1328 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1329
1330 sync_pb::EntitySpecifics specifics;
1331 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1332 ext_specifics->set_id(good_crx);
1333 ext_specifics->set_version(
Devlin Cronin03bf2d22017-12-20 08:21:051334 service()->GetInstalledExtension(good_crx)->version().GetString());
treib9afc6212015-10-30 18:49:581335 ext_specifics->set_enabled(false);
1336 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361337
1338 SyncChangeList list =
1339 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581340
1341 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1342 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1343 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1344
1345 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1346}
1347
1348TEST_F(ExtensionServiceSyncTest, ProcessSyncDataVersionCheck) {
1349 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581350 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361351 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111352 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1353 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581354
1355 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1356 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1357 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1358
1359 sync_pb::EntitySpecifics specifics;
1360 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1361 ext_specifics->set_id(good_crx);
1362 ext_specifics->set_enabled(true);
1363
1364 const base::Version installed_version =
Devlin Cronin03bf2d22017-12-20 08:21:051365 service()->GetInstalledExtension(good_crx)->version();
treib9afc6212015-10-30 18:49:581366
1367 {
1368 ext_specifics->set_version(installed_version.GetString());
treib65f103042015-12-03 10:21:361369
1370 SyncChangeList list =
1371 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581372
1373 // Should do nothing if extension version == sync version.
1374 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1375 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1376 // Make sure the version we'll send back to sync didn't change.
1377 syncer::SyncDataList data =
1378 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1379 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221380 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581381 ExtensionSyncData::CreateFromSyncData(data[0]);
1382 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001383 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581384 }
1385
1386 // Should do nothing if extension version > sync version.
1387 {
1388 ext_specifics->set_version("0.0.0.0");
treib65f103042015-12-03 10:21:361389
1390 SyncChangeList list =
1391 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581392
1393 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1394 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1395 // Make sure the version we'll send back to sync didn't change.
1396 syncer::SyncDataList data =
1397 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1398 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221399 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581400 ExtensionSyncData::CreateFromSyncData(data[0]);
1401 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001402 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581403 }
1404
1405 // Should kick off an update if extension version < sync version.
1406 {
1407 const base::Version new_version("9.9.9.9");
1408 ext_specifics->set_version(new_version.GetString());
treib65f103042015-12-03 10:21:361409
1410 SyncChangeList list =
1411 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581412
1413 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1414 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1415 // Make sure that we'll send the NEW version back to sync, even though we
1416 // haven't actually updated yet. This is to prevent the data in sync from
1417 // flip-flopping back and forth until all clients are up to date.
1418 syncer::SyncDataList data =
1419 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1420 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221421 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581422 ExtensionSyncData::CreateFromSyncData(data[0]);
1423 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001424 EXPECT_EQ(new_version, extension_data->version());
treib9afc6212015-10-30 18:49:581425 }
1426
1427 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1428}
1429
1430TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNotInstalled) {
1431 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581432 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361433 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111434 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1435 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581436
1437 sync_pb::EntitySpecifics specifics;
1438 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1439 ext_specifics->set_id(good_crx);
1440 ext_specifics->set_enabled(false);
1441 ext_specifics->set_incognito_enabled(true);
1442 ext_specifics->set_update_url("http://www.google.com/");
1443 ext_specifics->set_version("1.2.3.4");
treib65f103042015-12-03 10:21:361444
1445 SyncChangeList list =
1446 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581447
1448 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1449 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1450 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1451 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1452 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1453 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1454
1455 const extensions::PendingExtensionInfo* info;
1456 EXPECT_TRUE(
1457 (info = service()->pending_extension_manager()->GetById(good_crx)));
1458 EXPECT_EQ(ext_specifics->update_url(), info->update_url().spec());
1459 EXPECT_TRUE(info->is_from_sync());
1460 EXPECT_EQ(Manifest::INTERNAL, info->install_source());
1461 // TODO(akalin): Figure out a way to test |info.ShouldAllowInstall()|.
1462}
1463
1464TEST_F(ExtensionServiceSyncTest, ProcessSyncDataEnableDisable) {
1465 InitializeEmptyExtensionService();
1466 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361467 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111468 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1469 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581470
1471 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1472
1473 struct TestCase {
1474 const char* name; // For failure output only.
1475 // Set of disable reasons before any Sync data comes in. If this is != 0,
1476 // the extension is disabled.
1477 int previous_disable_reasons;
1478 bool sync_enable; // The enabled flag coming in from Sync.
1479 // The disable reason(s) coming in from Sync, or -1 for "not set".
1480 int sync_disable_reasons;
1481 // The expected set of disable reasons after processing the Sync update. The
1482 // extension should be disabled iff this is != 0.
1483 int expect_disable_reasons;
1484 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361485 {"NopEnable", 0, true, 0, 0},
1486 {"NopDisable", extensions::disable_reason::DISABLE_USER_ACTION, false,
1487 extensions::disable_reason::DISABLE_USER_ACTION,
1488 extensions::disable_reason::DISABLE_USER_ACTION},
1489 {"Enable", extensions::disable_reason::DISABLE_USER_ACTION, true, 0, 0},
1490 {"Disable", 0, false, extensions::disable_reason::DISABLE_USER_ACTION,
1491 extensions::disable_reason::DISABLE_USER_ACTION},
1492 {"AddDisableReason", extensions::disable_reason::DISABLE_REMOTE_INSTALL,
1493 false,
1494 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1495 extensions::disable_reason::DISABLE_USER_ACTION,
1496 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1497 extensions::disable_reason::DISABLE_USER_ACTION},
1498 {"RemoveDisableReason",
1499 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1500 extensions::disable_reason::DISABLE_USER_ACTION,
1501 false, extensions::disable_reason::DISABLE_USER_ACTION,
1502 extensions::disable_reason::DISABLE_USER_ACTION},
1503 {"PreserveLocalDisableReason", extensions::disable_reason::DISABLE_RELOAD,
1504 true, 0, extensions::disable_reason::DISABLE_RELOAD},
1505 {"PreserveOnlyLocalDisableReason",
1506 extensions::disable_reason::DISABLE_USER_ACTION |
1507 extensions::disable_reason::DISABLE_RELOAD,
1508 true, 0, extensions::disable_reason::DISABLE_RELOAD},
treib29e1b9b12015-11-11 08:50:561509
Minh X. Nguyen45479012017-08-18 21:35:361510 // Interaction with Chrome clients <=M44, which don't sync disable_reasons
1511 // at all (any existing reasons are preserved).
1512 {"M44Enable", extensions::disable_reason::DISABLE_USER_ACTION, true, -1,
1513 0},
1514 // An M44 client enables an extension that had been disabled on a new
1515 // client. The disable reasons are still be there, but should be ignored.
1516 {"M44ReEnable", extensions::disable_reason::DISABLE_USER_ACTION, true,
1517 extensions::disable_reason::DISABLE_USER_ACTION, 0},
1518 {"M44Disable", 0, false, -1,
1519 extensions::disable_reason::DISABLE_USER_ACTION},
1520 {"M44ReDisable", 0, false, 0,
1521 extensions::disable_reason::DISABLE_USER_ACTION},
1522 {"M44AlreadyDisabledByUser",
1523 extensions::disable_reason::DISABLE_USER_ACTION, false, -1,
1524 extensions::disable_reason::DISABLE_USER_ACTION},
1525 {"M44AlreadyDisabledWithOtherReason",
1526 extensions::disable_reason::DISABLE_REMOTE_INSTALL, false, -1,
1527 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1528 extensions::disable_reason::DISABLE_USER_ACTION},
treib9afc6212015-10-30 18:49:581529 };
1530
1531 for (const TestCase& test_case : test_cases) {
1532 SCOPED_TRACE(test_case.name);
1533
1534 std::string id;
1535 std::string version;
1536 // Don't keep |extension| around longer than necessary.
1537 {
1538 const Extension* extension =
1539 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1540 // The extension should now be installed and enabled.
1541 ASSERT_TRUE(extension);
1542 id = extension->id();
1543 version = extension->VersionString();
1544 }
1545 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1546
1547 // Disable it if the test case says so.
1548 if (test_case.previous_disable_reasons) {
1549 service()->DisableExtension(id, test_case.previous_disable_reasons);
1550 ASSERT_TRUE(registry()->disabled_extensions().Contains(id));
1551 }
1552
1553 // Now a sync update comes in.
1554 sync_pb::EntitySpecifics specifics;
1555 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1556 ext_specifics->set_id(id);
1557 ext_specifics->set_enabled(test_case.sync_enable);
1558 ext_specifics->set_version(version);
1559 if (test_case.sync_disable_reasons != -1)
1560 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1561
treib65f103042015-12-03 10:21:361562 SyncChangeList list =
1563 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1564
treib9afc6212015-10-30 18:49:581565 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1566
1567 // Check expectations.
1568 const bool expect_enabled = !test_case.expect_disable_reasons;
1569 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1570 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
1571
1572 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031573 UninstallExtension(id);
treib9afc6212015-10-30 18:49:581574 }
1575}
1576
Konstantin Ganenkoae1129c2017-09-15 16:28:591577class ExtensionServiceSyncCustomGalleryTest : public ExtensionServiceSyncTest {
1578 public:
1579 void SetUp() override {
1580 ExtensionServiceSyncTest::SetUp();
rdevlin.cronin2f1ed4c2017-06-13 16:22:131581
Konstantin Ganenkoae1129c2017-09-15 16:28:591582 // This is the update URL specified in the permissions test extension.
1583 // Setting it here is necessary to make the extension considered syncable.
1584 extension_test_util::SetGalleryUpdateURL(
1585 GURL("http://localhost/autoupdate/updates.xml"));
1586 }
1587};
1588
1589TEST_F(ExtensionServiceSyncCustomGalleryTest, ProcessSyncDataDeferredEnable) {
treib9afc6212015-10-30 18:49:581590 InitializeEmptyExtensionService();
1591 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361592 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111593 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1594 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581595
1596 base::FilePath base_path = data_dir().AppendASCII("permissions_increase");
1597 base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1598
1599 base::FilePath path = base_path.AppendASCII("v1");
1600 const Extension* extension = PackAndInstallCRX(path, pem_path, INSTALL_NEW);
1601 // The extension must now be installed and enabled.
1602 ASSERT_TRUE(extension);
1603 ASSERT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
1604
1605 // Save the id, as the extension object will be destroyed during updating.
1606 std::string id = extension->id();
1607
1608 // Update to a new version with increased permissions.
1609 path = base_path.AppendASCII("v2");
1610 PackCRXAndUpdateExtension(id, path, pem_path, DISABLED);
1611
1612 // Now a sync update comes in, telling us to re-enable a *newer* version.
1613 sync_pb::EntitySpecifics specifics;
1614 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1615 ext_specifics->set_id(id);
1616 ext_specifics->set_version("3");
1617 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:361618 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:581619
treib65f103042015-12-03 10:21:361620 SyncChangeList list =
1621 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1622
treib9afc6212015-10-30 18:49:581623 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1624
1625 // Since the version didn't match, the extension should still be disabled.
1626 EXPECT_TRUE(registry()->disabled_extensions().Contains(id));
1627
1628 // After we update to the matching version, the extension should get enabled.
1629 path = base_path.AppendASCII("v3");
1630 PackCRXAndUpdateExtension(id, path, pem_path, ENABLED);
1631}
1632
atuchin2eb18eb2017-03-02 07:22:151633TEST_F(ExtensionServiceSyncCustomGalleryTest,
1634 ProcessSyncDataPermissionApproval) {
treib9afc6212015-10-30 18:49:581635 InitializeEmptyExtensionService();
1636 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361637 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:111638 std::make_unique<syncer::FakeSyncChangeProcessor>(),
1639 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581640
1641 const base::FilePath base_path =
1642 data_dir().AppendASCII("permissions_increase");
1643 const base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1644 const base::FilePath path_v1 = base_path.AppendASCII("v1");
1645 const base::FilePath path_v2 = base_path.AppendASCII("v2");
1646
1647 base::ScopedTempDir crx_dir;
1648 ASSERT_TRUE(crx_dir.CreateUniqueTempDir());
vabr9142fe22016-09-08 13:19:221649 const base::FilePath crx_path_v1 = crx_dir.GetPath().AppendASCII("temp1.crx");
treib9afc6212015-10-30 18:49:581650 PackCRX(path_v1, pem_path, crx_path_v1);
vabr9142fe22016-09-08 13:19:221651 const base::FilePath crx_path_v2 = crx_dir.GetPath().AppendASCII("temp2.crx");
treib9afc6212015-10-30 18:49:581652 PackCRX(path_v2, pem_path, crx_path_v2);
1653
1654 const std::string v1("1");
1655 const std::string v2("2");
1656
1657 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1658
1659 struct TestCase {
1660 const char* name; // For failure output only.
1661 const std::string& sync_version; // The version coming in from Sync.
1662 // The disable reason(s) coming in from Sync, or -1 for "not set".
1663 int sync_disable_reasons;
1664 // The expected set of disable reasons after processing the Sync update. The
1665 // extension should be enabled iff this is 0.
1666 int expect_disable_reasons;
1667 // Whether the extension's permissions should be auto-granted.
1668 bool expect_permissions_granted;
1669 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361670 // Sync tells us to re-enable an older version. No permissions should be
1671 // granted, since we can't be sure if the user actually approved the right
1672 // set of permissions.
1673 {"OldVersion", v1, 0,
1674 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
1675 // Legacy case: Sync tells us to re-enable the extension, but doesn't
1676 // specify disable reasons. No permissions should be granted.
1677 {"Legacy", v2, -1,
1678 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
1679 // Sync tells us to re-enable the extension and explicitly removes the
1680 // disable reasons. Now the extension should have its permissions granted.
1681 {"GrantPermissions", v2, 0, extensions::disable_reason::DISABLE_NONE,
1682 true},
treib9afc6212015-10-30 18:49:581683 };
1684
1685 for (const TestCase& test_case : test_cases) {
1686 SCOPED_TRACE(test_case.name);
1687
1688 std::string id;
1689 // Don't keep |extension| around longer than necessary (it'll be destroyed
1690 // during updating).
1691 {
1692 const Extension* extension = InstallCRX(crx_path_v1, INSTALL_NEW);
1693 // The extension should now be installed and enabled.
1694 ASSERT_TRUE(extension);
1695 ASSERT_EQ(v1, extension->VersionString());
1696 id = extension->id();
1697 }
1698 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1699
dchengc963c7142016-04-08 03:55:221700 std::unique_ptr<const PermissionSet> granted_permissions_v1 =
treib9afc6212015-10-30 18:49:581701 prefs->GetGrantedPermissions(id);
1702
1703 // Update to a new version with increased permissions.
1704 UpdateExtension(id, crx_path_v2, DISABLED);
1705
1706 // Now the extension should be disabled due to a permissions increase.
1707 {
1708 const Extension* extension =
1709 registry()->disabled_extensions().GetByID(id);
1710 ASSERT_TRUE(extension);
1711 ASSERT_EQ(v2, extension->VersionString());
1712 }
1713 ASSERT_TRUE(prefs->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:361714 id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE));
treib9afc6212015-10-30 18:49:581715
1716 // No new permissions should have been granted.
dchengc963c7142016-04-08 03:55:221717 std::unique_ptr<const PermissionSet> granted_permissions_v2 =
treib9afc6212015-10-30 18:49:581718 prefs->GetGrantedPermissions(id);
1719 ASSERT_EQ(*granted_permissions_v1, *granted_permissions_v2);
1720
1721 // Now a sync update comes in.
1722 sync_pb::EntitySpecifics specifics;
1723 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1724 ext_specifics->set_id(id);
1725 ext_specifics->set_enabled(true);
1726 ext_specifics->set_version(test_case.sync_version);
1727 if (test_case.sync_disable_reasons != -1)
1728 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1729
treib65f103042015-12-03 10:21:361730 SyncChangeList list =
1731 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1732
treib9afc6212015-10-30 18:49:581733 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1734
1735 // Check expectations.
1736 const bool expect_enabled = !test_case.expect_disable_reasons;
1737 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1738 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
dchengc963c7142016-04-08 03:55:221739 std::unique_ptr<const PermissionSet> granted_permissions =
treib9afc6212015-10-30 18:49:581740 prefs->GetGrantedPermissions(id);
1741 if (test_case.expect_permissions_granted) {
dchengc963c7142016-04-08 03:55:221742 std::unique_ptr<const PermissionSet> active_permissions =
treib9afc6212015-10-30 18:49:581743 prefs->GetActivePermissions(id);
1744 EXPECT_EQ(*granted_permissions, *active_permissions);
1745 } else {
1746 EXPECT_EQ(*granted_permissions, *granted_permissions_v1);
1747 }
1748
1749 // Remove the extension again, so we can install it again for the next case.
Devlin Cronin7b193412017-12-14 03:46:031750 UninstallExtension(id);
treib9afc6212015-10-30 18:49:581751 }
1752}
1753
treib227b2582015-12-09 09:28:261754// Regression test for crbug.com/558299
1755TEST_F(ExtensionServiceSyncTest, DontSyncThemes) {
1756 InitializeEmptyExtensionService();
1757
1758 // The user has enabled sync.
maxboguefe00952a2016-01-19 19:02:011759 ProfileSyncServiceFactory::GetForProfile(profile())->SetFirstSetupComplete();
treib227b2582015-12-09 09:28:261760 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
1761 extension_sync_service();
1762
1763 service()->Init();
1764 ASSERT_TRUE(service()->is_ready());
1765
1766 syncer::FakeSyncChangeProcessor* processor =
1767 new syncer::FakeSyncChangeProcessor;
1768 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:221769 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
1770 base::WrapUnique(new syncer::SyncErrorFactoryMock));
treib227b2582015-12-09 09:28:261771
1772 processor->changes().clear();
1773
1774 // Sanity check: Installing an extension should result in a sync change.
1775 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1776 EXPECT_EQ(1u, processor->changes().size());
1777
1778 processor->changes().clear();
1779
1780 // Installing a theme should not result in a sync change (themes are handled
1781 // separately by ThemeSyncableService).
1782 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
Evan Stade46d716d2017-06-02 20:50:091783 content::WindowedNotificationObserver theme_change_observer(
1784 chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
1785 content::Source<ThemeService>(
1786 ThemeServiceFactory::GetForProfile(profile())));
1787 theme_change_observer.Wait();
treib227b2582015-12-09 09:28:261788 EXPECT_TRUE(processor->changes().empty());
1789}
1790
brettw9e85ef42016-11-01 21:01:241791#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
treib9afc6212015-10-30 18:49:581792
atuchin2eb18eb2017-03-02 07:22:151793class ExtensionServiceTestSupervised
1794 : public ExtensionServiceSyncCustomGalleryTest,
1795 public SupervisedUserService::Delegate {
treib9afc6212015-10-30 18:49:581796 public:
treibb6af28cd2015-12-01 11:19:461797 ExtensionServiceTestSupervised()
Jinho Bangb5216cec2018-01-17 19:43:111798 : field_trial_list_(std::make_unique<base::MockEntropyProvider>()) {}
treibb6af28cd2015-12-01 11:19:461799
treib9afc6212015-10-30 18:49:581800 void TearDown() override {
1801 supervised_user_service()->SetDelegate(nullptr);
1802
atuchin2eb18eb2017-03-02 07:22:151803 ExtensionServiceSyncCustomGalleryTest::TearDown();
treib9afc6212015-10-30 18:49:581804 }
1805
1806 protected:
mamire9609642016-06-28 22:17:541807 void InitSupervisedUserInitiatedExtensionInstallFeature(bool enabled) {
mamire9609642016-06-28 22:17:541808 if (enabled) {
asvitkineb1db8262016-11-08 09:48:201809 scoped_feature_list_.InitAndEnableFeature(
1810 supervised_users::kSupervisedUserInitiatedExtensionInstall);
mamire9609642016-06-28 22:17:541811 }
mamire9609642016-06-28 22:17:541812 }
1813
mamirf7715a2a2016-07-04 13:05:081814 bool IsPendingCustodianApproval(const std::string& extension_id) {
kylechar1e0dd6b2017-10-03 16:07:511815 auto function = base::MakeRefCounted<
1816 WebstorePrivateIsPendingCustodianApprovalFunction>();
mamirf7715a2a2016-07-04 13:05:081817
1818 std::unique_ptr<base::Value> result(RunFunctionAndReturnSingleResult(
1819 function.get(), "[\"" + extension_id + "\"]", browser_context()));
1820
1821 bool copy_bool_result = false;
1822 EXPECT_TRUE(result->GetAsBoolean(&copy_bool_result));
1823 return copy_bool_result;
1824 }
1825
treib9afc6212015-10-30 18:49:581826 void InitServices(bool profile_is_supervised) {
1827 ExtensionServiceInitParams params = CreateDefaultInitParams();
1828 params.profile_is_supervised = profile_is_supervised;
mamire9609642016-06-28 22:17:541829 // If profile is supervised, don't pass a pref file such that the testing
1830 // profile creates a pref service that uses SupervisedUserPrefStore.
1831 if (profile_is_supervised) {
1832 params.pref_file = base::FilePath();
1833 }
treib9afc6212015-10-30 18:49:581834 InitializeExtensionService(params);
asargente48ab752016-03-12 00:59:201835 StartSyncing(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581836
1837 supervised_user_service()->SetDelegate(this);
1838 supervised_user_service()->Init();
1839 }
1840
mamire9609642016-06-28 22:17:541841 std::string InstallPermissionsTestExtension(bool by_custodian) {
1842 return InstallTestExtension(permissions_increase, dir_path("1"), pem_path(),
1843 by_custodian);
treib9afc6212015-10-30 18:49:581844 }
1845
1846 void UpdatePermissionsTestExtension(const std::string& id,
1847 const std::string& version,
1848 UpdateState expected_state) {
mamire9609642016-06-28 22:17:541849 UpdateTestExtension(dir_path(version), pem_path(), id, version,
1850 expected_state);
1851 }
1852
1853 std::string InstallNoPermissionsTestExtension(bool by_custodian) {
1854 base::FilePath base_path = data_dir().AppendASCII("autoupdate");
1855 base::FilePath pem_path = base_path.AppendASCII("key.pem");
1856 base::FilePath dir_path = base_path.AppendASCII("v1");
1857
1858 return InstallTestExtension(autoupdate, dir_path, pem_path, by_custodian);
1859 }
1860
1861 void UpdateNoPermissionsTestExtension(const std::string& id,
1862 const std::string& version,
1863 UpdateState expected_state) {
1864 base::FilePath base_path = data_dir().AppendASCII("autoupdate");
1865 base::FilePath pem_path = base_path.AppendASCII("key.pem");
1866 base::FilePath dir_path = base_path.AppendASCII("v" + version);
1867
1868 UpdateTestExtension(dir_path, pem_path, id, version, expected_state);
1869 }
1870
1871 std::string InstallTestExtension(const std::string& id,
1872 const base::FilePath& dir_path,
1873 const base::FilePath& pem_path,
1874 bool by_custodian) {
1875 InstallState expected_state = INSTALL_WITHOUT_LOAD;
1876 if (by_custodian) {
1877 extensions::util::SetWasInstalledByCustodian(id, profile(), true);
1878 expected_state = INSTALL_NEW;
1879 }
1880 const Extension* extension =
1881 PackAndInstallCRX(dir_path, pem_path, expected_state);
1882 // The extension must now be installed.
1883 EXPECT_TRUE(extension);
1884 EXPECT_EQ(extension->id(), id);
1885 if (by_custodian) {
1886 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1887 } else {
1888 CheckDisabledForCustodianApproval(id);
1889 }
1890
Devlin Cronin03bf2d22017-12-20 08:21:051891 EXPECT_EQ(base::Version("1"), extension->version());
mamire9609642016-06-28 22:17:541892
1893 return id;
1894 }
1895
1896 void UpdateTestExtension(const base::FilePath& dir_path,
1897 const base::FilePath& pem_path,
1898 const std::string& id,
1899 const std::string& version,
1900 const UpdateState& expected_state) {
1901 PackCRXAndUpdateExtension(id, dir_path, pem_path, expected_state);
treib9afc6212015-10-30 18:49:581902 const Extension* extension = registry()->GetInstalledExtension(id);
1903 ASSERT_TRUE(extension);
1904 // The version should have been updated.
Devlin Cronin03bf2d22017-12-20 08:21:051905 EXPECT_EQ(base::Version(version), extension->version());
mamire9609642016-06-28 22:17:541906 }
1907
1908 // Simulate a custodian approval for enabling the extension coming in
1909 // through Sync by adding the approved version to the map of approved
1910 // extensions. It doesn't simulate a change in the disable reasons.
1911 void SimulateCustodianApprovalChangeViaSync(const std::string& extension_id,
1912 const std::string& version,
1913 SyncChange::SyncChangeType type) {
1914 std::string key = SupervisedUserSettingsService::MakeSplitSettingKey(
1915 supervised_users::kApprovedExtensions, extension_id);
1916 syncer::SyncData sync_data =
1917 SupervisedUserSettingsService::CreateSyncDataForSetting(
jdoerrie122c4da2017-03-06 11:12:041918 key, base::Value(version));
mamire9609642016-06-28 22:17:541919
1920 SyncChangeList list(1, SyncChange(FROM_HERE, type, sync_data));
1921
1922 SupervisedUserSettingsService* supervised_user_settings_service =
1923 SupervisedUserSettingsServiceFactory::GetForProfile(profile());
1924 supervised_user_settings_service->ProcessSyncChanges(FROM_HERE, list);
1925 }
1926
1927 void CheckDisabledForCustodianApproval(const std::string& extension_id) {
1928 EXPECT_TRUE(registry()->disabled_extensions().Contains(extension_id));
1929 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile());
1930 EXPECT_TRUE(extension_prefs->HasDisableReason(
1931 extension_id,
Minh X. Nguyen45479012017-08-18 21:35:361932 extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
treib9afc6212015-10-30 18:49:581933 }
1934
1935 SupervisedUserService* supervised_user_service() {
1936 return SupervisedUserServiceFactory::GetForProfile(profile());
1937 }
1938
mamire9609642016-06-28 22:17:541939 static std::string RequestId(const std::string& extension_id,
1940 const std::string& version) {
1941 return SupervisedUserService::GetExtensionRequestId(
treib9afc6212015-10-30 18:49:581942 extension_id, base::Version(version));
1943 }
1944
1945 private:
1946 // This prevents the legacy supervised user init code from running.
1947 bool SetActive(bool active) override { return true; }
1948
1949 base::FilePath base_path() const {
1950 return data_dir().AppendASCII("permissions_increase");
1951 }
1952 base::FilePath dir_path(const std::string& version) const {
1953 return base_path().AppendASCII("v" + version);
1954 }
1955 base::FilePath pem_path() const {
1956 return base_path().AppendASCII("permissions.pem");
1957 }
treibb6af28cd2015-12-01 11:19:461958
1959 base::FieldTrialList field_trial_list_;
asvitkineb1db8262016-11-08 09:48:201960 base::test::ScopedFeatureList scoped_feature_list_;
treib9afc6212015-10-30 18:49:581961};
1962
1963class MockPermissionRequestCreator : public PermissionRequestCreator {
1964 public:
1965 MockPermissionRequestCreator() {}
1966 ~MockPermissionRequestCreator() override {}
1967
1968 bool IsEnabled() const override { return true; }
1969
1970 void CreateURLAccessRequest(const GURL& url_requested,
1971 const SuccessCallback& callback) override {
1972 FAIL();
1973 }
1974
mamire9609642016-06-28 22:17:541975 MOCK_METHOD2(CreateExtensionInstallRequest,
1976 void(const std::string& id,
1977 const SupervisedUserService::SuccessCallback& callback));
1978
treib9afc6212015-10-30 18:49:581979 MOCK_METHOD2(CreateExtensionUpdateRequest,
1980 void(const std::string& id,
1981 const SupervisedUserService::SuccessCallback& callback));
1982
1983 private:
1984 DISALLOW_COPY_AND_ASSIGN(MockPermissionRequestCreator);
1985};
1986
1987TEST_F(ExtensionServiceTestSupervised, InstallOnlyAllowedByCustodian) {
1988 InitServices(true /* profile_is_supervised */);
mamire9609642016-06-28 22:17:541989 InitSupervisedUserInitiatedExtensionInstallFeature(false);
treib9afc6212015-10-30 18:49:581990
mamir192d7882016-06-22 17:10:161991 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
1992
treib9afc6212015-10-30 18:49:581993 base::FilePath path1 = data_dir().AppendASCII("good.crx");
1994 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
1995 const Extension* extensions[] = {
1996 InstallCRX(path1, INSTALL_FAILED),
mamir192d7882016-06-22 17:10:161997 InstallCRX(path2, INSTALL_NEW)
treib9afc6212015-10-30 18:49:581998 };
1999
2000 // Only the extension with the "installed by custodian" flag should have been
2001 // installed and enabled.
2002 EXPECT_FALSE(extensions[0]);
2003 ASSERT_TRUE(extensions[1]);
2004 EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id()));
mamirf7715a2a2016-07-04 13:05:082005 EXPECT_FALSE(IsPendingCustodianApproval(extensions[1]->id()));
treib9afc6212015-10-30 18:49:582006}
2007
mamir192d7882016-06-22 17:10:162008TEST_F(ExtensionServiceTestSupervised,
2009 DelegatedAndPreinstalledExtensionIsSUFirst) {
2010 InitServices(false /* profile_is_supervised */);
mamire9609642016-06-28 22:17:542011 InitSupervisedUserInitiatedExtensionInstallFeature(false);
mamir192d7882016-06-22 17:10:162012
2013 // Install an extension.
2014 base::FilePath path = data_dir().AppendASCII("good.crx");
2015 const Extension* extension = InstallCRX(path, INSTALL_NEW);
2016 std::string id = extension->id();
2017 const std::string version("1.0.0.0");
2018 // It should be enabled.
2019 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2020
2021 // Now make the profile supervised.
2022 profile()->AsTestingProfile()->SetSupervisedUserId(
2023 supervised_users::kChildAccountSUID);
2024
2025 // It should not be enabled now (it is not loaded at all actually).
2026 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2027
2028 // Simulate data sync with the "was_installed_by_custodian" flag set to 1.
2029 sync_pb::EntitySpecifics specifics;
2030 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2031 ext_specifics->set_id(id);
2032 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:362033 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
mamir192d7882016-06-22 17:10:162034 ext_specifics->set_installed_by_custodian(true);
2035 ext_specifics->set_version(version);
2036
2037 SyncChangeList list =
2038 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2039
2040 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
2041
2042 // The extension should be enabled again.
2043 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2044 EXPECT_TRUE(extensions::util::WasInstalledByCustodian(id, profile()));
2045}
2046
2047TEST_F(ExtensionServiceTestSupervised,
2048 DelegatedAndPreinstalledExtensionSyncFirst) {
2049 InitServices(false /* profile_is_supervised */);
mamire9609642016-06-28 22:17:542050 InitSupervisedUserInitiatedExtensionInstallFeature(false);
mamir192d7882016-06-22 17:10:162051
2052 // Install an extension.
2053 base::FilePath path = data_dir().AppendASCII("good.crx");
2054 const Extension* extension = InstallCRX(path, INSTALL_NEW);
2055 std::string id = extension->id();
2056 const std::string version("1.0.0.0");
2057
2058 // It should be enabled.
2059 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2060
2061 // Simulate data sync with the "was_installed_by_custodian" flag set to 1.
2062 sync_pb::EntitySpecifics specifics;
2063 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2064 ext_specifics->set_id(id);
2065 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:362066 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
mamir192d7882016-06-22 17:10:162067 ext_specifics->set_installed_by_custodian(true);
2068 ext_specifics->set_version(version);
2069
2070 SyncChangeList list =
2071 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2072
2073 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
mamir192d7882016-06-22 17:10:162074 // The extension should be enabled.
2075 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2076 EXPECT_TRUE(extensions::util::WasInstalledByCustodian(id, profile()));
2077}
2078
mamire9609642016-06-28 22:17:542079TEST_F(ExtensionServiceTestSupervised,
2080 InstallAllowedByCustodianAndSupervisedUser) {
2081 InitServices(true /* profile_is_supervised */);
2082 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2083
2084 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
2085
2086 base::FilePath path1 = data_dir().AppendASCII("good.crx");
2087 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
2088 const Extension* extensions[] = {
2089 InstallCRX(path1, INSTALL_WITHOUT_LOAD),
2090 InstallCRX(path2, INSTALL_NEW)
2091 };
2092
2093 // Only the extension with the "installed by custodian" flag should have been
2094 // installed and enabled.
2095 // The extension missing the "installed by custodian" flag is a
2096 // supervised user initiated install and hence not enabled.
2097 ASSERT_TRUE(extensions[0]);
2098 ASSERT_TRUE(extensions[1]);
2099 EXPECT_TRUE(registry()->disabled_extensions().Contains(extensions[0]->id()));
mamirf7715a2a2016-07-04 13:05:082100 EXPECT_TRUE(IsPendingCustodianApproval(extensions[0]->id()));
mamire9609642016-06-28 22:17:542101 EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id()));
mamirf7715a2a2016-07-04 13:05:082102 EXPECT_FALSE(IsPendingCustodianApproval(extensions[1]->id()));
mamire9609642016-06-28 22:17:542103}
2104
2105TEST_F(ExtensionServiceTestSupervised,
2106 PreinstalledExtensionWithSUInitiatedInstalls) {
2107 InitServices(false /* profile_is_supervised */);
2108 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2109
2110 // Install an extension.
2111 base::FilePath path = data_dir().AppendASCII("good.crx");
2112 const Extension* extension = InstallCRX(path, INSTALL_NEW);
2113 std::string id = extension->id();
2114 // Make sure it's enabled.
2115 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2116
2117 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2118 supervised_user_service()->AddPermissionRequestCreator(
2119 base::WrapUnique(creator));
2120 const std::string version("1.0.0.0");
2121
2122 EXPECT_CALL(*creator, CreateExtensionInstallRequest(
2123 RequestId(good_crx, version), testing::_));
2124
2125 // Now make the profile supervised.
2126 profile()->AsTestingProfile()->SetSupervisedUserId(
2127 supervised_users::kChildAccountSUID);
2128
2129 Mock::VerifyAndClearExpectations(creator);
2130
2131 // The extension should not be enabled anymore.
2132 CheckDisabledForCustodianApproval(id);
mamirf7715a2a2016-07-04 13:05:082133 EXPECT_TRUE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542134}
2135
2136TEST_F(ExtensionServiceTestSupervised,
2137 PreinstalledExtensionWithoutSUInitiatedInstalls) {
2138 InitServices(false /* profile_is_supervised */);
2139 InitSupervisedUserInitiatedExtensionInstallFeature(false);
2140
2141 // Install an extension.
2142 base::FilePath path = data_dir().AppendASCII("good.crx");
2143 const Extension* extension = InstallCRX(path, INSTALL_NEW);
2144 std::string id = extension->id();
2145
2146 // Make sure it's enabled.
2147 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2148
2149 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2150 supervised_user_service()->AddPermissionRequestCreator(
2151 base::WrapUnique(creator));
2152 const std::string version("1.0.0.0");
2153
2154 // No request should be sent because supervised user initiated installs
2155 // are disabled.
2156 EXPECT_CALL(*creator, CreateExtensionInstallRequest(testing::_, testing::_))
2157 .Times(0);
2158
2159 // Now make the profile supervised.
2160 profile()->AsTestingProfile()->SetSupervisedUserId(
2161 supervised_users::kChildAccountSUID);
2162
Karan Bhatia2a117232017-08-23 00:24:562163 // The extension should now be disabled.
2164 EXPECT_TRUE(registry()->disabled_extensions().Contains(id));
2165 EXPECT_EQ(extensions::disable_reason::DISABLE_BLOCKED_BY_POLICY,
2166 ExtensionPrefs::Get(profile())->GetDisableReasons(id));
mamire9609642016-06-28 22:17:542167}
2168
2169TEST_F(ExtensionServiceTestSupervised, ExtensionApprovalBeforeInstallation) {
2170 // This tests the case when the sync entity flagging the extension as approved
2171 // arrives before the extension itself is installed.
2172 InitServices(true /* profile_is_supervised */);
2173 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2174
2175 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2176 supervised_user_service()->AddPermissionRequestCreator(
2177 base::WrapUnique(creator));
2178
2179 std::string id = good_crx;
2180 std::string version("1.0.0.0");
2181
2182 SimulateCustodianApprovalChangeViaSync(id, version, SyncChange::ACTION_ADD);
2183
2184 // Now install an extension.
2185 base::FilePath path = data_dir().AppendASCII("good.crx");
2186 InstallCRX(path, INSTALL_NEW);
2187
2188 // No approval request should be sent.
2189 EXPECT_CALL(*creator, CreateExtensionInstallRequest(testing::_, testing::_))
2190 .Times(0);
2191
2192 // Make sure it's enabled.
2193 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082194 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542195}
2196
treib9afc6212015-10-30 18:49:582197TEST_F(ExtensionServiceTestSupervised, UpdateWithoutPermissionIncrease) {
2198 InitServices(true /* profile_is_supervised */);
2199
treib9afc6212015-10-30 18:49:582200 // Save the id, as the extension object will be destroyed during updating.
mamire9609642016-06-28 22:17:542201 std::string id = InstallNoPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582202
2203 // Update to a new version.
mamire9609642016-06-28 22:17:542204 std::string version2("2");
2205 UpdateNoPermissionsTestExtension(id, version2, ENABLED);
treib9afc6212015-10-30 18:49:582206
2207 // The extension should still be there and enabled.
mamire9609642016-06-28 22:17:542208 const Extension* extension = registry()->enabled_extensions().GetByID(id);
treib9afc6212015-10-30 18:49:582209 ASSERT_TRUE(extension);
2210 // The version should have changed.
Devlin Cronin03bf2d22017-12-20 08:21:052211 EXPECT_EQ(base::Version(version2), extension->version());
mamirf7715a2a2016-07-04 13:05:082212 EXPECT_FALSE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582213}
2214
treib9afc6212015-10-30 18:49:582215TEST_F(ExtensionServiceTestSupervised,
2216 UpdateWithPermissionIncreaseApprovalOldVersion) {
treib9afc6212015-10-30 18:49:582217 InitServices(true /* profile_is_supervised */);
2218
2219 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2220 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222221 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582222
2223 const std::string version1("1");
2224 const std::string version2("2");
2225
mamire9609642016-06-28 22:17:542226 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582227
2228 // Update to a new version with increased permissions.
2229 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542230 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582231 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542232 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082233 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582234
2235 // Simulate a custodian approval for re-enabling the extension coming in
2236 // through Sync, but set the old version. This can happen when there already
2237 // was a pending request for an earlier version of the extension.
2238 sync_pb::EntitySpecifics specifics;
2239 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2240 ext_specifics->set_id(id);
2241 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:362242 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:582243 ext_specifics->set_installed_by_custodian(true);
2244 ext_specifics->set_version(version1);
2245
2246 // Attempting to re-enable an old version should result in a permission
2247 // request for the current version.
2248 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542249 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582250
treib65f103042015-12-03 10:21:362251 SyncChangeList list =
2252 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2253
2254 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582255 // The re-enable should be ignored, since the version doesn't match.
2256 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2257 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
2258 id, base::Version(version1)));
2259 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
2260 id, base::Version(version2)));
mamire9609642016-06-28 22:17:542261 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082262 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582263}
2264
2265TEST_F(ExtensionServiceTestSupervised,
2266 UpdateWithPermissionIncreaseApprovalMatchingVersion) {
treib9afc6212015-10-30 18:49:582267 InitServices(true /* profile_is_supervised */);
2268
2269 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2270 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222271 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582272
mamire9609642016-06-28 22:17:542273 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582274
2275 // Update to a new version with increased permissions.
2276 const std::string version2("2");
2277 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542278 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582279 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542280 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082281 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582282
2283 // Simulate a custodian approval for re-enabling the extension coming in
2284 // through Sync.
2285 sync_pb::EntitySpecifics specifics;
2286 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2287 ext_specifics->set_id(id);
2288 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:362289 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:582290 ext_specifics->set_installed_by_custodian(true);
2291 ext_specifics->set_version(version2);
2292
treib65f103042015-12-03 10:21:362293 SyncChangeList list =
2294 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2295
2296 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582297 // The extension should have gotten re-enabled.
2298 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082299 EXPECT_FALSE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582300}
2301
2302TEST_F(ExtensionServiceTestSupervised,
2303 UpdateWithPermissionIncreaseApprovalNewVersion) {
treib9afc6212015-10-30 18:49:582304 InitServices(true /* profile_is_supervised */);
2305
2306 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2307 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222308 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582309
mamire9609642016-06-28 22:17:542310 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582311
2312 // Update to a new version with increased permissions.
2313 const std::string version2("2");
2314 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542315 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582316 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542317 Mock::VerifyAndClearExpectations(creator);
treib9afc6212015-10-30 18:49:582318
2319 // Simulate a custodian approval for re-enabling the extension coming in
2320 // through Sync. Set a newer version than we have installed.
2321 const std::string version3("3");
2322 sync_pb::EntitySpecifics specifics;
2323 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2324 ext_specifics->set_id(id);
2325 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:362326 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:582327 ext_specifics->set_installed_by_custodian(true);
2328 ext_specifics->set_version(version3);
2329
2330 // This should *not* result in a new permission request.
2331 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542332 RequestId(id, version3), testing::_))
treib9afc6212015-10-30 18:49:582333 .Times(0);
2334
treib65f103042015-12-03 10:21:362335 SyncChangeList list =
2336 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2337
2338 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582339 // The re-enable should be delayed until the extension is updated to the
2340 // matching version.
2341 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2342 EXPECT_TRUE(extension_sync_service()->HasPendingReenable(
2343 id, base::Version(version3)));
2344
2345 // Update to the matching version. Now the extension should get enabled.
2346 UpdatePermissionsTestExtension(id, version3, ENABLED);
2347}
2348
mamire9609642016-06-28 22:17:542349TEST_F(ExtensionServiceTestSupervised, SupervisedUserInitiatedInstalls) {
mamire9609642016-06-28 22:17:542350 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2351
2352 InitServices(true /* profile_is_supervised */);
2353
2354 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2355 supervised_user_service()->AddPermissionRequestCreator(
2356 base::WrapUnique(creator));
2357
2358 base::FilePath path = data_dir().AppendASCII("good.crx");
2359 std::string version("1.0.0.0");
2360
2361 EXPECT_CALL(*creator, CreateExtensionInstallRequest(
2362 RequestId(good_crx, version), testing::_));
2363
2364 // Should be installed but disabled, a request for approval should be sent.
2365 const Extension* extension = InstallCRX(path, INSTALL_WITHOUT_LOAD);
2366 ASSERT_TRUE(extension);
2367 ASSERT_EQ(extension->id(), good_crx);
2368 EXPECT_TRUE(registry()->disabled_extensions().Contains(good_crx));
2369 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082370 EXPECT_TRUE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542371
2372 SimulateCustodianApprovalChangeViaSync(good_crx, version,
2373 SyncChange::ACTION_ADD);
2374
2375 // The extension should be enabled now.
2376 EXPECT_TRUE(registry()->enabled_extensions().Contains(good_crx));
mamirf7715a2a2016-07-04 13:05:082377 EXPECT_FALSE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542378
2379 // Simulate approval removal coming via Sync.
2380 SimulateCustodianApprovalChangeViaSync(good_crx, version,
2381 SyncChange::ACTION_DELETE);
2382
2383 // The extension should be disabled now.
2384 EXPECT_TRUE(registry()->disabled_extensions().Contains(good_crx));
mamirf7715a2a2016-07-04 13:05:082385 EXPECT_TRUE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542386}
2387
2388TEST_F(ExtensionServiceTestSupervised,
2389 UpdateSUInitiatedInstallWithoutPermissionIncrease) {
mamire9609642016-06-28 22:17:542390 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2391
2392 InitServices(true /* profile_is_supervised */);
2393
2394 std::string id = InstallNoPermissionsTestExtension(false /* by_custodian */);
2395 std::string version1("1");
2396
2397 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2398
2399 // The extension should be enabled now.
2400 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2401
2402 std::string version2("2");
2403
2404 // Update to a new version.
2405 UpdateNoPermissionsTestExtension(id, version2, ENABLED);
2406
2407 // The extension should still be there and enabled.
2408 const Extension* extension = registry()->enabled_extensions().GetByID(id);
2409 ASSERT_TRUE(extension);
2410 // The version should have increased.
Devlin Cronin03bf2d22017-12-20 08:21:052411 EXPECT_EQ(1, extension->version().CompareTo(base::Version(version1)));
mamire9609642016-06-28 22:17:542412
2413 // Check that the approved version has been updated in the prefs as well.
2414 // Prefs are updated via Sync. If the prefs are updated, then the new
2415 // approved version has been pushed to Sync as well.
2416 std::string approved_version;
2417 PrefService* pref_service = profile()->GetPrefs();
2418 const base::DictionaryValue* approved_extensions =
2419 pref_service->GetDictionary(prefs::kSupervisedUserApprovedExtensions);
2420 approved_extensions->GetStringWithoutPathExpansion(id, &approved_version);
2421
Devlin Cronin03bf2d22017-12-20 08:21:052422 EXPECT_EQ(base::Version(approved_version), extension->version());
mamirf7715a2a2016-07-04 13:05:082423 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542424}
2425
2426TEST_F(ExtensionServiceTestSupervised,
2427 UpdateSUInitiatedInstallWithPermissionIncrease) {
mamire9609642016-06-28 22:17:542428 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2429
2430 InitServices(true /* profile_is_supervised */);
2431
2432 std::string id = InstallPermissionsTestExtension(false /* by_custodian */);
2433 std::string version1("1");
2434
2435 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2436
2437 // The extension should be enabled now.
2438 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2439
2440 std::string version3("3");
2441
2442 UpdatePermissionsTestExtension(id, version3, DISABLED);
2443
2444 // The extension should be disabled.
2445 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2446 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:362447 id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE));
mamire9609642016-06-28 22:17:542448
2449 std::string version2("2");
2450 // Approve an older version
2451 SimulateCustodianApprovalChangeViaSync(id, version2,
2452 SyncChange::ACTION_UPDATE);
2453
2454 // The extension should remain disabled.
2455 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2456 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:362457 id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE));
mamire9609642016-06-28 22:17:542458 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:362459 id, extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
mamire9609642016-06-28 22:17:542460
mamirf7715a2a2016-07-04 13:05:082461 EXPECT_TRUE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542462 // Approve the latest version
2463 SimulateCustodianApprovalChangeViaSync(id, version3,
2464 SyncChange::ACTION_UPDATE);
2465
2466 // The extension should be enabled again.
2467 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082468 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542469}
2470
2471TEST_F(ExtensionServiceTestSupervised,
2472 UpdateSUInitiatedInstallWithPermissionIncreaseApprovalArrivesFirst) {
mamire9609642016-06-28 22:17:542473 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2474
2475 InitServices(true /* profile_is_supervised */);
2476
2477 std::string id = InstallPermissionsTestExtension(false /* by_custodian */);
2478
2479 std::string version1("1");
2480 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2481
2482 // The extension should be enabled now.
2483 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2484
2485 std::string version2("2");
2486 // Approve a newer version
2487 SimulateCustodianApprovalChangeViaSync(id, version2,
2488 SyncChange::ACTION_UPDATE);
2489
2490 // The extension should be disabled.
2491 CheckDisabledForCustodianApproval(id);
2492
2493 // Now update the extension to the same version that was approved.
2494 UpdatePermissionsTestExtension(id, version2, ENABLED);
2495 // The extension should be enabled again.
2496 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082497 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542498}
2499
treib9afc6212015-10-30 18:49:582500TEST_F(ExtensionServiceSyncTest, SyncUninstallByCustodianSkipsPolicy) {
2501 InitializeEmptyExtensionService();
2502 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:362503 syncer::EXTENSIONS, syncer::SyncDataList(),
Jinho Bangb5216cec2018-01-17 19:43:112504 std::make_unique<syncer::FakeSyncChangeProcessor>(),
2505 std::make_unique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:582506
mamir192d7882016-06-22 17:10:162507 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
treib9afc6212015-10-30 18:49:582508 // Install two extensions.
2509 base::FilePath path1 = data_dir().AppendASCII("good.crx");
2510 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
2511 const Extension* extensions[] = {
2512 InstallCRX(path1, INSTALL_NEW),
mamir192d7882016-06-22 17:10:162513 InstallCRX(path2, INSTALL_NEW)
treib9afc6212015-10-30 18:49:582514 };
2515
2516 // Add a policy provider that will disallow any changes.
2517 extensions::TestManagementPolicyProvider provider(
2518 extensions::TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS);
2519 ExtensionSystem::Get(
2520 browser_context())->management_policy()->RegisterProvider(&provider);
2521
2522 // Create a sync deletion for each extension.
treib65f103042015-12-03 10:21:362523 SyncChangeList list;
treib9afc6212015-10-30 18:49:582524 for (size_t i = 0; i < arraysize(extensions); i++) {
2525 const std::string& id = extensions[i]->id();
2526 sync_pb::EntitySpecifics specifics;
2527 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2528 ext_specifics->set_id(id);
2529 ext_specifics->set_version("1.0");
2530 ext_specifics->set_installed_by_custodian(
mamir192d7882016-06-22 17:10:162531 extensions::util::WasInstalledByCustodian(id, profile()));
2532
treib9afc6212015-10-30 18:49:582533 syncer::SyncData sync_data =
2534 syncer::SyncData::CreateLocalData(id, "Name", specifics);
treib65f103042015-12-03 10:21:362535 list.push_back(SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, sync_data));
treib9afc6212015-10-30 18:49:582536 }
2537
2538 // Save the extension ids, as uninstalling destroys the Extension instance.
2539 std::string extension_ids[] = {
2540 extensions[0]->id(),
2541 extensions[1]->id()
2542 };
2543
2544 // Now apply the uninstallations.
treib65f103042015-12-03 10:21:362545 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582546
2547 // Uninstalling the extension without installed_by_custodian should have been
2548 // blocked by policy, so it should still be there.
2549 EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_ids[0]));
2550
2551 // But installed_by_custodian should result in bypassing the policy check.
2552 EXPECT_FALSE(
2553 registry()->GenerateInstalledExtensionsSet()->Contains(extension_ids[1]));
2554}
2555
rdevlin.cronin738501d2015-11-05 21:51:362556TEST_F(ExtensionServiceSyncTest, SyncExtensionHasAllhostsWithheld) {
2557 InitializeEmptyExtensionService();
asargente48ab752016-03-12 00:59:202558 StartSyncing(syncer::EXTENSIONS);
rdevlin.cronin738501d2015-11-05 21:51:362559
2560 // Create an extension that needs all-hosts.
2561 const std::string kName("extension");
2562 scoped_refptr<const Extension> extension =
Devlin Cronin3f5b18f2017-08-22 21:54:052563 extensions::ExtensionBuilder(kName)
limasdf3d102542015-12-09 03:58:452564 .SetLocation(Manifest::INTERNAL)
Devlin Cronin3f5b18f2017-08-22 21:54:052565 .AddPermission("*://*/*")
limasdf3d102542015-12-09 03:58:452566 .Build();
rdevlin.cronin738501d2015-11-05 21:51:362567
2568 // Install and enable it.
2569 service()->AddExtension(extension.get());
2570 service()->GrantPermissionsAndEnableExtension(extension.get());
2571 const std::string id = extension->id();
2572 EXPECT_TRUE(registry()->enabled_extensions().GetByID(id));
2573
2574 // Simulate a sync node coming in where the extension had all-hosts withheld.
2575 // This means that it should have all-hosts withheld on this machine, too.
rdevlin.cronin738501d2015-11-05 21:51:362576 sync_pb::EntitySpecifics specifics;
2577 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2578 ext_specifics->set_id(id);
2579 ext_specifics->set_name(kName);
2580 ext_specifics->set_version("1.0");
2581 ext_specifics->set_all_urls_enabled(false);
2582 ext_specifics->set_enabled(true);
rdevlin.cronin738501d2015-11-05 21:51:362583
treib65f103042015-12-03 10:21:362584 SyncChangeList list =
2585 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2586
2587 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
rdevlin.cronin738501d2015-11-05 21:51:362588
rdevlin.cronind01837b2016-08-17 01:37:182589 const Extension* enabled_extension =
2590 registry()->enabled_extensions().GetByID(id);
2591 ASSERT_TRUE(enabled_extension);
2592 ScriptingPermissionsModifier modifier(profile(), enabled_extension);
2593 EXPECT_FALSE(modifier.IsAllowedOnAllUrls());
2594 EXPECT_TRUE(modifier.HasSetAllowedOnAllUrls());
rdevlin.cronin738501d2015-11-05 21:51:362595}
2596
brettw9e85ef42016-11-01 21:01:242597#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
asargente48ab752016-03-12 00:59:202598
2599// Tests sync behavior in the case of an item that starts out as an app and
2600// gets updated to become an extension.
2601TEST_F(ExtensionServiceSyncTest, AppToExtension) {
2602 InitializeEmptyExtensionService();
2603 service()->Init();
2604 ASSERT_TRUE(service()->is_ready());
2605
2606 // Install v1, which is an app.
2607 const Extension* v1 =
2608 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v1.crx"),
2609 INSTALL_NEW);
2610 EXPECT_TRUE(v1->is_app());
2611 EXPECT_FALSE(v1->is_extension());
2612 std::string id = v1->id();
2613
2614 StatefulChangeProcessor extensions_processor(syncer::ModelType::EXTENSIONS);
2615 StatefulChangeProcessor apps_processor(syncer::ModelType::APPS);
2616 extension_sync_service()->MergeDataAndStartSyncing(
2617 syncer::EXTENSIONS, syncer::SyncDataList(),
2618 extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222619 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202620 extension_sync_service()->MergeDataAndStartSyncing(
2621 syncer::APPS, syncer::SyncDataList(), apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222622 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202623
2624 // Check the app/extension change processors to be sure the right data was
2625 // added.
2626 EXPECT_TRUE(extensions_processor.changes().empty());
2627 EXPECT_TRUE(extensions_processor.data().empty());
2628 EXPECT_EQ(1u, apps_processor.data().size());
2629 ASSERT_EQ(1u, apps_processor.changes().size());
2630 const SyncChange& app_change = apps_processor.changes()[0];
2631 EXPECT_EQ(SyncChange::ACTION_ADD, app_change.change_type());
dchengc963c7142016-04-08 03:55:222632 std::unique_ptr<ExtensionSyncData> app_data =
asargente48ab752016-03-12 00:59:202633 ExtensionSyncData::CreateFromSyncData(app_change.sync_data());
2634 EXPECT_TRUE(app_data->is_app());
2635 EXPECT_EQ(id, app_data->id());
Devlin Cronin03bf2d22017-12-20 08:21:052636 EXPECT_EQ(v1->version(), app_data->version());
asargente48ab752016-03-12 00:59:202637
2638 // Update the app to v2, which is an extension.
2639 const Extension* v2 =
2640 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v2.crx"),
2641 INSTALL_UPDATED);
2642 EXPECT_FALSE(v2->is_app());
2643 EXPECT_TRUE(v2->is_extension());
2644 EXPECT_EQ(id, v2->id());
2645
2646 // Make sure we saw an extension item added.
2647 ASSERT_EQ(1u, extensions_processor.changes().size());
2648 const SyncChange& extension_change = extensions_processor.changes()[0];
2649 EXPECT_EQ(SyncChange::ACTION_ADD, extension_change.change_type());
dchengc963c7142016-04-08 03:55:222650 std::unique_ptr<ExtensionSyncData> extension_data =
asargente48ab752016-03-12 00:59:202651 ExtensionSyncData::CreateFromSyncData(extension_change.sync_data());
2652 EXPECT_FALSE(extension_data->is_app());
2653 EXPECT_EQ(id, extension_data->id());
Devlin Cronin03bf2d22017-12-20 08:21:052654 EXPECT_EQ(v2->version(), extension_data->version());
asargente48ab752016-03-12 00:59:202655
2656 // Get the current data from the change processors to use as the input to
2657 // the following call to MergeDataAndStartSyncing. This simulates what should
2658 // happen with sync.
2659 syncer::SyncDataList extensions_data =
2660 extensions_processor.GetAllSyncData(syncer::EXTENSIONS);
2661 syncer::SyncDataList apps_data = apps_processor.GetAllSyncData(syncer::APPS);
2662
2663 // Stop syncing, then start again.
2664 extension_sync_service()->StopSyncing(syncer::EXTENSIONS);
2665 extension_sync_service()->StopSyncing(syncer::APPS);
2666 extension_sync_service()->MergeDataAndStartSyncing(
2667 syncer::EXTENSIONS, extensions_data, extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222668 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202669 extension_sync_service()->MergeDataAndStartSyncing(
2670 syncer::APPS, apps_data, apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222671 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202672
2673 // Make sure we saw an app item deleted.
2674 bool found_delete = false;
2675 for (const auto& change : apps_processor.changes()) {
2676 if (change.change_type() == SyncChange::ACTION_DELETE) {
dchengc963c7142016-04-08 03:55:222677 std::unique_ptr<ExtensionSyncData> data =
asargente48ab752016-03-12 00:59:202678 ExtensionSyncData::CreateFromSyncChange(change);
2679 if (data->id() == id) {
2680 found_delete = true;
2681 break;
2682 }
2683 }
2684 }
2685 EXPECT_TRUE(found_delete);
2686
2687 // Make sure there is one extension, and there are no more apps.
2688 EXPECT_EQ(1u, extensions_processor.data().size());
2689 EXPECT_TRUE(apps_processor.data().empty());
2690}
proberge901ecab2017-08-31 19:24:282691
2692class BlacklistedExtensionSyncServiceTest : public ExtensionServiceSyncTest {
2693 public:
2694 BlacklistedExtensionSyncServiceTest() {}
2695
2696 void SetUp() override {
2697 ExtensionServiceSyncTest::SetUp();
2698
2699 InitializeEmptyExtensionService();
2700
2701 // Enable sync.
2702 browser_sync::ProfileSyncService* sync_service =
2703 ProfileSyncServiceFactory::GetForProfile(profile());
2704 sync_service->SetFirstSetupComplete();
2705
2706 test_blacklist_.Attach(service()->blacklist_);
2707 service()->Init();
2708
2709 // Load up a simple extension.
2710 extensions::ChromeTestExtensionLoader extension_loader(profile());
2711 extension_loader.set_pack_extension(true);
2712 extension_ = extension_loader.LoadExtension(
2713 data_dir().AppendASCII("simple_with_file"));
2714 ASSERT_TRUE(extension_);
2715 extension_id_ = extension_->id();
2716 ASSERT_TRUE(registry()->enabled_extensions().GetByID(extension_id_));
2717
2718 {
Jinho Bangb5216cec2018-01-17 19:43:112719 auto processor = std::make_unique<syncer::FakeSyncChangeProcessor>();
proberge901ecab2017-08-31 19:24:282720 processor_raw_ = processor.get();
2721 extension_sync_service()->MergeDataAndStartSyncing(
2722 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
Jinho Bangb5216cec2018-01-17 19:43:112723 std::make_unique<syncer::SyncErrorFactoryMock>());
proberge901ecab2017-08-31 19:24:282724 }
2725 processor_raw_->changes().clear();
2726 }
2727
2728 void ForceBlacklistUpdate() {
2729 service()->OnBlacklistUpdated();
Gabriel Charette01507a22017-09-27 21:30:082730 content::RunAllTasksUntilIdle();
proberge901ecab2017-08-31 19:24:282731 }
2732
2733 syncer::FakeSyncChangeProcessor* processor() { return processor_raw_; }
2734
2735 const Extension* extension() { return extension_.get(); }
2736
2737 std::string& extension_id() { return extension_id_; }
2738
2739 extensions::TestBlacklist& test_blacklist() { return test_blacklist_; }
2740
2741 private:
2742 syncer::FakeSyncChangeProcessor* processor_raw_;
2743 scoped_refptr<const Extension> extension_;
2744 std::string extension_id_;
2745 extensions::TestBlacklist test_blacklist_;
2746
2747 DISALLOW_COPY_AND_ASSIGN(BlacklistedExtensionSyncServiceTest);
2748};
2749
2750// Test that sync cannot enable blacklisted extensions.
2751TEST_F(BlacklistedExtensionSyncServiceTest, SyncBlacklistedExtension) {
2752 std::string& extension_id = this->extension_id();
2753
2754 // Blacklist the extension.
2755 test_blacklist().SetBlacklistState(extension_id,
2756 extensions::BLACKLISTED_MALWARE, true);
2757 ForceBlacklistUpdate();
2758
2759 // Try enabling the extension via sync.
2760 EnableExtensionFromSync(*extension());
2761
2762 // The extension should not be enabled.
2763 EXPECT_FALSE(registry()->enabled_extensions().GetByID(extension_id));
2764 EXPECT_TRUE(processor()->changes().empty());
2765}
2766
2767// Test that some greylisted extensions can be enabled through sync.
2768TEST_F(BlacklistedExtensionSyncServiceTest, SyncAllowedGreylistedExtension) {
2769 std::string& extension_id = this->extension_id();
2770
2771 // Greylist the extension.
2772 test_blacklist().SetBlacklistState(
2773 extension_id, extensions::BLACKLISTED_POTENTIALLY_UNWANTED, true);
2774 ForceBlacklistUpdate();
2775
2776 EXPECT_FALSE(registry()->enabled_extensions().GetByID(extension_id));
2777 {
2778 ASSERT_EQ(1u, processor()->changes().size());
2779 const SyncChange& change = processor()->changes()[0];
2780 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
2781 std::unique_ptr<ExtensionSyncData> data =
2782 ExtensionSyncData::CreateFromSyncData(change.sync_data());
2783 EXPECT_EQ(extension_id, data->id());
2784 EXPECT_EQ(extensions::disable_reason::DISABLE_GREYLIST,
2785 data->disable_reasons());
2786 EXPECT_FALSE(data->enabled());
2787 }
2788 processor()->changes().clear();
2789
2790 // Manually re-enabling the extension should work.
2791 service()->EnableExtension(extension_id);
2792 EXPECT_TRUE(registry()->enabled_extensions().GetByID(extension_id));
2793 {
2794 ASSERT_EQ(1u, processor()->changes().size());
2795 const SyncChange& change = processor()->changes()[0];
2796 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
2797 std::unique_ptr<ExtensionSyncData> data =
2798 ExtensionSyncData::CreateFromSyncData(change.sync_data());
2799 EXPECT_EQ(extension_id, data->id());
2800 EXPECT_EQ(0, data->disable_reasons());
2801 EXPECT_TRUE(data->enabled());
2802 }
2803 processor()->changes().clear();
2804}