blob: ba2d36517bbd2b8368e0409c5992df4344ec8016 [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"
37#include "chrome/common/chrome_switches.h"
38#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"
50#include "extensions/browser/extension_prefs.h"
51#include "extensions/browser/extension_registry.h"
52#include "extensions/browser/extension_system.h"
karandeepb810e33402017-04-05 23:41:2253#include "extensions/browser/extension_util.h"
treib9afc6212015-10-30 18:49:5854#include "extensions/browser/management_policy.h"
55#include "extensions/browser/test_management_policy.h"
Minh X. Nguyen45479012017-08-18 21:35:3656#include "extensions/common/disable_reason.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() {
ricea91d6fc122016-08-30 08:47:14197 return base::MakeUnique<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(),
ricea91d6fc122016-08-30 08:47:14225 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
226 base::MakeUnique<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(),
ricea91d6fc122016-08-30 08:47:14335 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
336 base::MakeUnique<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(),
ricea91d6fc122016-08-30 08:47:14370 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
371 base::MakeUnique<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 {
406 auto processor = base::MakeUnique<syncer::FakeSyncChangeProcessor>();
407 processor_raw = processor.get();
408 extension_sync_service()->MergeDataAndStartSyncing(
409 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
410 base::MakeUnique<syncer::SyncErrorFactoryMock>());
411 }
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 {
492 auto processor = base::MakeUnique<syncer::FakeSyncChangeProcessor>();
493 processor_raw = processor.get();
494 extension_sync_service()->MergeDataAndStartSyncing(
495 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
496 base::MakeUnique<syncer::SyncErrorFactoryMock>());
497 }
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,
ricea91d6fc122016-08-30 08:47:14579 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
580 base::MakeUnique<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),
ricea91d6fc122016-08-30 08:47:14611 base::MakeUnique<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(),
ricea91d6fc122016-08-30 08:47:14691 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
692 base::MakeUnique<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());
robpercivaldcd8b102016-01-25 19:39:00706 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(),
ricea91d6fc122016-08-30 08:47:14720 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
721 base::MakeUnique<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(),
ricea91d6fc122016-08-30 08:47:14799 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
800 base::MakeUnique<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());
robpercivaldcd8b102016-01-25 19:39:00814 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(),
ricea91d6fc122016-08-30 08:47:14828 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
829 base::MakeUnique<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(),
ricea91d6fc122016-08-30 08:47:14844 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
845 base::MakeUnique<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(),
ricea91d6fc122016-08-30 08:47:14914 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
915 base::MakeUnique<syncer::SyncErrorFactoryMock>());
asargente48ab752016-03-12 00:59:20916 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:58917
918 UninstallExtension(good_crx, false);
919 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(),
ricea91d6fc122016-08-30 08:47:14947 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
948 base::MakeUnique<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(),
ricea91d6fc122016-08-30 08:47:141051 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1052 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581053 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361054 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141055 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1056 base::MakeUnique<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(),
ricea91d6fc122016-08-30 08:47:141071 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1072 base::MakeUnique<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(
1116 service()->GetInstalledExtension(good_crx)->version()->GetString());
1117
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(),
ricea91d6fc122016-08-30 08:47:141145 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1146 base::MakeUnique<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);
1157 return base::MakeUnique<ScriptingPermissionsModifier>(profile(), extension);
1158 };
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(
1169 service()->GetInstalledExtension(good_crx)->version()->GetString());
1170 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(),
ricea91d6fc122016-08-30 08:47:141242 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1243 base::MakeUnique<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));
1308
1309 // Remove the extension again, so we can install it again for the next case.
1310 UninstallExtension(good_crx, false,
1311 test_case.sync_enabled ? Extension::ENABLED
1312 : Extension::DISABLED);
1313 }
1314}
1315
1316TEST_F(ExtensionServiceSyncTest, ProcessSyncDataTerminatedExtension) {
1317 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581318 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361319 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141320 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1321 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581322
1323 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1324 TerminateExtension(good_crx);
1325 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1326 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1327
1328 sync_pb::EntitySpecifics specifics;
1329 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1330 ext_specifics->set_id(good_crx);
1331 ext_specifics->set_version(
1332 service()->GetInstalledExtension(good_crx)->version()->GetString());
1333 ext_specifics->set_enabled(false);
1334 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361335
1336 SyncChangeList list =
1337 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581338
1339 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1340 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1341 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1342
1343 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1344}
1345
1346TEST_F(ExtensionServiceSyncTest, ProcessSyncDataVersionCheck) {
1347 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581348 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361349 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141350 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1351 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581352
1353 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1354 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1355 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1356
1357 sync_pb::EntitySpecifics specifics;
1358 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1359 ext_specifics->set_id(good_crx);
1360 ext_specifics->set_enabled(true);
1361
1362 const base::Version installed_version =
1363 *service()->GetInstalledExtension(good_crx)->version();
1364
1365 {
1366 ext_specifics->set_version(installed_version.GetString());
treib65f103042015-12-03 10:21:361367
1368 SyncChangeList list =
1369 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581370
1371 // Should do nothing if extension version == sync version.
1372 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1373 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1374 // Make sure the version we'll send back to sync didn't change.
1375 syncer::SyncDataList data =
1376 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1377 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221378 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581379 ExtensionSyncData::CreateFromSyncData(data[0]);
1380 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001381 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581382 }
1383
1384 // Should do nothing if extension version > sync version.
1385 {
1386 ext_specifics->set_version("0.0.0.0");
treib65f103042015-12-03 10:21:361387
1388 SyncChangeList list =
1389 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581390
1391 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1392 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1393 // Make sure the version we'll send back to sync didn't change.
1394 syncer::SyncDataList data =
1395 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1396 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221397 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581398 ExtensionSyncData::CreateFromSyncData(data[0]);
1399 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001400 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581401 }
1402
1403 // Should kick off an update if extension version < sync version.
1404 {
1405 const base::Version new_version("9.9.9.9");
1406 ext_specifics->set_version(new_version.GetString());
treib65f103042015-12-03 10:21:361407
1408 SyncChangeList list =
1409 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581410
1411 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1412 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1413 // Make sure that we'll send the NEW version back to sync, even though we
1414 // haven't actually updated yet. This is to prevent the data in sync from
1415 // flip-flopping back and forth until all clients are up to date.
1416 syncer::SyncDataList data =
1417 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1418 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221419 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581420 ExtensionSyncData::CreateFromSyncData(data[0]);
1421 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001422 EXPECT_EQ(new_version, extension_data->version());
treib9afc6212015-10-30 18:49:581423 }
1424
1425 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1426}
1427
1428TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNotInstalled) {
1429 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581430 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361431 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141432 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1433 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581434
1435 sync_pb::EntitySpecifics specifics;
1436 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1437 ext_specifics->set_id(good_crx);
1438 ext_specifics->set_enabled(false);
1439 ext_specifics->set_incognito_enabled(true);
1440 ext_specifics->set_update_url("http://www.google.com/");
1441 ext_specifics->set_version("1.2.3.4");
treib65f103042015-12-03 10:21:361442
1443 SyncChangeList list =
1444 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581445
1446 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1447 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1448 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1449 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1450 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1451 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1452
1453 const extensions::PendingExtensionInfo* info;
1454 EXPECT_TRUE(
1455 (info = service()->pending_extension_manager()->GetById(good_crx)));
1456 EXPECT_EQ(ext_specifics->update_url(), info->update_url().spec());
1457 EXPECT_TRUE(info->is_from_sync());
1458 EXPECT_EQ(Manifest::INTERNAL, info->install_source());
1459 // TODO(akalin): Figure out a way to test |info.ShouldAllowInstall()|.
1460}
1461
1462TEST_F(ExtensionServiceSyncTest, ProcessSyncDataEnableDisable) {
1463 InitializeEmptyExtensionService();
1464 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361465 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141466 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1467 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581468
1469 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1470
1471 struct TestCase {
1472 const char* name; // For failure output only.
1473 // Set of disable reasons before any Sync data comes in. If this is != 0,
1474 // the extension is disabled.
1475 int previous_disable_reasons;
1476 bool sync_enable; // The enabled flag coming in from Sync.
1477 // The disable reason(s) coming in from Sync, or -1 for "not set".
1478 int sync_disable_reasons;
1479 // The expected set of disable reasons after processing the Sync update. The
1480 // extension should be disabled iff this is != 0.
1481 int expect_disable_reasons;
1482 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361483 {"NopEnable", 0, true, 0, 0},
1484 {"NopDisable", extensions::disable_reason::DISABLE_USER_ACTION, false,
1485 extensions::disable_reason::DISABLE_USER_ACTION,
1486 extensions::disable_reason::DISABLE_USER_ACTION},
1487 {"Enable", extensions::disable_reason::DISABLE_USER_ACTION, true, 0, 0},
1488 {"Disable", 0, false, extensions::disable_reason::DISABLE_USER_ACTION,
1489 extensions::disable_reason::DISABLE_USER_ACTION},
1490 {"AddDisableReason", extensions::disable_reason::DISABLE_REMOTE_INSTALL,
1491 false,
1492 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1493 extensions::disable_reason::DISABLE_USER_ACTION,
1494 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1495 extensions::disable_reason::DISABLE_USER_ACTION},
1496 {"RemoveDisableReason",
1497 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1498 extensions::disable_reason::DISABLE_USER_ACTION,
1499 false, extensions::disable_reason::DISABLE_USER_ACTION,
1500 extensions::disable_reason::DISABLE_USER_ACTION},
1501 {"PreserveLocalDisableReason", extensions::disable_reason::DISABLE_RELOAD,
1502 true, 0, extensions::disable_reason::DISABLE_RELOAD},
1503 {"PreserveOnlyLocalDisableReason",
1504 extensions::disable_reason::DISABLE_USER_ACTION |
1505 extensions::disable_reason::DISABLE_RELOAD,
1506 true, 0, extensions::disable_reason::DISABLE_RELOAD},
treib29e1b9b12015-11-11 08:50:561507
Minh X. Nguyen45479012017-08-18 21:35:361508 // Interaction with Chrome clients <=M44, which don't sync disable_reasons
1509 // at all (any existing reasons are preserved).
1510 {"M44Enable", extensions::disable_reason::DISABLE_USER_ACTION, true, -1,
1511 0},
1512 // An M44 client enables an extension that had been disabled on a new
1513 // client. The disable reasons are still be there, but should be ignored.
1514 {"M44ReEnable", extensions::disable_reason::DISABLE_USER_ACTION, true,
1515 extensions::disable_reason::DISABLE_USER_ACTION, 0},
1516 {"M44Disable", 0, false, -1,
1517 extensions::disable_reason::DISABLE_USER_ACTION},
1518 {"M44ReDisable", 0, false, 0,
1519 extensions::disable_reason::DISABLE_USER_ACTION},
1520 {"M44AlreadyDisabledByUser",
1521 extensions::disable_reason::DISABLE_USER_ACTION, false, -1,
1522 extensions::disable_reason::DISABLE_USER_ACTION},
1523 {"M44AlreadyDisabledWithOtherReason",
1524 extensions::disable_reason::DISABLE_REMOTE_INSTALL, false, -1,
1525 extensions::disable_reason::DISABLE_REMOTE_INSTALL |
1526 extensions::disable_reason::DISABLE_USER_ACTION},
treib9afc6212015-10-30 18:49:581527 };
1528
1529 for (const TestCase& test_case : test_cases) {
1530 SCOPED_TRACE(test_case.name);
1531
1532 std::string id;
1533 std::string version;
1534 // Don't keep |extension| around longer than necessary.
1535 {
1536 const Extension* extension =
1537 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1538 // The extension should now be installed and enabled.
1539 ASSERT_TRUE(extension);
1540 id = extension->id();
1541 version = extension->VersionString();
1542 }
1543 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1544
1545 // Disable it if the test case says so.
1546 if (test_case.previous_disable_reasons) {
1547 service()->DisableExtension(id, test_case.previous_disable_reasons);
1548 ASSERT_TRUE(registry()->disabled_extensions().Contains(id));
1549 }
1550
1551 // Now a sync update comes in.
1552 sync_pb::EntitySpecifics specifics;
1553 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1554 ext_specifics->set_id(id);
1555 ext_specifics->set_enabled(test_case.sync_enable);
1556 ext_specifics->set_version(version);
1557 if (test_case.sync_disable_reasons != -1)
1558 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1559
treib65f103042015-12-03 10:21:361560 SyncChangeList list =
1561 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1562
treib9afc6212015-10-30 18:49:581563 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1564
1565 // Check expectations.
1566 const bool expect_enabled = !test_case.expect_disable_reasons;
1567 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1568 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
1569
1570 // Remove the extension again, so we can install it again for the next case.
1571 UninstallExtension(id, false, expect_enabled ? Extension::ENABLED
1572 : Extension::DISABLED);
1573 }
1574}
1575
1576TEST_F(ExtensionServiceSyncTest, ProcessSyncDataDeferredEnable) {
rdevlin.cronin2f1ed4c2017-06-13 16:22:131577 // The permissions_increase test extension has a different update URL.
1578 // In order to make it syncable, we have to pretend it syncs from the
1579 // webstore.
1580 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1581 switches::kAppsGalleryUpdateURL,
1582 "http://localhost/autoupdate/updates.xml");
1583
treib9afc6212015-10-30 18:49:581584 InitializeEmptyExtensionService();
1585 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361586 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141587 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1588 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581589
1590 base::FilePath base_path = data_dir().AppendASCII("permissions_increase");
1591 base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1592
1593 base::FilePath path = base_path.AppendASCII("v1");
1594 const Extension* extension = PackAndInstallCRX(path, pem_path, INSTALL_NEW);
1595 // The extension must now be installed and enabled.
1596 ASSERT_TRUE(extension);
1597 ASSERT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
1598
1599 // Save the id, as the extension object will be destroyed during updating.
1600 std::string id = extension->id();
1601
1602 // Update to a new version with increased permissions.
1603 path = base_path.AppendASCII("v2");
1604 PackCRXAndUpdateExtension(id, path, pem_path, DISABLED);
1605
1606 // Now a sync update comes in, telling us to re-enable a *newer* version.
1607 sync_pb::EntitySpecifics specifics;
1608 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1609 ext_specifics->set_id(id);
1610 ext_specifics->set_version("3");
1611 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:361612 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:581613
treib65f103042015-12-03 10:21:361614 SyncChangeList list =
1615 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1616
treib9afc6212015-10-30 18:49:581617 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1618
1619 // Since the version didn't match, the extension should still be disabled.
1620 EXPECT_TRUE(registry()->disabled_extensions().Contains(id));
1621
1622 // After we update to the matching version, the extension should get enabled.
1623 path = base_path.AppendASCII("v3");
1624 PackCRXAndUpdateExtension(id, path, pem_path, ENABLED);
1625}
1626
atuchin2eb18eb2017-03-02 07:22:151627class ExtensionServiceSyncCustomGalleryTest : public ExtensionServiceSyncTest {
1628 public:
1629 void SetUp() override {
1630 ExtensionServiceSyncTest::SetUp();
treib9afc6212015-10-30 18:49:581631
atuchin2eb18eb2017-03-02 07:22:151632 // This is the update URL specified in the permissions test extension.
1633 // Setting it here is necessary to make the extension considered syncable.
1634 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1635 switches::kAppsGalleryUpdateURL,
1636 "http://localhost/autoupdate/updates.xml");
1637 }
1638};
1639
1640TEST_F(ExtensionServiceSyncCustomGalleryTest,
1641 ProcessSyncDataPermissionApproval) {
treib9afc6212015-10-30 18:49:581642 InitializeEmptyExtensionService();
1643 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361644 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141645 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1646 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581647
1648 const base::FilePath base_path =
1649 data_dir().AppendASCII("permissions_increase");
1650 const base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1651 const base::FilePath path_v1 = base_path.AppendASCII("v1");
1652 const base::FilePath path_v2 = base_path.AppendASCII("v2");
1653
1654 base::ScopedTempDir crx_dir;
1655 ASSERT_TRUE(crx_dir.CreateUniqueTempDir());
vabr9142fe22016-09-08 13:19:221656 const base::FilePath crx_path_v1 = crx_dir.GetPath().AppendASCII("temp1.crx");
treib9afc6212015-10-30 18:49:581657 PackCRX(path_v1, pem_path, crx_path_v1);
vabr9142fe22016-09-08 13:19:221658 const base::FilePath crx_path_v2 = crx_dir.GetPath().AppendASCII("temp2.crx");
treib9afc6212015-10-30 18:49:581659 PackCRX(path_v2, pem_path, crx_path_v2);
1660
1661 const std::string v1("1");
1662 const std::string v2("2");
1663
1664 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1665
1666 struct TestCase {
1667 const char* name; // For failure output only.
1668 const std::string& sync_version; // The version coming in from Sync.
1669 // The disable reason(s) coming in from Sync, or -1 for "not set".
1670 int sync_disable_reasons;
1671 // The expected set of disable reasons after processing the Sync update. The
1672 // extension should be enabled iff this is 0.
1673 int expect_disable_reasons;
1674 // Whether the extension's permissions should be auto-granted.
1675 bool expect_permissions_granted;
1676 } test_cases[] = {
Minh X. Nguyen45479012017-08-18 21:35:361677 // Sync tells us to re-enable an older version. No permissions should be
1678 // granted, since we can't be sure if the user actually approved the right
1679 // set of permissions.
1680 {"OldVersion", v1, 0,
1681 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
1682 // Legacy case: Sync tells us to re-enable the extension, but doesn't
1683 // specify disable reasons. No permissions should be granted.
1684 {"Legacy", v2, -1,
1685 extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE, false},
1686 // Sync tells us to re-enable the extension and explicitly removes the
1687 // disable reasons. Now the extension should have its permissions granted.
1688 {"GrantPermissions", v2, 0, extensions::disable_reason::DISABLE_NONE,
1689 true},
treib9afc6212015-10-30 18:49:581690 };
1691
1692 for (const TestCase& test_case : test_cases) {
1693 SCOPED_TRACE(test_case.name);
1694
1695 std::string id;
1696 // Don't keep |extension| around longer than necessary (it'll be destroyed
1697 // during updating).
1698 {
1699 const Extension* extension = InstallCRX(crx_path_v1, INSTALL_NEW);
1700 // The extension should now be installed and enabled.
1701 ASSERT_TRUE(extension);
1702 ASSERT_EQ(v1, extension->VersionString());
1703 id = extension->id();
1704 }
1705 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1706
dchengc963c7142016-04-08 03:55:221707 std::unique_ptr<const PermissionSet> granted_permissions_v1 =
treib9afc6212015-10-30 18:49:581708 prefs->GetGrantedPermissions(id);
1709
1710 // Update to a new version with increased permissions.
1711 UpdateExtension(id, crx_path_v2, DISABLED);
1712
1713 // Now the extension should be disabled due to a permissions increase.
1714 {
1715 const Extension* extension =
1716 registry()->disabled_extensions().GetByID(id);
1717 ASSERT_TRUE(extension);
1718 ASSERT_EQ(v2, extension->VersionString());
1719 }
1720 ASSERT_TRUE(prefs->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:361721 id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE));
treib9afc6212015-10-30 18:49:581722
1723 // No new permissions should have been granted.
dchengc963c7142016-04-08 03:55:221724 std::unique_ptr<const PermissionSet> granted_permissions_v2 =
treib9afc6212015-10-30 18:49:581725 prefs->GetGrantedPermissions(id);
1726 ASSERT_EQ(*granted_permissions_v1, *granted_permissions_v2);
1727
1728 // Now a sync update comes in.
1729 sync_pb::EntitySpecifics specifics;
1730 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1731 ext_specifics->set_id(id);
1732 ext_specifics->set_enabled(true);
1733 ext_specifics->set_version(test_case.sync_version);
1734 if (test_case.sync_disable_reasons != -1)
1735 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1736
treib65f103042015-12-03 10:21:361737 SyncChangeList list =
1738 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1739
treib9afc6212015-10-30 18:49:581740 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1741
1742 // Check expectations.
1743 const bool expect_enabled = !test_case.expect_disable_reasons;
1744 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1745 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
dchengc963c7142016-04-08 03:55:221746 std::unique_ptr<const PermissionSet> granted_permissions =
treib9afc6212015-10-30 18:49:581747 prefs->GetGrantedPermissions(id);
1748 if (test_case.expect_permissions_granted) {
dchengc963c7142016-04-08 03:55:221749 std::unique_ptr<const PermissionSet> active_permissions =
treib9afc6212015-10-30 18:49:581750 prefs->GetActivePermissions(id);
1751 EXPECT_EQ(*granted_permissions, *active_permissions);
1752 } else {
1753 EXPECT_EQ(*granted_permissions, *granted_permissions_v1);
1754 }
1755
1756 // Remove the extension again, so we can install it again for the next case.
1757 UninstallExtension(id, false, expect_enabled ? Extension::ENABLED
1758 : Extension::DISABLED);
1759 }
1760}
1761
treib227b2582015-12-09 09:28:261762// Regression test for crbug.com/558299
1763TEST_F(ExtensionServiceSyncTest, DontSyncThemes) {
1764 InitializeEmptyExtensionService();
1765
1766 // The user has enabled sync.
maxboguefe00952a2016-01-19 19:02:011767 ProfileSyncServiceFactory::GetForProfile(profile())->SetFirstSetupComplete();
treib227b2582015-12-09 09:28:261768 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
1769 extension_sync_service();
1770
1771 service()->Init();
1772 ASSERT_TRUE(service()->is_ready());
1773
1774 syncer::FakeSyncChangeProcessor* processor =
1775 new syncer::FakeSyncChangeProcessor;
1776 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:221777 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
1778 base::WrapUnique(new syncer::SyncErrorFactoryMock));
treib227b2582015-12-09 09:28:261779
1780 processor->changes().clear();
1781
1782 // Sanity check: Installing an extension should result in a sync change.
1783 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1784 EXPECT_EQ(1u, processor->changes().size());
1785
1786 processor->changes().clear();
1787
1788 // Installing a theme should not result in a sync change (themes are handled
1789 // separately by ThemeSyncableService).
1790 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
Evan Stade46d716d2017-06-02 20:50:091791 content::WindowedNotificationObserver theme_change_observer(
1792 chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
1793 content::Source<ThemeService>(
1794 ThemeServiceFactory::GetForProfile(profile())));
1795 theme_change_observer.Wait();
treib227b2582015-12-09 09:28:261796 EXPECT_TRUE(processor->changes().empty());
1797}
1798
brettw9e85ef42016-11-01 21:01:241799#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
treib9afc6212015-10-30 18:49:581800
atuchin2eb18eb2017-03-02 07:22:151801class ExtensionServiceTestSupervised
1802 : public ExtensionServiceSyncCustomGalleryTest,
1803 public SupervisedUserService::Delegate {
treib9afc6212015-10-30 18:49:581804 public:
treibb6af28cd2015-12-01 11:19:461805 ExtensionServiceTestSupervised()
robliao79393ffb2016-09-21 18:45:291806 : field_trial_list_(base::MakeUnique<base::MockEntropyProvider>()) {}
treibb6af28cd2015-12-01 11:19:461807
treib9afc6212015-10-30 18:49:581808 void TearDown() override {
1809 supervised_user_service()->SetDelegate(nullptr);
1810
atuchin2eb18eb2017-03-02 07:22:151811 ExtensionServiceSyncCustomGalleryTest::TearDown();
treib9afc6212015-10-30 18:49:581812 }
1813
1814 protected:
mamire9609642016-06-28 22:17:541815 void InitSupervisedUserInitiatedExtensionInstallFeature(bool enabled) {
mamire9609642016-06-28 22:17:541816 if (enabled) {
asvitkineb1db8262016-11-08 09:48:201817 scoped_feature_list_.InitAndEnableFeature(
1818 supervised_users::kSupervisedUserInitiatedExtensionInstall);
mamire9609642016-06-28 22:17:541819 }
mamire9609642016-06-28 22:17:541820 }
1821
mamirf7715a2a2016-07-04 13:05:081822 bool IsPendingCustodianApproval(const std::string& extension_id) {
1823 auto function = make_scoped_refptr(
1824 new WebstorePrivateIsPendingCustodianApprovalFunction());
1825
1826 std::unique_ptr<base::Value> result(RunFunctionAndReturnSingleResult(
1827 function.get(), "[\"" + extension_id + "\"]", browser_context()));
1828
1829 bool copy_bool_result = false;
1830 EXPECT_TRUE(result->GetAsBoolean(&copy_bool_result));
1831 return copy_bool_result;
1832 }
1833
treib9afc6212015-10-30 18:49:581834 void InitServices(bool profile_is_supervised) {
1835 ExtensionServiceInitParams params = CreateDefaultInitParams();
1836 params.profile_is_supervised = profile_is_supervised;
mamire9609642016-06-28 22:17:541837 // If profile is supervised, don't pass a pref file such that the testing
1838 // profile creates a pref service that uses SupervisedUserPrefStore.
1839 if (profile_is_supervised) {
1840 params.pref_file = base::FilePath();
1841 }
treib9afc6212015-10-30 18:49:581842 InitializeExtensionService(params);
asargente48ab752016-03-12 00:59:201843 StartSyncing(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581844
1845 supervised_user_service()->SetDelegate(this);
1846 supervised_user_service()->Init();
1847 }
1848
mamire9609642016-06-28 22:17:541849 std::string InstallPermissionsTestExtension(bool by_custodian) {
1850 return InstallTestExtension(permissions_increase, dir_path("1"), pem_path(),
1851 by_custodian);
treib9afc6212015-10-30 18:49:581852 }
1853
1854 void UpdatePermissionsTestExtension(const std::string& id,
1855 const std::string& version,
1856 UpdateState expected_state) {
mamire9609642016-06-28 22:17:541857 UpdateTestExtension(dir_path(version), pem_path(), id, version,
1858 expected_state);
1859 }
1860
1861 std::string InstallNoPermissionsTestExtension(bool by_custodian) {
1862 base::FilePath base_path = data_dir().AppendASCII("autoupdate");
1863 base::FilePath pem_path = base_path.AppendASCII("key.pem");
1864 base::FilePath dir_path = base_path.AppendASCII("v1");
1865
1866 return InstallTestExtension(autoupdate, dir_path, pem_path, by_custodian);
1867 }
1868
1869 void UpdateNoPermissionsTestExtension(const std::string& id,
1870 const std::string& version,
1871 UpdateState expected_state) {
1872 base::FilePath base_path = data_dir().AppendASCII("autoupdate");
1873 base::FilePath pem_path = base_path.AppendASCII("key.pem");
1874 base::FilePath dir_path = base_path.AppendASCII("v" + version);
1875
1876 UpdateTestExtension(dir_path, pem_path, id, version, expected_state);
1877 }
1878
1879 std::string InstallTestExtension(const std::string& id,
1880 const base::FilePath& dir_path,
1881 const base::FilePath& pem_path,
1882 bool by_custodian) {
1883 InstallState expected_state = INSTALL_WITHOUT_LOAD;
1884 if (by_custodian) {
1885 extensions::util::SetWasInstalledByCustodian(id, profile(), true);
1886 expected_state = INSTALL_NEW;
1887 }
1888 const Extension* extension =
1889 PackAndInstallCRX(dir_path, pem_path, expected_state);
1890 // The extension must now be installed.
1891 EXPECT_TRUE(extension);
1892 EXPECT_EQ(extension->id(), id);
1893 if (by_custodian) {
1894 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1895 } else {
1896 CheckDisabledForCustodianApproval(id);
1897 }
1898
1899 EXPECT_EQ(*extension->version(), base::Version("1"));
1900
1901 return id;
1902 }
1903
1904 void UpdateTestExtension(const base::FilePath& dir_path,
1905 const base::FilePath& pem_path,
1906 const std::string& id,
1907 const std::string& version,
1908 const UpdateState& expected_state) {
1909 PackCRXAndUpdateExtension(id, dir_path, pem_path, expected_state);
treib9afc6212015-10-30 18:49:581910 const Extension* extension = registry()->GetInstalledExtension(id);
1911 ASSERT_TRUE(extension);
1912 // The version should have been updated.
mamire9609642016-06-28 22:17:541913 EXPECT_EQ(*extension->version(), base::Version(version));
1914 }
1915
1916 // Simulate a custodian approval for enabling the extension coming in
1917 // through Sync by adding the approved version to the map of approved
1918 // extensions. It doesn't simulate a change in the disable reasons.
1919 void SimulateCustodianApprovalChangeViaSync(const std::string& extension_id,
1920 const std::string& version,
1921 SyncChange::SyncChangeType type) {
1922 std::string key = SupervisedUserSettingsService::MakeSplitSettingKey(
1923 supervised_users::kApprovedExtensions, extension_id);
1924 syncer::SyncData sync_data =
1925 SupervisedUserSettingsService::CreateSyncDataForSetting(
jdoerrie122c4da2017-03-06 11:12:041926 key, base::Value(version));
mamire9609642016-06-28 22:17:541927
1928 SyncChangeList list(1, SyncChange(FROM_HERE, type, sync_data));
1929
1930 SupervisedUserSettingsService* supervised_user_settings_service =
1931 SupervisedUserSettingsServiceFactory::GetForProfile(profile());
1932 supervised_user_settings_service->ProcessSyncChanges(FROM_HERE, list);
1933 }
1934
1935 void CheckDisabledForCustodianApproval(const std::string& extension_id) {
1936 EXPECT_TRUE(registry()->disabled_extensions().Contains(extension_id));
1937 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile());
1938 EXPECT_TRUE(extension_prefs->HasDisableReason(
1939 extension_id,
Minh X. Nguyen45479012017-08-18 21:35:361940 extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
treib9afc6212015-10-30 18:49:581941 }
1942
1943 SupervisedUserService* supervised_user_service() {
1944 return SupervisedUserServiceFactory::GetForProfile(profile());
1945 }
1946
mamire9609642016-06-28 22:17:541947 static std::string RequestId(const std::string& extension_id,
1948 const std::string& version) {
1949 return SupervisedUserService::GetExtensionRequestId(
treib9afc6212015-10-30 18:49:581950 extension_id, base::Version(version));
1951 }
1952
1953 private:
1954 // This prevents the legacy supervised user init code from running.
1955 bool SetActive(bool active) override { return true; }
1956
1957 base::FilePath base_path() const {
1958 return data_dir().AppendASCII("permissions_increase");
1959 }
1960 base::FilePath dir_path(const std::string& version) const {
1961 return base_path().AppendASCII("v" + version);
1962 }
1963 base::FilePath pem_path() const {
1964 return base_path().AppendASCII("permissions.pem");
1965 }
treibb6af28cd2015-12-01 11:19:461966
1967 base::FieldTrialList field_trial_list_;
asvitkineb1db8262016-11-08 09:48:201968 base::test::ScopedFeatureList scoped_feature_list_;
treib9afc6212015-10-30 18:49:581969};
1970
1971class MockPermissionRequestCreator : public PermissionRequestCreator {
1972 public:
1973 MockPermissionRequestCreator() {}
1974 ~MockPermissionRequestCreator() override {}
1975
1976 bool IsEnabled() const override { return true; }
1977
1978 void CreateURLAccessRequest(const GURL& url_requested,
1979 const SuccessCallback& callback) override {
1980 FAIL();
1981 }
1982
mamire9609642016-06-28 22:17:541983 MOCK_METHOD2(CreateExtensionInstallRequest,
1984 void(const std::string& id,
1985 const SupervisedUserService::SuccessCallback& callback));
1986
treib9afc6212015-10-30 18:49:581987 MOCK_METHOD2(CreateExtensionUpdateRequest,
1988 void(const std::string& id,
1989 const SupervisedUserService::SuccessCallback& callback));
1990
1991 private:
1992 DISALLOW_COPY_AND_ASSIGN(MockPermissionRequestCreator);
1993};
1994
1995TEST_F(ExtensionServiceTestSupervised, InstallOnlyAllowedByCustodian) {
1996 InitServices(true /* profile_is_supervised */);
mamire9609642016-06-28 22:17:541997 InitSupervisedUserInitiatedExtensionInstallFeature(false);
treib9afc6212015-10-30 18:49:581998
mamir192d7882016-06-22 17:10:161999 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
2000
treib9afc6212015-10-30 18:49:582001 base::FilePath path1 = data_dir().AppendASCII("good.crx");
2002 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
2003 const Extension* extensions[] = {
2004 InstallCRX(path1, INSTALL_FAILED),
mamir192d7882016-06-22 17:10:162005 InstallCRX(path2, INSTALL_NEW)
treib9afc6212015-10-30 18:49:582006 };
2007
2008 // Only the extension with the "installed by custodian" flag should have been
2009 // installed and enabled.
2010 EXPECT_FALSE(extensions[0]);
2011 ASSERT_TRUE(extensions[1]);
2012 EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id()));
mamirf7715a2a2016-07-04 13:05:082013 EXPECT_FALSE(IsPendingCustodianApproval(extensions[1]->id()));
treib9afc6212015-10-30 18:49:582014}
2015
mamir192d7882016-06-22 17:10:162016TEST_F(ExtensionServiceTestSupervised,
2017 DelegatedAndPreinstalledExtensionIsSUFirst) {
2018 InitServices(false /* profile_is_supervised */);
mamire9609642016-06-28 22:17:542019 InitSupervisedUserInitiatedExtensionInstallFeature(false);
mamir192d7882016-06-22 17:10:162020
2021 // Install an extension.
2022 base::FilePath path = data_dir().AppendASCII("good.crx");
2023 const Extension* extension = InstallCRX(path, INSTALL_NEW);
2024 std::string id = extension->id();
2025 const std::string version("1.0.0.0");
2026 // It should be enabled.
2027 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2028
2029 // Now make the profile supervised.
2030 profile()->AsTestingProfile()->SetSupervisedUserId(
2031 supervised_users::kChildAccountSUID);
2032
2033 // It should not be enabled now (it is not loaded at all actually).
2034 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2035
2036 // Simulate data sync with the "was_installed_by_custodian" flag set to 1.
2037 sync_pb::EntitySpecifics specifics;
2038 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2039 ext_specifics->set_id(id);
2040 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:362041 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
mamir192d7882016-06-22 17:10:162042 ext_specifics->set_installed_by_custodian(true);
2043 ext_specifics->set_version(version);
2044
2045 SyncChangeList list =
2046 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2047
2048 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
2049
2050 // The extension should be enabled again.
2051 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2052 EXPECT_TRUE(extensions::util::WasInstalledByCustodian(id, profile()));
2053}
2054
2055TEST_F(ExtensionServiceTestSupervised,
2056 DelegatedAndPreinstalledExtensionSyncFirst) {
2057 InitServices(false /* profile_is_supervised */);
mamire9609642016-06-28 22:17:542058 InitSupervisedUserInitiatedExtensionInstallFeature(false);
mamir192d7882016-06-22 17:10:162059
2060 // Install an extension.
2061 base::FilePath path = data_dir().AppendASCII("good.crx");
2062 const Extension* extension = InstallCRX(path, INSTALL_NEW);
2063 std::string id = extension->id();
2064 const std::string version("1.0.0.0");
2065
2066 // It should be enabled.
2067 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2068
2069 // Simulate data sync with the "was_installed_by_custodian" flag set to 1.
2070 sync_pb::EntitySpecifics specifics;
2071 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2072 ext_specifics->set_id(id);
2073 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:362074 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
mamir192d7882016-06-22 17:10:162075 ext_specifics->set_installed_by_custodian(true);
2076 ext_specifics->set_version(version);
2077
2078 SyncChangeList list =
2079 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2080
2081 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
mamir192d7882016-06-22 17:10:162082 // The extension should be enabled.
2083 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2084 EXPECT_TRUE(extensions::util::WasInstalledByCustodian(id, profile()));
2085}
2086
mamire9609642016-06-28 22:17:542087TEST_F(ExtensionServiceTestSupervised,
2088 InstallAllowedByCustodianAndSupervisedUser) {
2089 InitServices(true /* profile_is_supervised */);
2090 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2091
2092 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
2093
2094 base::FilePath path1 = data_dir().AppendASCII("good.crx");
2095 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
2096 const Extension* extensions[] = {
2097 InstallCRX(path1, INSTALL_WITHOUT_LOAD),
2098 InstallCRX(path2, INSTALL_NEW)
2099 };
2100
2101 // Only the extension with the "installed by custodian" flag should have been
2102 // installed and enabled.
2103 // The extension missing the "installed by custodian" flag is a
2104 // supervised user initiated install and hence not enabled.
2105 ASSERT_TRUE(extensions[0]);
2106 ASSERT_TRUE(extensions[1]);
2107 EXPECT_TRUE(registry()->disabled_extensions().Contains(extensions[0]->id()));
mamirf7715a2a2016-07-04 13:05:082108 EXPECT_TRUE(IsPendingCustodianApproval(extensions[0]->id()));
mamire9609642016-06-28 22:17:542109 EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id()));
mamirf7715a2a2016-07-04 13:05:082110 EXPECT_FALSE(IsPendingCustodianApproval(extensions[1]->id()));
mamire9609642016-06-28 22:17:542111}
2112
2113TEST_F(ExtensionServiceTestSupervised,
2114 PreinstalledExtensionWithSUInitiatedInstalls) {
2115 InitServices(false /* profile_is_supervised */);
2116 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2117
2118 // Install an extension.
2119 base::FilePath path = data_dir().AppendASCII("good.crx");
2120 const Extension* extension = InstallCRX(path, INSTALL_NEW);
2121 std::string id = extension->id();
2122 // Make sure it's enabled.
2123 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2124
2125 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2126 supervised_user_service()->AddPermissionRequestCreator(
2127 base::WrapUnique(creator));
2128 const std::string version("1.0.0.0");
2129
2130 EXPECT_CALL(*creator, CreateExtensionInstallRequest(
2131 RequestId(good_crx, version), testing::_));
2132
2133 // Now make the profile supervised.
2134 profile()->AsTestingProfile()->SetSupervisedUserId(
2135 supervised_users::kChildAccountSUID);
2136
2137 Mock::VerifyAndClearExpectations(creator);
2138
2139 // The extension should not be enabled anymore.
2140 CheckDisabledForCustodianApproval(id);
mamirf7715a2a2016-07-04 13:05:082141 EXPECT_TRUE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542142}
2143
2144TEST_F(ExtensionServiceTestSupervised,
2145 PreinstalledExtensionWithoutSUInitiatedInstalls) {
2146 InitServices(false /* profile_is_supervised */);
2147 InitSupervisedUserInitiatedExtensionInstallFeature(false);
2148
2149 // Install an extension.
2150 base::FilePath path = data_dir().AppendASCII("good.crx");
2151 const Extension* extension = InstallCRX(path, INSTALL_NEW);
2152 std::string id = extension->id();
2153
2154 // Make sure it's enabled.
2155 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2156
2157 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2158 supervised_user_service()->AddPermissionRequestCreator(
2159 base::WrapUnique(creator));
2160 const std::string version("1.0.0.0");
2161
2162 // No request should be sent because supervised user initiated installs
2163 // are disabled.
2164 EXPECT_CALL(*creator, CreateExtensionInstallRequest(testing::_, testing::_))
2165 .Times(0);
2166
2167 // Now make the profile supervised.
2168 profile()->AsTestingProfile()->SetSupervisedUserId(
2169 supervised_users::kChildAccountSUID);
2170
Karan Bhatia2a117232017-08-23 00:24:562171 // The extension should now be disabled.
2172 EXPECT_TRUE(registry()->disabled_extensions().Contains(id));
2173 EXPECT_EQ(extensions::disable_reason::DISABLE_BLOCKED_BY_POLICY,
2174 ExtensionPrefs::Get(profile())->GetDisableReasons(id));
mamire9609642016-06-28 22:17:542175}
2176
2177TEST_F(ExtensionServiceTestSupervised, ExtensionApprovalBeforeInstallation) {
2178 // This tests the case when the sync entity flagging the extension as approved
2179 // arrives before the extension itself is installed.
2180 InitServices(true /* profile_is_supervised */);
2181 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2182
2183 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2184 supervised_user_service()->AddPermissionRequestCreator(
2185 base::WrapUnique(creator));
2186
2187 std::string id = good_crx;
2188 std::string version("1.0.0.0");
2189
2190 SimulateCustodianApprovalChangeViaSync(id, version, SyncChange::ACTION_ADD);
2191
2192 // Now install an extension.
2193 base::FilePath path = data_dir().AppendASCII("good.crx");
2194 InstallCRX(path, INSTALL_NEW);
2195
2196 // No approval request should be sent.
2197 EXPECT_CALL(*creator, CreateExtensionInstallRequest(testing::_, testing::_))
2198 .Times(0);
2199
2200 // Make sure it's enabled.
2201 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082202 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542203}
2204
treib9afc6212015-10-30 18:49:582205TEST_F(ExtensionServiceTestSupervised, UpdateWithoutPermissionIncrease) {
2206 InitServices(true /* profile_is_supervised */);
2207
treib9afc6212015-10-30 18:49:582208 // Save the id, as the extension object will be destroyed during updating.
mamire9609642016-06-28 22:17:542209 std::string id = InstallNoPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582210
2211 // Update to a new version.
mamire9609642016-06-28 22:17:542212 std::string version2("2");
2213 UpdateNoPermissionsTestExtension(id, version2, ENABLED);
treib9afc6212015-10-30 18:49:582214
2215 // The extension should still be there and enabled.
mamire9609642016-06-28 22:17:542216 const Extension* extension = registry()->enabled_extensions().GetByID(id);
treib9afc6212015-10-30 18:49:582217 ASSERT_TRUE(extension);
2218 // The version should have changed.
mamire9609642016-06-28 22:17:542219 EXPECT_EQ(*extension->version(), base::Version(version2));
mamirf7715a2a2016-07-04 13:05:082220 EXPECT_FALSE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582221}
2222
treib9afc6212015-10-30 18:49:582223TEST_F(ExtensionServiceTestSupervised,
2224 UpdateWithPermissionIncreaseApprovalOldVersion) {
treib9afc6212015-10-30 18:49:582225 InitServices(true /* profile_is_supervised */);
2226
2227 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2228 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222229 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582230
2231 const std::string version1("1");
2232 const std::string version2("2");
2233
mamire9609642016-06-28 22:17:542234 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582235
2236 // Update to a new version with increased permissions.
2237 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542238 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582239 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542240 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082241 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582242
2243 // Simulate a custodian approval for re-enabling the extension coming in
2244 // through Sync, but set the old version. This can happen when there already
2245 // was a pending request for an earlier version of the extension.
2246 sync_pb::EntitySpecifics specifics;
2247 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2248 ext_specifics->set_id(id);
2249 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:362250 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:582251 ext_specifics->set_installed_by_custodian(true);
2252 ext_specifics->set_version(version1);
2253
2254 // Attempting to re-enable an old version should result in a permission
2255 // request for the current version.
2256 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542257 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582258
treib65f103042015-12-03 10:21:362259 SyncChangeList list =
2260 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2261
2262 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582263 // The re-enable should be ignored, since the version doesn't match.
2264 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2265 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
2266 id, base::Version(version1)));
2267 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
2268 id, base::Version(version2)));
mamire9609642016-06-28 22:17:542269 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082270 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582271}
2272
2273TEST_F(ExtensionServiceTestSupervised,
2274 UpdateWithPermissionIncreaseApprovalMatchingVersion) {
treib9afc6212015-10-30 18:49:582275 InitServices(true /* profile_is_supervised */);
2276
2277 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2278 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222279 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582280
mamire9609642016-06-28 22:17:542281 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582282
2283 // Update to a new version with increased permissions.
2284 const std::string version2("2");
2285 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542286 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582287 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542288 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082289 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582290
2291 // Simulate a custodian approval for re-enabling the extension coming in
2292 // through Sync.
2293 sync_pb::EntitySpecifics specifics;
2294 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2295 ext_specifics->set_id(id);
2296 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:362297 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:582298 ext_specifics->set_installed_by_custodian(true);
2299 ext_specifics->set_version(version2);
2300
treib65f103042015-12-03 10:21:362301 SyncChangeList list =
2302 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2303
2304 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582305 // The extension should have gotten re-enabled.
2306 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082307 EXPECT_FALSE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582308}
2309
2310TEST_F(ExtensionServiceTestSupervised,
2311 UpdateWithPermissionIncreaseApprovalNewVersion) {
treib9afc6212015-10-30 18:49:582312 InitServices(true /* profile_is_supervised */);
2313
2314 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2315 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222316 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582317
mamire9609642016-06-28 22:17:542318 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582319
2320 // Update to a new version with increased permissions.
2321 const std::string version2("2");
2322 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542323 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582324 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542325 Mock::VerifyAndClearExpectations(creator);
treib9afc6212015-10-30 18:49:582326
2327 // Simulate a custodian approval for re-enabling the extension coming in
2328 // through Sync. Set a newer version than we have installed.
2329 const std::string version3("3");
2330 sync_pb::EntitySpecifics specifics;
2331 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2332 ext_specifics->set_id(id);
2333 ext_specifics->set_enabled(true);
Minh X. Nguyen45479012017-08-18 21:35:362334 ext_specifics->set_disable_reasons(extensions::disable_reason::DISABLE_NONE);
treib9afc6212015-10-30 18:49:582335 ext_specifics->set_installed_by_custodian(true);
2336 ext_specifics->set_version(version3);
2337
2338 // This should *not* result in a new permission request.
2339 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542340 RequestId(id, version3), testing::_))
treib9afc6212015-10-30 18:49:582341 .Times(0);
2342
treib65f103042015-12-03 10:21:362343 SyncChangeList list =
2344 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2345
2346 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582347 // The re-enable should be delayed until the extension is updated to the
2348 // matching version.
2349 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2350 EXPECT_TRUE(extension_sync_service()->HasPendingReenable(
2351 id, base::Version(version3)));
2352
2353 // Update to the matching version. Now the extension should get enabled.
2354 UpdatePermissionsTestExtension(id, version3, ENABLED);
2355}
2356
mamire9609642016-06-28 22:17:542357TEST_F(ExtensionServiceTestSupervised, SupervisedUserInitiatedInstalls) {
mamire9609642016-06-28 22:17:542358 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2359
2360 InitServices(true /* profile_is_supervised */);
2361
2362 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2363 supervised_user_service()->AddPermissionRequestCreator(
2364 base::WrapUnique(creator));
2365
2366 base::FilePath path = data_dir().AppendASCII("good.crx");
2367 std::string version("1.0.0.0");
2368
2369 EXPECT_CALL(*creator, CreateExtensionInstallRequest(
2370 RequestId(good_crx, version), testing::_));
2371
2372 // Should be installed but disabled, a request for approval should be sent.
2373 const Extension* extension = InstallCRX(path, INSTALL_WITHOUT_LOAD);
2374 ASSERT_TRUE(extension);
2375 ASSERT_EQ(extension->id(), good_crx);
2376 EXPECT_TRUE(registry()->disabled_extensions().Contains(good_crx));
2377 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082378 EXPECT_TRUE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542379
2380 SimulateCustodianApprovalChangeViaSync(good_crx, version,
2381 SyncChange::ACTION_ADD);
2382
2383 // The extension should be enabled now.
2384 EXPECT_TRUE(registry()->enabled_extensions().Contains(good_crx));
mamirf7715a2a2016-07-04 13:05:082385 EXPECT_FALSE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542386
2387 // Simulate approval removal coming via Sync.
2388 SimulateCustodianApprovalChangeViaSync(good_crx, version,
2389 SyncChange::ACTION_DELETE);
2390
2391 // The extension should be disabled now.
2392 EXPECT_TRUE(registry()->disabled_extensions().Contains(good_crx));
mamirf7715a2a2016-07-04 13:05:082393 EXPECT_TRUE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542394}
2395
2396TEST_F(ExtensionServiceTestSupervised,
2397 UpdateSUInitiatedInstallWithoutPermissionIncrease) {
mamire9609642016-06-28 22:17:542398 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2399
2400 InitServices(true /* profile_is_supervised */);
2401
2402 std::string id = InstallNoPermissionsTestExtension(false /* by_custodian */);
2403 std::string version1("1");
2404
2405 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2406
2407 // The extension should be enabled now.
2408 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2409
2410 std::string version2("2");
2411
2412 // Update to a new version.
2413 UpdateNoPermissionsTestExtension(id, version2, ENABLED);
2414
2415 // The extension should still be there and enabled.
2416 const Extension* extension = registry()->enabled_extensions().GetByID(id);
2417 ASSERT_TRUE(extension);
2418 // The version should have increased.
2419 EXPECT_EQ(1, extension->version()->CompareTo(base::Version(version1)));
2420
2421 // Check that the approved version has been updated in the prefs as well.
2422 // Prefs are updated via Sync. If the prefs are updated, then the new
2423 // approved version has been pushed to Sync as well.
2424 std::string approved_version;
2425 PrefService* pref_service = profile()->GetPrefs();
2426 const base::DictionaryValue* approved_extensions =
2427 pref_service->GetDictionary(prefs::kSupervisedUserApprovedExtensions);
2428 approved_extensions->GetStringWithoutPathExpansion(id, &approved_version);
2429
2430 EXPECT_EQ(base::Version(approved_version), *extension->version());
mamirf7715a2a2016-07-04 13:05:082431 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542432}
2433
2434TEST_F(ExtensionServiceTestSupervised,
2435 UpdateSUInitiatedInstallWithPermissionIncrease) {
mamire9609642016-06-28 22:17:542436 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2437
2438 InitServices(true /* profile_is_supervised */);
2439
2440 std::string id = InstallPermissionsTestExtension(false /* by_custodian */);
2441 std::string version1("1");
2442
2443 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2444
2445 // The extension should be enabled now.
2446 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2447
2448 std::string version3("3");
2449
2450 UpdatePermissionsTestExtension(id, version3, DISABLED);
2451
2452 // The extension should be disabled.
2453 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2454 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:362455 id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE));
mamire9609642016-06-28 22:17:542456
2457 std::string version2("2");
2458 // Approve an older version
2459 SimulateCustodianApprovalChangeViaSync(id, version2,
2460 SyncChange::ACTION_UPDATE);
2461
2462 // The extension should remain disabled.
2463 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2464 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:362465 id, extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE));
mamire9609642016-06-28 22:17:542466 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
Minh X. Nguyen45479012017-08-18 21:35:362467 id, extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
mamire9609642016-06-28 22:17:542468
mamirf7715a2a2016-07-04 13:05:082469 EXPECT_TRUE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542470 // Approve the latest version
2471 SimulateCustodianApprovalChangeViaSync(id, version3,
2472 SyncChange::ACTION_UPDATE);
2473
2474 // The extension should be enabled again.
2475 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082476 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542477}
2478
2479TEST_F(ExtensionServiceTestSupervised,
2480 UpdateSUInitiatedInstallWithPermissionIncreaseApprovalArrivesFirst) {
mamire9609642016-06-28 22:17:542481 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2482
2483 InitServices(true /* profile_is_supervised */);
2484
2485 std::string id = InstallPermissionsTestExtension(false /* by_custodian */);
2486
2487 std::string version1("1");
2488 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2489
2490 // The extension should be enabled now.
2491 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2492
2493 std::string version2("2");
2494 // Approve a newer version
2495 SimulateCustodianApprovalChangeViaSync(id, version2,
2496 SyncChange::ACTION_UPDATE);
2497
2498 // The extension should be disabled.
2499 CheckDisabledForCustodianApproval(id);
2500
2501 // Now update the extension to the same version that was approved.
2502 UpdatePermissionsTestExtension(id, version2, ENABLED);
2503 // The extension should be enabled again.
2504 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082505 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542506}
2507
treib9afc6212015-10-30 18:49:582508TEST_F(ExtensionServiceSyncTest, SyncUninstallByCustodianSkipsPolicy) {
2509 InitializeEmptyExtensionService();
2510 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:362511 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:142512 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
2513 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:582514
mamir192d7882016-06-22 17:10:162515 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
treib9afc6212015-10-30 18:49:582516 // Install two extensions.
2517 base::FilePath path1 = data_dir().AppendASCII("good.crx");
2518 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
2519 const Extension* extensions[] = {
2520 InstallCRX(path1, INSTALL_NEW),
mamir192d7882016-06-22 17:10:162521 InstallCRX(path2, INSTALL_NEW)
treib9afc6212015-10-30 18:49:582522 };
2523
2524 // Add a policy provider that will disallow any changes.
2525 extensions::TestManagementPolicyProvider provider(
2526 extensions::TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS);
2527 ExtensionSystem::Get(
2528 browser_context())->management_policy()->RegisterProvider(&provider);
2529
2530 // Create a sync deletion for each extension.
treib65f103042015-12-03 10:21:362531 SyncChangeList list;
treib9afc6212015-10-30 18:49:582532 for (size_t i = 0; i < arraysize(extensions); i++) {
2533 const std::string& id = extensions[i]->id();
2534 sync_pb::EntitySpecifics specifics;
2535 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2536 ext_specifics->set_id(id);
2537 ext_specifics->set_version("1.0");
2538 ext_specifics->set_installed_by_custodian(
mamir192d7882016-06-22 17:10:162539 extensions::util::WasInstalledByCustodian(id, profile()));
2540
treib9afc6212015-10-30 18:49:582541 syncer::SyncData sync_data =
2542 syncer::SyncData::CreateLocalData(id, "Name", specifics);
treib65f103042015-12-03 10:21:362543 list.push_back(SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, sync_data));
treib9afc6212015-10-30 18:49:582544 }
2545
2546 // Save the extension ids, as uninstalling destroys the Extension instance.
2547 std::string extension_ids[] = {
2548 extensions[0]->id(),
2549 extensions[1]->id()
2550 };
2551
2552 // Now apply the uninstallations.
treib65f103042015-12-03 10:21:362553 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582554
2555 // Uninstalling the extension without installed_by_custodian should have been
2556 // blocked by policy, so it should still be there.
2557 EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_ids[0]));
2558
2559 // But installed_by_custodian should result in bypassing the policy check.
2560 EXPECT_FALSE(
2561 registry()->GenerateInstalledExtensionsSet()->Contains(extension_ids[1]));
2562}
2563
rdevlin.cronin738501d2015-11-05 21:51:362564TEST_F(ExtensionServiceSyncTest, SyncExtensionHasAllhostsWithheld) {
2565 InitializeEmptyExtensionService();
asargente48ab752016-03-12 00:59:202566 StartSyncing(syncer::EXTENSIONS);
rdevlin.cronin738501d2015-11-05 21:51:362567
2568 // Create an extension that needs all-hosts.
2569 const std::string kName("extension");
2570 scoped_refptr<const Extension> extension =
Devlin Cronin3f5b18f2017-08-22 21:54:052571 extensions::ExtensionBuilder(kName)
limasdf3d102542015-12-09 03:58:452572 .SetLocation(Manifest::INTERNAL)
Devlin Cronin3f5b18f2017-08-22 21:54:052573 .AddPermission("*://*/*")
limasdf3d102542015-12-09 03:58:452574 .Build();
rdevlin.cronin738501d2015-11-05 21:51:362575
2576 // Install and enable it.
2577 service()->AddExtension(extension.get());
2578 service()->GrantPermissionsAndEnableExtension(extension.get());
2579 const std::string id = extension->id();
2580 EXPECT_TRUE(registry()->enabled_extensions().GetByID(id));
2581
2582 // Simulate a sync node coming in where the extension had all-hosts withheld.
2583 // This means that it should have all-hosts withheld on this machine, too.
rdevlin.cronin738501d2015-11-05 21:51:362584 sync_pb::EntitySpecifics specifics;
2585 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2586 ext_specifics->set_id(id);
2587 ext_specifics->set_name(kName);
2588 ext_specifics->set_version("1.0");
2589 ext_specifics->set_all_urls_enabled(false);
2590 ext_specifics->set_enabled(true);
rdevlin.cronin738501d2015-11-05 21:51:362591
treib65f103042015-12-03 10:21:362592 SyncChangeList list =
2593 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2594
2595 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
rdevlin.cronin738501d2015-11-05 21:51:362596
rdevlin.cronind01837b2016-08-17 01:37:182597 const Extension* enabled_extension =
2598 registry()->enabled_extensions().GetByID(id);
2599 ASSERT_TRUE(enabled_extension);
2600 ScriptingPermissionsModifier modifier(profile(), enabled_extension);
2601 EXPECT_FALSE(modifier.IsAllowedOnAllUrls());
2602 EXPECT_TRUE(modifier.HasSetAllowedOnAllUrls());
rdevlin.cronin738501d2015-11-05 21:51:362603}
2604
brettw9e85ef42016-11-01 21:01:242605#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
asargente48ab752016-03-12 00:59:202606
2607// Tests sync behavior in the case of an item that starts out as an app and
2608// gets updated to become an extension.
2609TEST_F(ExtensionServiceSyncTest, AppToExtension) {
2610 InitializeEmptyExtensionService();
2611 service()->Init();
2612 ASSERT_TRUE(service()->is_ready());
2613
2614 // Install v1, which is an app.
2615 const Extension* v1 =
2616 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v1.crx"),
2617 INSTALL_NEW);
2618 EXPECT_TRUE(v1->is_app());
2619 EXPECT_FALSE(v1->is_extension());
2620 std::string id = v1->id();
2621
2622 StatefulChangeProcessor extensions_processor(syncer::ModelType::EXTENSIONS);
2623 StatefulChangeProcessor apps_processor(syncer::ModelType::APPS);
2624 extension_sync_service()->MergeDataAndStartSyncing(
2625 syncer::EXTENSIONS, syncer::SyncDataList(),
2626 extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222627 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202628 extension_sync_service()->MergeDataAndStartSyncing(
2629 syncer::APPS, syncer::SyncDataList(), apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222630 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202631
2632 // Check the app/extension change processors to be sure the right data was
2633 // added.
2634 EXPECT_TRUE(extensions_processor.changes().empty());
2635 EXPECT_TRUE(extensions_processor.data().empty());
2636 EXPECT_EQ(1u, apps_processor.data().size());
2637 ASSERT_EQ(1u, apps_processor.changes().size());
2638 const SyncChange& app_change = apps_processor.changes()[0];
2639 EXPECT_EQ(SyncChange::ACTION_ADD, app_change.change_type());
dchengc963c7142016-04-08 03:55:222640 std::unique_ptr<ExtensionSyncData> app_data =
asargente48ab752016-03-12 00:59:202641 ExtensionSyncData::CreateFromSyncData(app_change.sync_data());
2642 EXPECT_TRUE(app_data->is_app());
2643 EXPECT_EQ(id, app_data->id());
2644 EXPECT_EQ(*v1->version(), app_data->version());
2645
2646 // Update the app to v2, which is an extension.
2647 const Extension* v2 =
2648 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v2.crx"),
2649 INSTALL_UPDATED);
2650 EXPECT_FALSE(v2->is_app());
2651 EXPECT_TRUE(v2->is_extension());
2652 EXPECT_EQ(id, v2->id());
2653
2654 // Make sure we saw an extension item added.
2655 ASSERT_EQ(1u, extensions_processor.changes().size());
2656 const SyncChange& extension_change = extensions_processor.changes()[0];
2657 EXPECT_EQ(SyncChange::ACTION_ADD, extension_change.change_type());
dchengc963c7142016-04-08 03:55:222658 std::unique_ptr<ExtensionSyncData> extension_data =
asargente48ab752016-03-12 00:59:202659 ExtensionSyncData::CreateFromSyncData(extension_change.sync_data());
2660 EXPECT_FALSE(extension_data->is_app());
2661 EXPECT_EQ(id, extension_data->id());
2662 EXPECT_EQ(*v2->version(), extension_data->version());
2663
2664 // Get the current data from the change processors to use as the input to
2665 // the following call to MergeDataAndStartSyncing. This simulates what should
2666 // happen with sync.
2667 syncer::SyncDataList extensions_data =
2668 extensions_processor.GetAllSyncData(syncer::EXTENSIONS);
2669 syncer::SyncDataList apps_data = apps_processor.GetAllSyncData(syncer::APPS);
2670
2671 // Stop syncing, then start again.
2672 extension_sync_service()->StopSyncing(syncer::EXTENSIONS);
2673 extension_sync_service()->StopSyncing(syncer::APPS);
2674 extension_sync_service()->MergeDataAndStartSyncing(
2675 syncer::EXTENSIONS, extensions_data, extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222676 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202677 extension_sync_service()->MergeDataAndStartSyncing(
2678 syncer::APPS, apps_data, apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222679 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202680
2681 // Make sure we saw an app item deleted.
2682 bool found_delete = false;
2683 for (const auto& change : apps_processor.changes()) {
2684 if (change.change_type() == SyncChange::ACTION_DELETE) {
dchengc963c7142016-04-08 03:55:222685 std::unique_ptr<ExtensionSyncData> data =
asargente48ab752016-03-12 00:59:202686 ExtensionSyncData::CreateFromSyncChange(change);
2687 if (data->id() == id) {
2688 found_delete = true;
2689 break;
2690 }
2691 }
2692 }
2693 EXPECT_TRUE(found_delete);
2694
2695 // Make sure there is one extension, and there are no more apps.
2696 EXPECT_EQ(1u, extensions_processor.data().size());
2697 EXPECT_TRUE(apps_processor.data().empty());
2698}
proberge901ecab2017-08-31 19:24:282699
2700class BlacklistedExtensionSyncServiceTest : public ExtensionServiceSyncTest {
2701 public:
2702 BlacklistedExtensionSyncServiceTest() {}
2703
2704 void SetUp() override {
2705 ExtensionServiceSyncTest::SetUp();
2706
2707 InitializeEmptyExtensionService();
2708
2709 // Enable sync.
2710 browser_sync::ProfileSyncService* sync_service =
2711 ProfileSyncServiceFactory::GetForProfile(profile());
2712 sync_service->SetFirstSetupComplete();
2713
2714 test_blacklist_.Attach(service()->blacklist_);
2715 service()->Init();
2716
2717 // Load up a simple extension.
2718 extensions::ChromeTestExtensionLoader extension_loader(profile());
2719 extension_loader.set_pack_extension(true);
2720 extension_ = extension_loader.LoadExtension(
2721 data_dir().AppendASCII("simple_with_file"));
2722 ASSERT_TRUE(extension_);
2723 extension_id_ = extension_->id();
2724 ASSERT_TRUE(registry()->enabled_extensions().GetByID(extension_id_));
2725
2726 {
2727 auto processor = base::MakeUnique<syncer::FakeSyncChangeProcessor>();
2728 processor_raw_ = processor.get();
2729 extension_sync_service()->MergeDataAndStartSyncing(
2730 syncer::EXTENSIONS, syncer::SyncDataList(), std::move(processor),
2731 base::MakeUnique<syncer::SyncErrorFactoryMock>());
2732 }
2733 processor_raw_->changes().clear();
2734 }
2735
2736 void ForceBlacklistUpdate() {
2737 service()->OnBlacklistUpdated();
2738 content::RunAllBlockingPoolTasksUntilIdle();
2739 }
2740
2741 syncer::FakeSyncChangeProcessor* processor() { return processor_raw_; }
2742
2743 const Extension* extension() { return extension_.get(); }
2744
2745 std::string& extension_id() { return extension_id_; }
2746
2747 extensions::TestBlacklist& test_blacklist() { return test_blacklist_; }
2748
2749 private:
2750 syncer::FakeSyncChangeProcessor* processor_raw_;
2751 scoped_refptr<const Extension> extension_;
2752 std::string extension_id_;
2753 extensions::TestBlacklist test_blacklist_;
2754
2755 DISALLOW_COPY_AND_ASSIGN(BlacklistedExtensionSyncServiceTest);
2756};
2757
2758// Test that sync cannot enable blacklisted extensions.
2759TEST_F(BlacklistedExtensionSyncServiceTest, SyncBlacklistedExtension) {
2760 std::string& extension_id = this->extension_id();
2761
2762 // Blacklist the extension.
2763 test_blacklist().SetBlacklistState(extension_id,
2764 extensions::BLACKLISTED_MALWARE, true);
2765 ForceBlacklistUpdate();
2766
2767 // Try enabling the extension via sync.
2768 EnableExtensionFromSync(*extension());
2769
2770 // The extension should not be enabled.
2771 EXPECT_FALSE(registry()->enabled_extensions().GetByID(extension_id));
2772 EXPECT_TRUE(processor()->changes().empty());
2773}
2774
2775// Test that some greylisted extensions can be enabled through sync.
2776TEST_F(BlacklistedExtensionSyncServiceTest, SyncAllowedGreylistedExtension) {
2777 std::string& extension_id = this->extension_id();
2778
2779 // Greylist the extension.
2780 test_blacklist().SetBlacklistState(
2781 extension_id, extensions::BLACKLISTED_POTENTIALLY_UNWANTED, true);
2782 ForceBlacklistUpdate();
2783
2784 EXPECT_FALSE(registry()->enabled_extensions().GetByID(extension_id));
2785 {
2786 ASSERT_EQ(1u, processor()->changes().size());
2787 const SyncChange& change = processor()->changes()[0];
2788 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
2789 std::unique_ptr<ExtensionSyncData> data =
2790 ExtensionSyncData::CreateFromSyncData(change.sync_data());
2791 EXPECT_EQ(extension_id, data->id());
2792 EXPECT_EQ(extensions::disable_reason::DISABLE_GREYLIST,
2793 data->disable_reasons());
2794 EXPECT_FALSE(data->enabled());
2795 }
2796 processor()->changes().clear();
2797
2798 // Manually re-enabling the extension should work.
2799 service()->EnableExtension(extension_id);
2800 EXPECT_TRUE(registry()->enabled_extensions().GetByID(extension_id));
2801 {
2802 ASSERT_EQ(1u, processor()->changes().size());
2803 const SyncChange& change = processor()->changes()[0];
2804 EXPECT_EQ(SyncChange::ACTION_UPDATE, change.change_type());
2805 std::unique_ptr<ExtensionSyncData> data =
2806 ExtensionSyncData::CreateFromSyncData(change.sync_data());
2807 EXPECT_EQ(extension_id, data->id());
2808 EXPECT_EQ(0, data->disable_reasons());
2809 EXPECT_TRUE(data->enabled());
2810 }
2811 processor()->changes().clear();
2812}