blob: 1f4874c2d24ec780d6c300e21dd308701d5cc691 [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"
mamire9609642016-06-28 22:17:5414#include "base/feature_list.h"
treib9afc6212015-10-30 18:49:5815#include "base/files/file_util.h"
avia2f4804a2015-12-24 23:11:1316#include "base/macros.h"
dchengc963c7142016-04-08 03:55:2217#include "base/memory/ptr_util.h"
treib9afc6212015-10-30 18:49:5818#include "base/memory/weak_ptr.h"
19#include "base/metrics/field_trial.h"
20#include "base/test/mock_entropy_provider.h"
mamirf7715a2a2016-07-04 13:05:0821#include "chrome/browser/extensions/api/webstore_private/webstore_private_api.h"
treib9afc6212015-10-30 18:49:5822#include "chrome/browser/extensions/component_loader.h"
23#include "chrome/browser/extensions/extension_service.h"
24#include "chrome/browser/extensions/extension_service_test_with_install.h"
25#include "chrome/browser/extensions/extension_sync_data.h"
26#include "chrome/browser/extensions/extension_sync_service.h"
27#include "chrome/browser/extensions/extension_util.h"
rdevlin.cronind01837b2016-08-17 01:37:1828#include "chrome/browser/extensions/scripting_permissions_modifier.h"
treib9afc6212015-10-30 18:49:5829#include "chrome/browser/extensions/updater/extension_updater.h"
treib9afc6212015-10-30 18:49:5830#include "chrome/browser/sync/profile_sync_service_factory.h"
31#include "chrome/common/chrome_constants.h"
32#include "chrome/common/chrome_switches.h"
33#include "chrome/common/extensions/sync_helper.h"
34#include "chrome/test/base/testing_profile.h"
maxbogue26f40222016-09-16 20:22:1835#include "components/browser_sync/profile_sync_service.h"
rdevlin.cronin738501d2015-11-05 21:51:3636#include "components/crx_file/id_util.h"
Max Boguefef332d2016-07-28 22:09:0937#include "components/sync/api/fake_sync_change_processor.h"
38#include "components/sync/api/sync_change_processor_wrapper_for_test.h"
39#include "components/sync/api/sync_data.h"
40#include "components/sync/api/sync_error_factory_mock.h"
treibb6af28cd2015-12-01 11:19:4641#include "components/variations/variations_associated_data.h"
mamirf7715a2a2016-07-04 13:05:0842#include "extensions/browser/api_test_utils.h"
treib9afc6212015-10-30 18:49:5843#include "extensions/browser/app_sorting.h"
44#include "extensions/browser/extension_prefs.h"
45#include "extensions/browser/extension_registry.h"
46#include "extensions/browser/extension_system.h"
47#include "extensions/browser/management_policy.h"
48#include "extensions/browser/test_management_policy.h"
49#include "extensions/common/constants.h"
rdevlin.cronin738501d2015-11-05 21:51:3650#include "extensions/common/extension_builder.h"
treib9afc6212015-10-30 18:49:5851#include "extensions/common/manifest_url_handlers.h"
52#include "extensions/common/permissions/permission_set.h"
rdevlin.cronin738501d2015-11-05 21:51:3653#include "extensions/common/value_builder.h"
treib9afc6212015-10-30 18:49:5854#include "testing/gtest/include/gtest/gtest.h"
55
56#if defined(ENABLE_SUPERVISED_USERS)
57#include "chrome/browser/supervised_user/permission_request_creator.h"
58#include "chrome/browser/supervised_user/supervised_user_constants.h"
mamire9609642016-06-28 22:17:5459#include "chrome/browser/supervised_user/supervised_user_features.h"
treib9afc6212015-10-30 18:49:5860#include "chrome/browser/supervised_user/supervised_user_service.h"
61#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
mamire9609642016-06-28 22:17:5462#include "chrome/browser/supervised_user/supervised_user_settings_service.h"
63#include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
64#include "chrome/common/pref_names.h"
treib9afc6212015-10-30 18:49:5865#endif
66
mamirf7715a2a2016-07-04 13:05:0867using extensions::api_test_utils::RunFunctionAndReturnSingleResult;
treib9afc6212015-10-30 18:49:5868using extensions::AppSorting;
69using extensions::Extension;
70using extensions::ExtensionPrefs;
71using extensions::ExtensionSyncData;
72using extensions::ExtensionSystem;
73using extensions::Manifest;
74using extensions::PermissionSet;
rdevlin.cronind01837b2016-08-17 01:37:1875using extensions::ScriptingPermissionsModifier;
mamirf7715a2a2016-07-04 13:05:0876using extensions::WebstorePrivateIsPendingCustodianApprovalFunction;
treib65f103042015-12-03 10:21:3677using syncer::SyncChange;
78using syncer::SyncChangeList;
mamire9609642016-06-28 22:17:5479using testing::Mock;
treib65f103042015-12-03 10:21:3680
81namespace {
treib9afc6212015-10-30 18:49:5882
mamir192d7882016-06-22 17:10:1683const char autoupdate[] = "ogjcoiohnmldgjemafoockdghcjciccf";
treib9afc6212015-10-30 18:49:5884const char good0[] = "behllobkkfkfnphdnhnkndlbkcpglgmj";
85const char good2[] = "bjafgdebaacbbbecmhlhpofkepfkgcpa";
mamir192d7882016-06-22 17:10:1686const char good2048[] = "nmgjhmhbleinmjpbdhgajfjkbijcmgbh";
treib9afc6212015-10-30 18:49:5887const char good_crx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
88const char page_action[] = "obcimlgaoabeegjmmpldobjndiealpln";
mamir192d7882016-06-22 17:10:1689const char permissions_increase[] = "pgdpcfcocojkjfbgpiianjngphoopgmo";
treib9afc6212015-10-30 18:49:5890const char theme2_crx[] = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf";
91
treib65f103042015-12-03 10:21:3692SyncChangeList MakeSyncChangeList(const std::string& id,
93 const sync_pb::EntitySpecifics& specifics,
94 SyncChange::SyncChangeType change_type) {
95 syncer::SyncData sync_data =
96 syncer::SyncData::CreateLocalData(id, "Name", specifics);
97 return SyncChangeList(1, SyncChange(FROM_HERE, change_type, sync_data));
98}
99
asargente48ab752016-03-12 00:59:20100// This is a FakeSyncChangeProcessor specialization that maintains a store of
101// SyncData items in the superclass' data_ member variable, treating it like a
102// map keyed by the extension id from the SyncData. Each instance of this class
103// should only be used for one model type (which should be either extensions or
104// apps) to match how the real sync system handles things.
105class StatefulChangeProcessor : public syncer::FakeSyncChangeProcessor {
106 public:
107 explicit StatefulChangeProcessor(syncer::ModelType expected_type)
108 : expected_type_(expected_type) {
109 EXPECT_TRUE(expected_type == syncer::ModelType::EXTENSIONS ||
110 expected_type == syncer::ModelType::APPS);
111 }
112
113 ~StatefulChangeProcessor() override {}
114
115 // We let our parent class, FakeSyncChangeProcessor, handle saving the
116 // changes for us, but in addition we "apply" these changes by treating
117 // the FakeSyncChangeProcessor's SyncDataList as a map keyed by extension
118 // id.
119 syncer::SyncError ProcessSyncChanges(
120 const tracked_objects::Location& from_here,
121 const syncer::SyncChangeList& change_list) override {
122 syncer::FakeSyncChangeProcessor::ProcessSyncChanges(from_here, change_list);
123 for (const auto& change : change_list) {
124 syncer::SyncData sync_data = change.sync_data();
125 EXPECT_EQ(expected_type_, sync_data.GetDataType());
126
dchengc963c7142016-04-08 03:55:22127 std::unique_ptr<ExtensionSyncData> modified =
asargente48ab752016-03-12 00:59:20128 ExtensionSyncData::CreateFromSyncData(sync_data);
129
130 // Start by removing any existing entry for this extension id.
131 syncer::SyncDataList& data_list = data();
132 for (auto iter = data_list.begin(); iter != data_list.end(); ++iter) {
dchengc963c7142016-04-08 03:55:22133 std::unique_ptr<ExtensionSyncData> existing =
asargente48ab752016-03-12 00:59:20134 ExtensionSyncData::CreateFromSyncData(*iter);
135 if (existing->id() == modified->id()) {
136 data_list.erase(iter);
137 break;
138 }
139 }
140
141 // Now add in the new data for this id, if appropriate.
142 if (change.change_type() == SyncChange::ACTION_ADD ||
143 change.change_type() == SyncChange::ACTION_UPDATE) {
144 data_list.push_back(sync_data);
145 } else if (change.change_type() != SyncChange::ACTION_DELETE) {
146 ADD_FAILURE() << "Unexpected change type " << change.change_type();
147 }
148 }
149 return syncer::SyncError();
150 }
151
152 // We override this to help catch the error of trying to use a single
153 // StatefulChangeProcessor to process changes for both extensions and apps
154 // sync data.
155 syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override {
156 EXPECT_EQ(expected_type_, type);
157 return FakeSyncChangeProcessor::GetAllSyncData(type);
158 }
159
160 // This is a helper to vend a wrapped version of this object suitable for
161 // passing in to MergeDataAndStartSyncing, which takes a
dchengc963c7142016-04-08 03:55:22162 // std::unique_ptr<SyncChangeProcessor>, since in tests we typically don't
163 // want to
asargente48ab752016-03-12 00:59:20164 // give up ownership of a local change processor.
dchengc963c7142016-04-08 03:55:22165 std::unique_ptr<syncer::SyncChangeProcessor> GetWrapped() {
ricea91d6fc122016-08-30 08:47:14166 return base::MakeUnique<syncer::SyncChangeProcessorWrapperForTest>(this);
asargente48ab752016-03-12 00:59:20167 }
168
169 protected:
170 // The expected ModelType of changes that this processor will see.
171 syncer::ModelType expected_type_;
172
173 DISALLOW_COPY_AND_ASSIGN(StatefulChangeProcessor);
174};
175
treib65f103042015-12-03 10:21:36176} // namespace
177
treib9afc6212015-10-30 18:49:58178class ExtensionServiceSyncTest
179 : public extensions::ExtensionServiceTestWithInstall {
180 public:
181 void MockSyncStartFlare(bool* was_called,
182 syncer::ModelType* model_type_passed_in,
183 syncer::ModelType model_type) {
184 *was_called = true;
185 *model_type_passed_in = model_type;
186 }
187
asargente48ab752016-03-12 00:59:20188 // Helper to call MergeDataAndStartSyncing with no server data and dummy
189 // change processor / error factory.
190 void StartSyncing(syncer::ModelType type) {
191 ASSERT_TRUE(type == syncer::EXTENSIONS || type == syncer::APPS);
192 extension_sync_service()->MergeDataAndStartSyncing(
193 type, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14194 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
195 base::MakeUnique<syncer::SyncErrorFactoryMock>());
asargente48ab752016-03-12 00:59:20196 }
197
treib9afc6212015-10-30 18:49:58198 protected:
199 // Paths to some of the fake extensions.
200 base::FilePath good0_path() {
201 return data_dir()
202 .AppendASCII("good")
203 .AppendASCII("Extensions")
204 .AppendASCII(good0)
205 .AppendASCII("1.0.0.0");
206 }
207
208 ExtensionSyncService* extension_sync_service() {
209 return ExtensionSyncService::Get(profile());
210 }
211};
212
213TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledComponent) {
214 InitializeEmptyExtensionService();
215
216 bool flare_was_called = false;
217 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
218 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
219 extension_sync_service()->SetSyncStartFlareForTesting(
220 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
221 factory.GetWeakPtr(),
222 &flare_was_called, // Safe due to WeakPtrFactory scope.
223 &triggered_type)); // Safe due to WeakPtrFactory scope.
224
225 // Install a component extension.
226 std::string manifest;
227 ASSERT_TRUE(base::ReadFileToString(
228 good0_path().Append(extensions::kManifestFilename), &manifest));
229 service()->component_loader()->Add(manifest, good0_path());
230 ASSERT_FALSE(service()->is_ready());
231 service()->Init();
232 ASSERT_TRUE(service()->is_ready());
233
234 // Extensions added before service is_ready() don't trigger sync startup.
235 EXPECT_FALSE(flare_was_called);
236 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
237}
238
239TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledNormal) {
240 InitializeGoodInstalledExtensionService();
241
242 bool flare_was_called = false;
243 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
244 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
245 extension_sync_service()->SetSyncStartFlareForTesting(
246 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
247 factory.GetWeakPtr(),
248 &flare_was_called, // Safe due to WeakPtrFactory scope.
249 &triggered_type)); // Safe due to WeakPtrFactory scope.
250
251 ASSERT_FALSE(service()->is_ready());
252 service()->Init();
253 ASSERT_EQ(3u, loaded_.size());
254 ASSERT_TRUE(service()->is_ready());
255
256 // Extensions added before service is_ready() don't trigger sync startup.
257 EXPECT_FALSE(flare_was_called);
258 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
259}
260
261TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupOnInstall) {
262 InitializeEmptyExtensionService();
263 service()->Init();
264 ASSERT_TRUE(service()->is_ready());
265
266 bool flare_was_called = false;
267 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
268 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
269 extension_sync_service()->SetSyncStartFlareForTesting(
270 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
271 factory.GetWeakPtr(),
272 &flare_was_called, // Safe due to WeakPtrFactory scope.
273 &triggered_type)); // Safe due to WeakPtrFactory scope.
274
275 base::FilePath path = data_dir().AppendASCII("good.crx");
276 InstallCRX(path, INSTALL_NEW);
277
278 EXPECT_TRUE(flare_was_called);
279 EXPECT_EQ(syncer::EXTENSIONS, triggered_type);
280
281 // Reset.
282 flare_was_called = false;
283 triggered_type = syncer::UNSPECIFIED;
284
285 // Once sync starts, flare should no longer be invoked.
286 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36287 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14288 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
289 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58290 path = data_dir().AppendASCII("page_action.crx");
291 InstallCRX(path, INSTALL_NEW);
292 EXPECT_FALSE(flare_was_called);
293 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
294}
295
296TEST_F(ExtensionServiceSyncTest, DisableExtensionFromSync) {
297 // Start the extensions service with one external extension already installed.
298 base::FilePath source_install_dir =
299 data_dir().AppendASCII("good").AppendASCII("Extensions");
300 base::FilePath pref_path =
301 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
302
303 InitializeInstalledExtensionService(pref_path, source_install_dir);
304
305 // The user has enabled sync.
maxbogue0a379452016-09-22 21:35:05306 browser_sync::ProfileSyncService* sync_service =
treib9afc6212015-10-30 18:49:58307 ProfileSyncServiceFactory::GetForProfile(profile());
maxboguefe00952a2016-01-19 19:02:01308 sync_service->SetFirstSetupComplete();
treib9afc6212015-10-30 18:49:58309
310 service()->Init();
311 ASSERT_TRUE(service()->is_ready());
312
313 ASSERT_EQ(3u, loaded_.size());
314
315 // We start enabled.
316 const Extension* extension = service()->GetExtensionById(good0, true);
317 ASSERT_TRUE(extension);
318 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
319
320 // Sync starts up.
321 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36322 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14323 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
324 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58325
326 // Then sync data arrives telling us to disable |good0|.
327 ExtensionSyncData disable_good_crx(*extension, false,
328 Extension::DISABLE_USER_ACTION, false,
mamir192d7882016-06-22 17:10:16329 false, ExtensionSyncData::BOOLEAN_UNSET,
330 false);
treib65f103042015-12-03 10:21:36331 SyncChangeList list(
332 1, disable_good_crx.GetSyncChange(SyncChange::ACTION_UPDATE));
treib9afc6212015-10-30 18:49:58333 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
334
335 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
336}
337
338TEST_F(ExtensionServiceSyncTest, IgnoreSyncChangesWhenLocalStateIsMoreRecent) {
339 // Start the extension service with three extensions already installed.
340 base::FilePath source_install_dir =
341 data_dir().AppendASCII("good").AppendASCII("Extensions");
342 base::FilePath pref_path =
343 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
344
345 InitializeInstalledExtensionService(pref_path, source_install_dir);
346
347 // The user has enabled sync.
maxbogue0a379452016-09-22 21:35:05348 browser_sync::ProfileSyncService* sync_service =
treib9afc6212015-10-30 18:49:58349 ProfileSyncServiceFactory::GetForProfile(profile());
maxboguefe00952a2016-01-19 19:02:01350 sync_service->SetFirstSetupComplete();
treib9afc6212015-10-30 18:49:58351 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
352 extension_sync_service();
353
354 service()->Init();
355 ASSERT_TRUE(service()->is_ready());
356 ASSERT_EQ(3u, loaded_.size());
357
358 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
359 ASSERT_TRUE(service()->IsExtensionEnabled(good2));
360
361 // Disable and re-enable good0 before first sync data arrives.
362 service()->DisableExtension(good0, Extension::DISABLE_USER_ACTION);
363 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
364 service()->EnableExtension(good0);
365 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
366 // Disable good2 before first sync data arrives (good1 is considered
367 // non-syncable because it has plugin permission).
368 service()->DisableExtension(good2, Extension::DISABLE_USER_ACTION);
369 ASSERT_FALSE(service()->IsExtensionEnabled(good2));
370
371 const Extension* extension0 = service()->GetExtensionById(good0, true);
372 const Extension* extension2 = service()->GetExtensionById(good2, true);
373 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension0));
374 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension2));
375
376 // Now sync data comes in that says to disable good0 and enable good2.
377 ExtensionSyncData disable_good0(*extension0, false,
378 Extension::DISABLE_USER_ACTION, false, false,
mamir192d7882016-06-22 17:10:16379 ExtensionSyncData::BOOLEAN_UNSET, false);
treib9afc6212015-10-30 18:49:58380 ExtensionSyncData enable_good2(*extension2, true, Extension::DISABLE_NONE,
381 false, false,
mamir192d7882016-06-22 17:10:16382 ExtensionSyncData::BOOLEAN_UNSET, false);
treib9afc6212015-10-30 18:49:58383 syncer::SyncDataList sync_data;
384 sync_data.push_back(disable_good0.GetSyncData());
385 sync_data.push_back(enable_good2.GetSyncData());
386 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:22387 syncer::EXTENSIONS, sync_data,
ricea91d6fc122016-08-30 08:47:14388 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
389 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58390
391 // Both sync changes should be ignored, since the local state was changed
392 // before sync started, and so the local state is considered more recent.
393 EXPECT_TRUE(service()->IsExtensionEnabled(good0));
394 EXPECT_FALSE(service()->IsExtensionEnabled(good2));
395}
396
treibb794dd52015-12-01 18:47:14397TEST_F(ExtensionServiceSyncTest, DontSelfNotify) {
398 // Start the extension service with three extensions already installed.
399 base::FilePath source_install_dir =
400 data_dir().AppendASCII("good").AppendASCII("Extensions");
401 base::FilePath pref_path =
402 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
403
404 InitializeInstalledExtensionService(pref_path, source_install_dir);
405
406 // The user has enabled sync.
maxboguefe00952a2016-01-19 19:02:01407 ProfileSyncServiceFactory::GetForProfile(profile())->SetFirstSetupComplete();
treibb794dd52015-12-01 18:47:14408 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
409 extension_sync_service();
410
411 service()->Init();
412 ASSERT_TRUE(service()->is_ready());
413 ASSERT_EQ(3u, loaded_.size());
414 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
415
416 syncer::FakeSyncChangeProcessor* processor =
417 new syncer::FakeSyncChangeProcessor;
418 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:22419 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
ricea91d6fc122016-08-30 08:47:14420 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treibb794dd52015-12-01 18:47:14421
422 processor->changes().clear();
423
424 // Simulate various incoming sync changes, and make sure they don't result in
425 // any outgoing changes.
426
427 {
428 const Extension* extension = service()->GetExtensionById(good0, true);
429 ASSERT_TRUE(extension);
430
431 // Disable the extension.
432 ExtensionSyncData data(*extension, false, Extension::DISABLE_USER_ACTION,
mamir192d7882016-06-22 17:10:16433 false, false, ExtensionSyncData::BOOLEAN_UNSET,
434 false);
treib65f103042015-12-03 10:21:36435 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14436
437 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
438
439 EXPECT_TRUE(processor->changes().empty());
440 }
441
442 {
443 const Extension* extension = service()->GetExtensionById(good0, true);
444 ASSERT_TRUE(extension);
445
446 // Set incognito enabled to true.
447 ExtensionSyncData data(*extension, false, Extension::DISABLE_NONE, true,
mamir192d7882016-06-22 17:10:16448 false, ExtensionSyncData::BOOLEAN_UNSET, false);
treib65f103042015-12-03 10:21:36449 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14450
451 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
452
453 EXPECT_TRUE(processor->changes().empty());
454 }
455
456 {
457 const Extension* extension = service()->GetExtensionById(good0, true);
458 ASSERT_TRUE(extension);
459
460 // Add another disable reason.
461 ExtensionSyncData data(*extension, false,
462 Extension::DISABLE_USER_ACTION |
463 Extension::DISABLE_PERMISSIONS_INCREASE,
mamir192d7882016-06-22 17:10:16464 false, false, ExtensionSyncData::BOOLEAN_UNSET,
465 false);
treib65f103042015-12-03 10:21:36466 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14467
468 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
469
470 EXPECT_TRUE(processor->changes().empty());
471 }
472
473 {
474 const Extension* extension = service()->GetExtensionById(good0, true);
475 ASSERT_TRUE(extension);
476
477 // Uninstall the extension.
478 ExtensionSyncData data(*extension, false,
479 Extension::DISABLE_USER_ACTION |
480 Extension::DISABLE_PERMISSIONS_INCREASE,
mamir192d7882016-06-22 17:10:16481 false, false, ExtensionSyncData::BOOLEAN_UNSET,
482 false);
treib65f103042015-12-03 10:21:36483 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_DELETE));
treibb794dd52015-12-01 18:47:14484
485 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
486
487 EXPECT_TRUE(processor->changes().empty());
488 }
489}
490
treib9afc6212015-10-30 18:49:58491TEST_F(ExtensionServiceSyncTest, GetSyncData) {
492 InitializeEmptyExtensionService();
493 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
494 const Extension* extension = service()->GetInstalledExtension(good_crx);
495 ASSERT_TRUE(extension);
496
497 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36498 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14499 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
500 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58501
502 syncer::SyncDataList list =
503 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
504 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22505 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58506 ExtensionSyncData::CreateFromSyncData(list[0]);
507 ASSERT_TRUE(data.get());
508 EXPECT_EQ(extension->id(), data->id());
509 EXPECT_FALSE(data->uninstalled());
510 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
511 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
512 data->incognito_enabled());
513 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
robpercivaldcd8b102016-01-25 19:39:00514 EXPECT_EQ(data->version(), *extension->version());
treib9afc6212015-10-30 18:49:58515 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
516 data->update_url());
517 EXPECT_EQ(extension->name(), data->name());
518}
519
treib29e1b9b12015-11-11 08:50:56520TEST_F(ExtensionServiceSyncTest, GetSyncDataDisableReasons) {
521 InitializeEmptyExtensionService();
522 const Extension* extension =
523 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
524 ASSERT_TRUE(extension);
525
treib29e1b9b12015-11-11 08:50:56526 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36527 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14528 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
529 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib29e1b9b12015-11-11 08:50:56530
531 {
532 syncer::SyncDataList list =
533 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
534 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22535 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56536 ExtensionSyncData::CreateFromSyncData(list[0]);
537 ASSERT_TRUE(data.get());
538 EXPECT_TRUE(data->enabled());
539 EXPECT_TRUE(data->supports_disable_reasons());
540 EXPECT_EQ(Extension::DISABLE_NONE, data->disable_reasons());
541 }
542
543 // Syncable disable reason, should propagate to sync.
544 service()->DisableExtension(good_crx, Extension::DISABLE_USER_ACTION);
545 {
546 syncer::SyncDataList list =
547 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
548 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22549 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56550 ExtensionSyncData::CreateFromSyncData(list[0]);
551 ASSERT_TRUE(data.get());
552 EXPECT_FALSE(data->enabled());
553 EXPECT_TRUE(data->supports_disable_reasons());
554 EXPECT_EQ(Extension::DISABLE_USER_ACTION, data->disable_reasons());
555 }
556 service()->EnableExtension(good_crx);
557
558 // Non-syncable disable reason. The sync data should still say "enabled".
559 service()->DisableExtension(good_crx, Extension::DISABLE_RELOAD);
560 {
561 syncer::SyncDataList list =
562 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
563 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22564 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56565 ExtensionSyncData::CreateFromSyncData(list[0]);
566 ASSERT_TRUE(data.get());
567 EXPECT_TRUE(data->enabled());
568 EXPECT_TRUE(data->supports_disable_reasons());
569 EXPECT_EQ(Extension::DISABLE_NONE, data->disable_reasons());
570 }
571 service()->EnableExtension(good_crx);
572
573 // Both a syncable and a non-syncable disable reason, only the former should
574 // propagate to sync.
575 service()->DisableExtension(
576 good_crx, Extension::DISABLE_USER_ACTION | Extension::DISABLE_RELOAD);
577 {
578 syncer::SyncDataList list =
579 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
580 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22581 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56582 ExtensionSyncData::CreateFromSyncData(list[0]);
583 ASSERT_TRUE(data.get());
584 EXPECT_FALSE(data->enabled());
585 EXPECT_TRUE(data->supports_disable_reasons());
586 EXPECT_EQ(Extension::DISABLE_USER_ACTION, data->disable_reasons());
587 }
588 service()->EnableExtension(good_crx);
589}
590
treib9afc6212015-10-30 18:49:58591TEST_F(ExtensionServiceSyncTest, GetSyncDataTerminated) {
592 InitializeEmptyExtensionService();
593 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
594 TerminateExtension(good_crx);
595 const Extension* extension = service()->GetInstalledExtension(good_crx);
596 ASSERT_TRUE(extension);
597
treib9afc6212015-10-30 18:49:58598 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36599 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14600 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
601 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58602
603 syncer::SyncDataList list =
604 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
605 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22606 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58607 ExtensionSyncData::CreateFromSyncData(list[0]);
608 ASSERT_TRUE(data.get());
609 EXPECT_EQ(extension->id(), data->id());
610 EXPECT_FALSE(data->uninstalled());
611 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
612 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
613 data->incognito_enabled());
614 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
robpercivaldcd8b102016-01-25 19:39:00615 EXPECT_EQ(data->version(), *extension->version());
treib9afc6212015-10-30 18:49:58616 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
617 data->update_url());
618 EXPECT_EQ(extension->name(), data->name());
619}
620
621TEST_F(ExtensionServiceSyncTest, GetSyncDataFilter) {
622 InitializeEmptyExtensionService();
623 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
624 const Extension* extension = service()->GetInstalledExtension(good_crx);
625 ASSERT_TRUE(extension);
626
treib9afc6212015-10-30 18:49:58627 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36628 syncer::APPS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14629 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
630 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58631
632 syncer::SyncDataList list =
633 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
634 ASSERT_EQ(list.size(), 0U);
635}
636
637TEST_F(ExtensionServiceSyncTest, GetSyncExtensionDataUserSettings) {
638 InitializeEmptyExtensionService();
639 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
640 const Extension* extension = service()->GetInstalledExtension(good_crx);
641 ASSERT_TRUE(extension);
642
treib9afc6212015-10-30 18:49:58643 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36644 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14645 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
646 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58647
648 {
649 syncer::SyncDataList list =
650 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
651 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22652 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58653 ExtensionSyncData::CreateFromSyncData(list[0]);
654 ASSERT_TRUE(data.get());
655 EXPECT_TRUE(data->enabled());
656 EXPECT_FALSE(data->incognito_enabled());
657 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
658 }
659
660 service()->DisableExtension(good_crx, Extension::DISABLE_USER_ACTION);
661 {
662 syncer::SyncDataList list =
663 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
664 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22665 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58666 ExtensionSyncData::CreateFromSyncData(list[0]);
667 ASSERT_TRUE(data.get());
668 EXPECT_FALSE(data->enabled());
669 EXPECT_FALSE(data->incognito_enabled());
670 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
671 }
672
673 extensions::util::SetIsIncognitoEnabled(good_crx, profile(), true);
rdevlin.cronind01837b2016-08-17 01:37:18674 ScriptingPermissionsModifier permissions_modifier(
675 profile(), registry()->GetExtensionById(
676 good_crx, extensions::ExtensionRegistry::EVERYTHING));
677 permissions_modifier.SetAllowedOnAllUrls(false);
treib9afc6212015-10-30 18:49:58678 {
679 syncer::SyncDataList list =
680 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
681 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22682 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58683 ExtensionSyncData::CreateFromSyncData(list[0]);
684 ASSERT_TRUE(data.get());
685 EXPECT_FALSE(data->enabled());
686 EXPECT_TRUE(data->incognito_enabled());
687 EXPECT_EQ(ExtensionSyncData::BOOLEAN_FALSE, data->all_urls_enabled());
688 }
689
690 service()->EnableExtension(good_crx);
rdevlin.cronind01837b2016-08-17 01:37:18691 permissions_modifier.SetAllowedOnAllUrls(true);
treib9afc6212015-10-30 18:49:58692 {
693 syncer::SyncDataList list =
694 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
695 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22696 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58697 ExtensionSyncData::CreateFromSyncData(list[0]);
698 ASSERT_TRUE(data.get());
699 EXPECT_TRUE(data->enabled());
700 EXPECT_TRUE(data->incognito_enabled());
701 EXPECT_EQ(ExtensionSyncData::BOOLEAN_TRUE, data->all_urls_enabled());
702 }
703}
704
705TEST_F(ExtensionServiceSyncTest, SyncForUninstalledExternalExtension) {
706 InitializeEmptyExtensionService();
707 InstallCRXWithLocation(
708 data_dir().AppendASCII("good.crx"), Manifest::EXTERNAL_PREF, INSTALL_NEW);
709 const Extension* extension = service()->GetInstalledExtension(good_crx);
710 ASSERT_TRUE(extension);
711
treib9afc6212015-10-30 18:49:58712 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36713 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14714 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
715 base::MakeUnique<syncer::SyncErrorFactoryMock>());
asargente48ab752016-03-12 00:59:20716 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:58717
718 UninstallExtension(good_crx, false);
719 EXPECT_TRUE(
720 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
721
722 sync_pb::EntitySpecifics specifics;
723 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
724 sync_pb::ExtensionSpecifics* extension_specifics =
725 app_specifics->mutable_extension();
726 extension_specifics->set_id(good_crx);
727 extension_specifics->set_version("1.0");
728 extension_specifics->set_enabled(true);
729
treib65f103042015-12-03 10:21:36730 SyncChangeList list =
731 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:58732
733 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
734 EXPECT_TRUE(
735 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
736}
737
738TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettings) {
739 InitializeEmptyExtensionService();
740 const Extension* app =
741 PackAndInstallCRX(data_dir().AppendASCII("app"), INSTALL_NEW);
742 ASSERT_TRUE(app);
743 ASSERT_TRUE(app->is_app());
744
treib9afc6212015-10-30 18:49:58745 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36746 syncer::APPS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14747 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
748 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58749
750 syncer::StringOrdinal initial_ordinal =
751 syncer::StringOrdinal::CreateInitialOrdinal();
752 {
753 syncer::SyncDataList list =
754 extension_sync_service()->GetAllSyncData(syncer::APPS);
755 ASSERT_EQ(list.size(), 1U);
756
dchengc963c7142016-04-08 03:55:22757 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58758 ExtensionSyncData::CreateFromSyncData(list[0]);
759 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->app_launch_ordinal()));
760 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
761 }
762
deepak.m14ba69e62015-11-17 05:42:12763 AppSorting* sorting = ExtensionSystem::Get(profile())->app_sorting();
treib9afc6212015-10-30 18:49:58764 sorting->SetAppLaunchOrdinal(app->id(), initial_ordinal.CreateAfter());
765 {
766 syncer::SyncDataList list =
767 extension_sync_service()->GetAllSyncData(syncer::APPS);
768 ASSERT_EQ(list.size(), 1U);
769
dchengc963c7142016-04-08 03:55:22770 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58771 ExtensionSyncData::CreateFromSyncData(list[0]);
772 ASSERT_TRUE(app_sync_data.get());
773 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
774 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
775 }
776
777 sorting->SetPageOrdinal(app->id(), initial_ordinal.CreateAfter());
778 {
779 syncer::SyncDataList list =
780 extension_sync_service()->GetAllSyncData(syncer::APPS);
781 ASSERT_EQ(list.size(), 1U);
782
dchengc963c7142016-04-08 03:55:22783 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58784 ExtensionSyncData::CreateFromSyncData(list[0]);
785 ASSERT_TRUE(app_sync_data.get());
786 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
787 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->page_ordinal()));
788 }
789}
790
791// TODO (rdevlin.cronin): The OnExtensionMoved() method has been removed from
792// ExtensionService, so this test probably needs a new home. Unfortunately, it
793// relies pretty heavily on things like InitializeExtension[Sync]Service() and
794// PackAndInstallCRX(). When we clean up a bit more, this should move out.
795TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettingsOnExtensionMoved) {
796 InitializeEmptyExtensionService();
797 const size_t kAppCount = 3;
798 const Extension* apps[kAppCount];
799 apps[0] = PackAndInstallCRX(data_dir().AppendASCII("app1"), INSTALL_NEW);
800 apps[1] = PackAndInstallCRX(data_dir().AppendASCII("app2"), INSTALL_NEW);
801 apps[2] = PackAndInstallCRX(data_dir().AppendASCII("app4"), INSTALL_NEW);
802 for (size_t i = 0; i < kAppCount; ++i) {
803 ASSERT_TRUE(apps[i]);
804 ASSERT_TRUE(apps[i]->is_app());
805 }
806
treib9afc6212015-10-30 18:49:58807 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36808 syncer::APPS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22809 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
810 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58811
deepak.m14ba69e62015-11-17 05:42:12812 ExtensionSystem::Get(service()->GetBrowserContext())
treib9afc6212015-10-30 18:49:58813 ->app_sorting()
814 ->OnExtensionMoved(apps[0]->id(), apps[1]->id(), apps[2]->id());
815 {
816 syncer::SyncDataList list =
817 extension_sync_service()->GetAllSyncData(syncer::APPS);
818 ASSERT_EQ(list.size(), 3U);
819
dchengc963c7142016-04-08 03:55:22820 std::unique_ptr<ExtensionSyncData> data[kAppCount];
treib9afc6212015-10-30 18:49:58821 for (size_t i = 0; i < kAppCount; ++i) {
822 data[i] = ExtensionSyncData::CreateFromSyncData(list[i]);
823 ASSERT_TRUE(data[i].get());
824 }
825
826 // The sync data is not always in the same order our apps were installed in,
827 // so we do that sorting here so we can make sure the values are changed as
828 // expected.
829 syncer::StringOrdinal app_launch_ordinals[kAppCount];
830 for (size_t i = 0; i < kAppCount; ++i) {
831 for (size_t j = 0; j < kAppCount; ++j) {
832 if (apps[i]->id() == data[j]->id())
833 app_launch_ordinals[i] = data[j]->app_launch_ordinal();
834 }
835 }
836
837 EXPECT_TRUE(app_launch_ordinals[1].LessThan(app_launch_ordinals[0]));
838 EXPECT_TRUE(app_launch_ordinals[0].LessThan(app_launch_ordinals[2]));
839 }
840}
841
842TEST_F(ExtensionServiceSyncTest, GetSyncDataList) {
843 InitializeEmptyExtensionService();
844 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
845 InstallCRX(data_dir().AppendASCII("page_action.crx"), INSTALL_NEW);
846 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
847 InstallCRX(data_dir().AppendASCII("theme2.crx"), INSTALL_NEW);
848
treib9afc6212015-10-30 18:49:58849 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36850 syncer::APPS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14851 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
852 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58853 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36854 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14855 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
856 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58857
858 service()->DisableExtension(page_action, Extension::DISABLE_USER_ACTION);
859 TerminateExtension(theme2_crx);
860
861 EXPECT_EQ(0u, extension_sync_service()->GetAllSyncData(syncer::APPS).size());
862 EXPECT_EQ(
863 2u, extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS).size());
864}
865
866TEST_F(ExtensionServiceSyncTest, ProcessSyncDataUninstall) {
867 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:58868 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36869 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14870 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
871 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58872
873 sync_pb::EntitySpecifics specifics;
874 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
875 ext_specifics->set_id(good_crx);
876 ext_specifics->set_version("1.0");
treib65f103042015-12-03 10:21:36877
878 SyncChangeList list =
879 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:58880
881 // Should do nothing.
882 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
883 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
884
885 // Install the extension.
886 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
887 InstallCRX(extension_path, INSTALL_NEW);
888 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
889
890 // Should uninstall the extension.
891 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
892 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
893
894 // Should again do nothing.
895 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
896 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
897}
898
899TEST_F(ExtensionServiceSyncTest, ProcessSyncDataWrongType) {
900 InitializeEmptyExtensionService();
asargente48ab752016-03-12 00:59:20901 StartSyncing(syncer::EXTENSIONS);
902 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:58903
904 // Install the extension.
905 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
906 InstallCRX(extension_path, INSTALL_NEW);
907 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
908
909 sync_pb::EntitySpecifics specifics;
910 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
911 sync_pb::ExtensionSpecifics* extension_specifics =
912 app_specifics->mutable_extension();
913 extension_specifics->set_id(good_crx);
914 extension_specifics->set_version(
915 service()->GetInstalledExtension(good_crx)->version()->GetString());
916
917 {
918 extension_specifics->set_enabled(true);
treib65f103042015-12-03 10:21:36919
920 SyncChangeList list =
921 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:58922
923 // Should do nothing
924 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
925 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
926 }
927
928 {
929 extension_specifics->set_enabled(false);
treib65f103042015-12-03 10:21:36930
931 SyncChangeList list =
932 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:58933
934 // Should again do nothing.
935 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
936 EXPECT_TRUE(service()->GetExtensionById(good_crx, false));
937 }
938}
939
940TEST_F(ExtensionServiceSyncTest, ProcessSyncDataSettings) {
941 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:58942 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36943 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14944 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
945 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58946
947 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
948 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
949 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
rdevlin.cronind01837b2016-08-17 01:37:18950 // Returns a ScriptingPermissionsModifier for the extension. We use this
951 // because various parts of this test reload the extension, making keeping a
952 // ptr to it inviable.
953 auto get_permissions_modifier = [this]() {
954 const Extension* extension = registry()->GetExtensionById(
955 good_crx, extensions::ExtensionRegistry::EVERYTHING);
956 return base::MakeUnique<ScriptingPermissionsModifier>(profile(), extension);
957 };
958 EXPECT_FALSE(get_permissions_modifier()->HasSetAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:58959 const bool kDefaultAllowedScripting =
rdevlin.cronind01837b2016-08-17 01:37:18960 ScriptingPermissionsModifier::DefaultAllowedOnAllUrls();
treib9afc6212015-10-30 18:49:58961 EXPECT_EQ(kDefaultAllowedScripting,
rdevlin.cronind01837b2016-08-17 01:37:18962 get_permissions_modifier()->IsAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:58963
964 sync_pb::EntitySpecifics specifics;
965 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
966 ext_specifics->set_id(good_crx);
967 ext_specifics->set_version(
968 service()->GetInstalledExtension(good_crx)->version()->GetString());
969 ext_specifics->set_enabled(false);
970
971 {
treib65f103042015-12-03 10:21:36972 SyncChangeList list =
973 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
974
treib9afc6212015-10-30 18:49:58975 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
976 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
977 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
rdevlin.cronind01837b2016-08-17 01:37:18978 EXPECT_FALSE(get_permissions_modifier()->HasSetAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:58979 EXPECT_EQ(kDefaultAllowedScripting,
rdevlin.cronind01837b2016-08-17 01:37:18980 get_permissions_modifier()->IsAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:58981 }
982
983 {
984 ext_specifics->set_enabled(true);
985 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:36986
987 SyncChangeList list =
988 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
989
treib9afc6212015-10-30 18:49:58990 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
991 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
992 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
993 }
994
995 {
996 ext_specifics->set_enabled(false);
997 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:36998
999 SyncChangeList list =
1000 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1001
treib9afc6212015-10-30 18:49:581002 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1003 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1004 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1005 }
1006
1007 {
1008 ext_specifics->set_enabled(true);
1009 ext_specifics->set_all_urls_enabled(!kDefaultAllowedScripting);
treib65f103042015-12-03 10:21:361010
1011 SyncChangeList list =
1012 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1013
treib9afc6212015-10-30 18:49:581014 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1015 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
rdevlin.cronind01837b2016-08-17 01:37:181016 EXPECT_TRUE(get_permissions_modifier()->HasSetAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:581017 EXPECT_EQ(!kDefaultAllowedScripting,
rdevlin.cronind01837b2016-08-17 01:37:181018 get_permissions_modifier()->IsAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:581019 }
1020
1021 {
1022 ext_specifics->set_all_urls_enabled(kDefaultAllowedScripting);
treib65f103042015-12-03 10:21:361023
1024 SyncChangeList list =
1025 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1026
treib9afc6212015-10-30 18:49:581027 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1028 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
rdevlin.cronind01837b2016-08-17 01:37:181029 EXPECT_TRUE(get_permissions_modifier()->HasSetAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:581030 EXPECT_EQ(kDefaultAllowedScripting,
rdevlin.cronind01837b2016-08-17 01:37:181031 get_permissions_modifier()->IsAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:581032 }
1033
1034 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1035}
1036
1037TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNewExtension) {
1038 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581039 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361040 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141041 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1042 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581043
1044 const base::FilePath path = data_dir().AppendASCII("good.crx");
1045 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1046
1047 struct TestCase {
1048 const char* name; // For failure output only.
1049 bool sync_enabled; // The "enabled" flag coming in from Sync.
1050 // The disable reason(s) coming in from Sync, or -1 for "not set".
1051 int sync_disable_reasons;
1052 // The disable reason(s) that should be set on the installed extension.
1053 // This will usually be the same as |sync_disable_reasons|, but see the
1054 // "Legacy" case.
1055 int expect_disable_reasons;
1056 // Whether the extension's permissions should be auto-granted during
1057 // installation.
1058 bool expect_permissions_granted;
1059 } test_cases[] = {
1060 // Standard case: Extension comes in enabled; permissions should be granted
1061 // during installation.
1062 { "Standard", true, 0, 0, true },
1063 // If the extension comes in disabled, its permissions should still be
1064 // granted (the user already approved them on another machine).
1065 { "Disabled", false, Extension::DISABLE_USER_ACTION,
1066 Extension::DISABLE_USER_ACTION, true },
1067 // Legacy case (<M45): No disable reasons come in from Sync (see
1068 // crbug.com/484214). After installation, the reason should be set to
treib3b91e9f2015-11-04 11:29:411069 // DISABLE_USER_ACTION (default assumption).
1070 { "Legacy", false, -1, Extension::DISABLE_USER_ACTION, true },
treib9afc6212015-10-30 18:49:581071 // If the extension came in disabled due to a permissions increase, then the
1072 // user has *not* approved the permissions, and they shouldn't be granted.
1073 // crbug.com/484214
1074 { "PermissionsIncrease", false, Extension::DISABLE_PERMISSIONS_INCREASE,
1075 Extension::DISABLE_PERMISSIONS_INCREASE, false },
1076 };
1077
1078 for (const TestCase& test_case : test_cases) {
1079 SCOPED_TRACE(test_case.name);
1080
1081 sync_pb::EntitySpecifics specifics;
1082 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1083 ext_specifics->set_id(good_crx);
1084 ext_specifics->set_version(base::Version("1").GetString());
1085 ext_specifics->set_enabled(test_case.sync_enabled);
1086 if (test_case.sync_disable_reasons != -1)
1087 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1088
treib65f103042015-12-03 10:21:361089 SyncChangeList list =
1090 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1091
treib9afc6212015-10-30 18:49:581092 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1093
1094 ASSERT_TRUE(service()->pending_extension_manager()->IsIdPending(good_crx));
1095 UpdateExtension(good_crx, path, test_case.sync_enabled ? ENABLED
1096 : DISABLED);
1097 EXPECT_EQ(test_case.expect_disable_reasons,
1098 prefs->GetDisableReasons(good_crx));
dchengc963c7142016-04-08 03:55:221099 std::unique_ptr<const PermissionSet> permissions =
treib9afc6212015-10-30 18:49:581100 prefs->GetGrantedPermissions(good_crx);
1101 EXPECT_EQ(test_case.expect_permissions_granted, !permissions->IsEmpty());
1102 ASSERT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1103
1104 // Remove the extension again, so we can install it again for the next case.
1105 UninstallExtension(good_crx, false,
1106 test_case.sync_enabled ? Extension::ENABLED
1107 : Extension::DISABLED);
1108 }
1109}
1110
1111TEST_F(ExtensionServiceSyncTest, ProcessSyncDataTerminatedExtension) {
1112 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581113 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361114 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141115 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1116 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581117
1118 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1119 TerminateExtension(good_crx);
1120 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1121 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1122
1123 sync_pb::EntitySpecifics specifics;
1124 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1125 ext_specifics->set_id(good_crx);
1126 ext_specifics->set_version(
1127 service()->GetInstalledExtension(good_crx)->version()->GetString());
1128 ext_specifics->set_enabled(false);
1129 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361130
1131 SyncChangeList list =
1132 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581133
1134 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1135 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1136 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1137
1138 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1139}
1140
1141TEST_F(ExtensionServiceSyncTest, ProcessSyncDataVersionCheck) {
1142 InitializeExtensionServiceWithUpdater();
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()));
1151
1152 sync_pb::EntitySpecifics specifics;
1153 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1154 ext_specifics->set_id(good_crx);
1155 ext_specifics->set_enabled(true);
1156
1157 const base::Version installed_version =
1158 *service()->GetInstalledExtension(good_crx)->version();
1159
1160 {
1161 ext_specifics->set_version(installed_version.GetString());
treib65f103042015-12-03 10:21:361162
1163 SyncChangeList list =
1164 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581165
1166 // Should do nothing if extension version == sync version.
1167 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1168 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1169 // Make sure the version we'll send back to sync didn't change.
1170 syncer::SyncDataList data =
1171 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1172 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221173 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581174 ExtensionSyncData::CreateFromSyncData(data[0]);
1175 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001176 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581177 }
1178
1179 // Should do nothing if extension version > sync version.
1180 {
1181 ext_specifics->set_version("0.0.0.0");
treib65f103042015-12-03 10:21:361182
1183 SyncChangeList list =
1184 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581185
1186 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1187 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1188 // Make sure the version we'll send back to sync didn't change.
1189 syncer::SyncDataList data =
1190 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1191 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221192 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581193 ExtensionSyncData::CreateFromSyncData(data[0]);
1194 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001195 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581196 }
1197
1198 // Should kick off an update if extension version < sync version.
1199 {
1200 const base::Version new_version("9.9.9.9");
1201 ext_specifics->set_version(new_version.GetString());
treib65f103042015-12-03 10:21:361202
1203 SyncChangeList list =
1204 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581205
1206 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1207 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1208 // Make sure that we'll send the NEW version back to sync, even though we
1209 // haven't actually updated yet. This is to prevent the data in sync from
1210 // flip-flopping back and forth until all clients are up to date.
1211 syncer::SyncDataList data =
1212 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1213 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221214 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581215 ExtensionSyncData::CreateFromSyncData(data[0]);
1216 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001217 EXPECT_EQ(new_version, extension_data->version());
treib9afc6212015-10-30 18:49:581218 }
1219
1220 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1221}
1222
1223TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNotInstalled) {
1224 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581225 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361226 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141227 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1228 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581229
1230 sync_pb::EntitySpecifics specifics;
1231 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1232 ext_specifics->set_id(good_crx);
1233 ext_specifics->set_enabled(false);
1234 ext_specifics->set_incognito_enabled(true);
1235 ext_specifics->set_update_url("http://www.google.com/");
1236 ext_specifics->set_version("1.2.3.4");
treib65f103042015-12-03 10:21:361237
1238 SyncChangeList list =
1239 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581240
1241 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1242 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1243 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1244 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1245 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1246 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1247
1248 const extensions::PendingExtensionInfo* info;
1249 EXPECT_TRUE(
1250 (info = service()->pending_extension_manager()->GetById(good_crx)));
1251 EXPECT_EQ(ext_specifics->update_url(), info->update_url().spec());
1252 EXPECT_TRUE(info->is_from_sync());
1253 EXPECT_EQ(Manifest::INTERNAL, info->install_source());
1254 // TODO(akalin): Figure out a way to test |info.ShouldAllowInstall()|.
1255}
1256
1257TEST_F(ExtensionServiceSyncTest, ProcessSyncDataEnableDisable) {
1258 InitializeEmptyExtensionService();
1259 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361260 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141261 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1262 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581263
1264 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1265
1266 struct TestCase {
1267 const char* name; // For failure output only.
1268 // Set of disable reasons before any Sync data comes in. If this is != 0,
1269 // the extension is disabled.
1270 int previous_disable_reasons;
1271 bool sync_enable; // The enabled flag coming in from Sync.
1272 // The disable reason(s) coming in from Sync, or -1 for "not set".
1273 int sync_disable_reasons;
1274 // The expected set of disable reasons after processing the Sync update. The
1275 // extension should be disabled iff this is != 0.
1276 int expect_disable_reasons;
1277 } test_cases[] = {
1278 { "NopEnable", 0, true, 0, 0 },
1279 { "NopDisable", Extension::DISABLE_USER_ACTION, false,
1280 Extension::DISABLE_USER_ACTION, Extension::DISABLE_USER_ACTION },
treib29e1b9b12015-11-11 08:50:561281 { "Enable", Extension::DISABLE_USER_ACTION, true, 0, 0 },
treib9afc6212015-10-30 18:49:581282 { "Disable", 0, false, Extension::DISABLE_USER_ACTION,
1283 Extension::DISABLE_USER_ACTION },
treib9afc6212015-10-30 18:49:581284 { "AddDisableReason", Extension::DISABLE_REMOTE_INSTALL, false,
1285 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION,
1286 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION },
treib9afc6212015-10-30 18:49:581287 { "RemoveDisableReason",
1288 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION, false,
1289 Extension::DISABLE_USER_ACTION, Extension::DISABLE_USER_ACTION },
treib29e1b9b12015-11-11 08:50:561290 { "PreserveLocalDisableReason", Extension::DISABLE_RELOAD, true, 0,
1291 Extension::DISABLE_RELOAD },
1292 { "PreserveOnlyLocalDisableReason",
1293 Extension::DISABLE_USER_ACTION | Extension::DISABLE_RELOAD, true, 0,
1294 Extension::DISABLE_RELOAD },
1295
1296 // Interaction with Chrome clients <=M44, which don't sync disable_reasons
1297 // at all (any existing reasons are preserved).
1298 { "M44Enable", Extension::DISABLE_USER_ACTION, true, -1, 0 },
1299 // An M44 client enables an extension that had been disabled on a new
1300 // client. The disable reasons are still be there, but should be ignored.
1301 { "M44ReEnable", Extension::DISABLE_USER_ACTION, true,
1302 Extension::DISABLE_USER_ACTION, 0 },
1303 { "M44Disable", 0, false, -1, Extension::DISABLE_USER_ACTION },
1304 { "M44ReDisable", 0, false, 0, Extension::DISABLE_USER_ACTION },
1305 { "M44AlreadyDisabledByUser", Extension::DISABLE_USER_ACTION, false, -1,
1306 Extension::DISABLE_USER_ACTION},
1307 { "M44AlreadyDisabledWithOtherReason", Extension::DISABLE_REMOTE_INSTALL,
1308 false, -1,
1309 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION },
treib9afc6212015-10-30 18:49:581310 };
1311
1312 for (const TestCase& test_case : test_cases) {
1313 SCOPED_TRACE(test_case.name);
1314
1315 std::string id;
1316 std::string version;
1317 // Don't keep |extension| around longer than necessary.
1318 {
1319 const Extension* extension =
1320 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1321 // The extension should now be installed and enabled.
1322 ASSERT_TRUE(extension);
1323 id = extension->id();
1324 version = extension->VersionString();
1325 }
1326 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1327
1328 // Disable it if the test case says so.
1329 if (test_case.previous_disable_reasons) {
1330 service()->DisableExtension(id, test_case.previous_disable_reasons);
1331 ASSERT_TRUE(registry()->disabled_extensions().Contains(id));
1332 }
1333
1334 // Now a sync update comes in.
1335 sync_pb::EntitySpecifics specifics;
1336 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1337 ext_specifics->set_id(id);
1338 ext_specifics->set_enabled(test_case.sync_enable);
1339 ext_specifics->set_version(version);
1340 if (test_case.sync_disable_reasons != -1)
1341 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1342
treib65f103042015-12-03 10:21:361343 SyncChangeList list =
1344 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1345
treib9afc6212015-10-30 18:49:581346 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1347
1348 // Check expectations.
1349 const bool expect_enabled = !test_case.expect_disable_reasons;
1350 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1351 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
1352
1353 // Remove the extension again, so we can install it again for the next case.
1354 UninstallExtension(id, false, expect_enabled ? Extension::ENABLED
1355 : Extension::DISABLED);
1356 }
1357}
1358
1359TEST_F(ExtensionServiceSyncTest, ProcessSyncDataDeferredEnable) {
1360 InitializeEmptyExtensionService();
1361 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361362 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141363 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1364 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581365
1366 base::FilePath base_path = data_dir().AppendASCII("permissions_increase");
1367 base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1368
1369 base::FilePath path = base_path.AppendASCII("v1");
1370 const Extension* extension = PackAndInstallCRX(path, pem_path, INSTALL_NEW);
1371 // The extension must now be installed and enabled.
1372 ASSERT_TRUE(extension);
1373 ASSERT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
1374
1375 // Save the id, as the extension object will be destroyed during updating.
1376 std::string id = extension->id();
1377
1378 // Update to a new version with increased permissions.
1379 path = base_path.AppendASCII("v2");
1380 PackCRXAndUpdateExtension(id, path, pem_path, DISABLED);
1381
1382 // Now a sync update comes in, telling us to re-enable a *newer* version.
1383 sync_pb::EntitySpecifics specifics;
1384 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1385 ext_specifics->set_id(id);
1386 ext_specifics->set_version("3");
1387 ext_specifics->set_enabled(true);
1388 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
1389
treib65f103042015-12-03 10:21:361390 SyncChangeList list =
1391 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1392
treib9afc6212015-10-30 18:49:581393 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1394
1395 // Since the version didn't match, the extension should still be disabled.
1396 EXPECT_TRUE(registry()->disabled_extensions().Contains(id));
1397
1398 // After we update to the matching version, the extension should get enabled.
1399 path = base_path.AppendASCII("v3");
1400 PackCRXAndUpdateExtension(id, path, pem_path, ENABLED);
1401}
1402
1403TEST_F(ExtensionServiceSyncTest, ProcessSyncDataPermissionApproval) {
1404 // This is the update URL specified in the test extension. Setting it here is
1405 // necessary to make it considered syncable.
1406 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1407 switches::kAppsGalleryUpdateURL,
1408 "http://localhost/autoupdate/updates.xml");
1409
1410 InitializeEmptyExtensionService();
1411 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361412 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141413 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1414 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581415
1416 const base::FilePath base_path =
1417 data_dir().AppendASCII("permissions_increase");
1418 const base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1419 const base::FilePath path_v1 = base_path.AppendASCII("v1");
1420 const base::FilePath path_v2 = base_path.AppendASCII("v2");
1421
1422 base::ScopedTempDir crx_dir;
1423 ASSERT_TRUE(crx_dir.CreateUniqueTempDir());
vabr9142fe22016-09-08 13:19:221424 const base::FilePath crx_path_v1 = crx_dir.GetPath().AppendASCII("temp1.crx");
treib9afc6212015-10-30 18:49:581425 PackCRX(path_v1, pem_path, crx_path_v1);
vabr9142fe22016-09-08 13:19:221426 const base::FilePath crx_path_v2 = crx_dir.GetPath().AppendASCII("temp2.crx");
treib9afc6212015-10-30 18:49:581427 PackCRX(path_v2, pem_path, crx_path_v2);
1428
1429 const std::string v1("1");
1430 const std::string v2("2");
1431
1432 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1433
1434 struct TestCase {
1435 const char* name; // For failure output only.
1436 const std::string& sync_version; // The version coming in from Sync.
1437 // The disable reason(s) coming in from Sync, or -1 for "not set".
1438 int sync_disable_reasons;
1439 // The expected set of disable reasons after processing the Sync update. The
1440 // extension should be enabled iff this is 0.
1441 int expect_disable_reasons;
1442 // Whether the extension's permissions should be auto-granted.
1443 bool expect_permissions_granted;
1444 } test_cases[] = {
1445 // Sync tells us to re-enable an older version. No permissions should be
1446 // granted, since we can't be sure if the user actually approved the right
1447 // set of permissions.
1448 { "OldVersion", v1, 0, Extension::DISABLE_PERMISSIONS_INCREASE, false },
1449 // Legacy case: Sync tells us to re-enable the extension, but doesn't
1450 // specify disable reasons. No permissions should be granted.
1451 { "Legacy", v2, -1, Extension::DISABLE_PERMISSIONS_INCREASE, false },
1452 // Sync tells us to re-enable the extension and explicitly removes the
1453 // disable reasons. Now the extension should have its permissions granted.
1454 { "GrantPermissions", v2, 0, Extension::DISABLE_NONE, true },
1455 };
1456
1457 for (const TestCase& test_case : test_cases) {
1458 SCOPED_TRACE(test_case.name);
1459
1460 std::string id;
1461 // Don't keep |extension| around longer than necessary (it'll be destroyed
1462 // during updating).
1463 {
1464 const Extension* extension = InstallCRX(crx_path_v1, INSTALL_NEW);
1465 // The extension should now be installed and enabled.
1466 ASSERT_TRUE(extension);
1467 ASSERT_EQ(v1, extension->VersionString());
1468 id = extension->id();
1469 }
1470 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1471
dchengc963c7142016-04-08 03:55:221472 std::unique_ptr<const PermissionSet> granted_permissions_v1 =
treib9afc6212015-10-30 18:49:581473 prefs->GetGrantedPermissions(id);
1474
1475 // Update to a new version with increased permissions.
1476 UpdateExtension(id, crx_path_v2, DISABLED);
1477
1478 // Now the extension should be disabled due to a permissions increase.
1479 {
1480 const Extension* extension =
1481 registry()->disabled_extensions().GetByID(id);
1482 ASSERT_TRUE(extension);
1483 ASSERT_EQ(v2, extension->VersionString());
1484 }
1485 ASSERT_TRUE(prefs->HasDisableReason(
1486 id, Extension::DISABLE_PERMISSIONS_INCREASE));
1487
1488 // No new permissions should have been granted.
dchengc963c7142016-04-08 03:55:221489 std::unique_ptr<const PermissionSet> granted_permissions_v2 =
treib9afc6212015-10-30 18:49:581490 prefs->GetGrantedPermissions(id);
1491 ASSERT_EQ(*granted_permissions_v1, *granted_permissions_v2);
1492
1493 // Now a sync update comes in.
1494 sync_pb::EntitySpecifics specifics;
1495 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1496 ext_specifics->set_id(id);
1497 ext_specifics->set_enabled(true);
1498 ext_specifics->set_version(test_case.sync_version);
1499 if (test_case.sync_disable_reasons != -1)
1500 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1501
treib65f103042015-12-03 10:21:361502 SyncChangeList list =
1503 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1504
treib9afc6212015-10-30 18:49:581505 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1506
1507 // Check expectations.
1508 const bool expect_enabled = !test_case.expect_disable_reasons;
1509 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1510 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
dchengc963c7142016-04-08 03:55:221511 std::unique_ptr<const PermissionSet> granted_permissions =
treib9afc6212015-10-30 18:49:581512 prefs->GetGrantedPermissions(id);
1513 if (test_case.expect_permissions_granted) {
dchengc963c7142016-04-08 03:55:221514 std::unique_ptr<const PermissionSet> active_permissions =
treib9afc6212015-10-30 18:49:581515 prefs->GetActivePermissions(id);
1516 EXPECT_EQ(*granted_permissions, *active_permissions);
1517 } else {
1518 EXPECT_EQ(*granted_permissions, *granted_permissions_v1);
1519 }
1520
1521 // Remove the extension again, so we can install it again for the next case.
1522 UninstallExtension(id, false, expect_enabled ? Extension::ENABLED
1523 : Extension::DISABLED);
1524 }
1525}
1526
treib227b2582015-12-09 09:28:261527// Regression test for crbug.com/558299
1528TEST_F(ExtensionServiceSyncTest, DontSyncThemes) {
1529 InitializeEmptyExtensionService();
1530
1531 // The user has enabled sync.
maxboguefe00952a2016-01-19 19:02:011532 ProfileSyncServiceFactory::GetForProfile(profile())->SetFirstSetupComplete();
treib227b2582015-12-09 09:28:261533 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
1534 extension_sync_service();
1535
1536 service()->Init();
1537 ASSERT_TRUE(service()->is_ready());
1538
1539 syncer::FakeSyncChangeProcessor* processor =
1540 new syncer::FakeSyncChangeProcessor;
1541 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:221542 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
1543 base::WrapUnique(new syncer::SyncErrorFactoryMock));
treib227b2582015-12-09 09:28:261544
1545 processor->changes().clear();
1546
1547 // Sanity check: Installing an extension should result in a sync change.
1548 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1549 EXPECT_EQ(1u, processor->changes().size());
1550
1551 processor->changes().clear();
1552
1553 // Installing a theme should not result in a sync change (themes are handled
1554 // separately by ThemeSyncableService).
1555 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
1556 EXPECT_TRUE(processor->changes().empty());
1557}
1558
treib9afc6212015-10-30 18:49:581559#if defined(ENABLE_SUPERVISED_USERS)
1560
1561class ExtensionServiceTestSupervised : public ExtensionServiceSyncTest,
1562 public SupervisedUserService::Delegate {
1563 public:
treibb6af28cd2015-12-01 11:19:461564 ExtensionServiceTestSupervised()
robliao79393ffb2016-09-21 18:45:291565 : field_trial_list_(base::MakeUnique<base::MockEntropyProvider>()) {}
treibb6af28cd2015-12-01 11:19:461566
treib9afc6212015-10-30 18:49:581567 void SetUp() override {
1568 ExtensionServiceSyncTest::SetUp();
1569
1570 // This is the update URL specified in the permissions test extension.
1571 // Setting it here is necessary to make the extension considered syncable.
1572 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1573 switches::kAppsGalleryUpdateURL,
1574 "http://localhost/autoupdate/updates.xml");
1575 }
1576
1577 void TearDown() override {
1578 supervised_user_service()->SetDelegate(nullptr);
1579
1580 ExtensionServiceSyncTest::TearDown();
1581 }
1582
1583 protected:
mamire9609642016-06-28 22:17:541584 void InitSupervisedUserInitiatedExtensionInstallFeature(bool enabled) {
1585 base::FeatureList::ClearInstanceForTesting();
1586 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
1587 if (enabled) {
1588 feature_list->InitializeFromCommandLine(
1589 "SupervisedUserInitiatedExtensionInstall", std::string());
1590 }
1591 base::FeatureList::SetInstance(std::move(feature_list));
1592 }
1593
mamirf7715a2a2016-07-04 13:05:081594 bool IsPendingCustodianApproval(const std::string& extension_id) {
1595 auto function = make_scoped_refptr(
1596 new WebstorePrivateIsPendingCustodianApprovalFunction());
1597
1598 std::unique_ptr<base::Value> result(RunFunctionAndReturnSingleResult(
1599 function.get(), "[\"" + extension_id + "\"]", browser_context()));
1600
1601 bool copy_bool_result = false;
1602 EXPECT_TRUE(result->GetAsBoolean(&copy_bool_result));
1603 return copy_bool_result;
1604 }
1605
treib9afc6212015-10-30 18:49:581606 void InitServices(bool profile_is_supervised) {
1607 ExtensionServiceInitParams params = CreateDefaultInitParams();
1608 params.profile_is_supervised = profile_is_supervised;
mamire9609642016-06-28 22:17:541609 // If profile is supervised, don't pass a pref file such that the testing
1610 // profile creates a pref service that uses SupervisedUserPrefStore.
1611 if (profile_is_supervised) {
1612 params.pref_file = base::FilePath();
1613 }
treib9afc6212015-10-30 18:49:581614 InitializeExtensionService(params);
asargente48ab752016-03-12 00:59:201615 StartSyncing(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581616
1617 supervised_user_service()->SetDelegate(this);
1618 supervised_user_service()->Init();
1619 }
1620
mamire9609642016-06-28 22:17:541621 std::string InstallPermissionsTestExtension(bool by_custodian) {
1622 return InstallTestExtension(permissions_increase, dir_path("1"), pem_path(),
1623 by_custodian);
treib9afc6212015-10-30 18:49:581624 }
1625
1626 void UpdatePermissionsTestExtension(const std::string& id,
1627 const std::string& version,
1628 UpdateState expected_state) {
mamire9609642016-06-28 22:17:541629 UpdateTestExtension(dir_path(version), pem_path(), id, version,
1630 expected_state);
1631 }
1632
1633 std::string InstallNoPermissionsTestExtension(bool by_custodian) {
1634 base::FilePath base_path = data_dir().AppendASCII("autoupdate");
1635 base::FilePath pem_path = base_path.AppendASCII("key.pem");
1636 base::FilePath dir_path = base_path.AppendASCII("v1");
1637
1638 return InstallTestExtension(autoupdate, dir_path, pem_path, by_custodian);
1639 }
1640
1641 void UpdateNoPermissionsTestExtension(const std::string& id,
1642 const std::string& version,
1643 UpdateState expected_state) {
1644 base::FilePath base_path = data_dir().AppendASCII("autoupdate");
1645 base::FilePath pem_path = base_path.AppendASCII("key.pem");
1646 base::FilePath dir_path = base_path.AppendASCII("v" + version);
1647
1648 UpdateTestExtension(dir_path, pem_path, id, version, expected_state);
1649 }
1650
1651 std::string InstallTestExtension(const std::string& id,
1652 const base::FilePath& dir_path,
1653 const base::FilePath& pem_path,
1654 bool by_custodian) {
1655 InstallState expected_state = INSTALL_WITHOUT_LOAD;
1656 if (by_custodian) {
1657 extensions::util::SetWasInstalledByCustodian(id, profile(), true);
1658 expected_state = INSTALL_NEW;
1659 }
1660 const Extension* extension =
1661 PackAndInstallCRX(dir_path, pem_path, expected_state);
1662 // The extension must now be installed.
1663 EXPECT_TRUE(extension);
1664 EXPECT_EQ(extension->id(), id);
1665 if (by_custodian) {
1666 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1667 } else {
1668 CheckDisabledForCustodianApproval(id);
1669 }
1670
1671 EXPECT_EQ(*extension->version(), base::Version("1"));
1672
1673 return id;
1674 }
1675
1676 void UpdateTestExtension(const base::FilePath& dir_path,
1677 const base::FilePath& pem_path,
1678 const std::string& id,
1679 const std::string& version,
1680 const UpdateState& expected_state) {
1681 PackCRXAndUpdateExtension(id, dir_path, pem_path, expected_state);
treib9afc6212015-10-30 18:49:581682 const Extension* extension = registry()->GetInstalledExtension(id);
1683 ASSERT_TRUE(extension);
1684 // The version should have been updated.
mamire9609642016-06-28 22:17:541685 EXPECT_EQ(*extension->version(), base::Version(version));
1686 }
1687
1688 // Simulate a custodian approval for enabling the extension coming in
1689 // through Sync by adding the approved version to the map of approved
1690 // extensions. It doesn't simulate a change in the disable reasons.
1691 void SimulateCustodianApprovalChangeViaSync(const std::string& extension_id,
1692 const std::string& version,
1693 SyncChange::SyncChangeType type) {
1694 std::string key = SupervisedUserSettingsService::MakeSplitSettingKey(
1695 supervised_users::kApprovedExtensions, extension_id);
1696 syncer::SyncData sync_data =
1697 SupervisedUserSettingsService::CreateSyncDataForSetting(
1698 key, base::StringValue(version));
1699
1700 SyncChangeList list(1, SyncChange(FROM_HERE, type, sync_data));
1701
1702 SupervisedUserSettingsService* supervised_user_settings_service =
1703 SupervisedUserSettingsServiceFactory::GetForProfile(profile());
1704 supervised_user_settings_service->ProcessSyncChanges(FROM_HERE, list);
1705 }
1706
1707 void CheckDisabledForCustodianApproval(const std::string& extension_id) {
1708 EXPECT_TRUE(registry()->disabled_extensions().Contains(extension_id));
1709 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile());
1710 EXPECT_TRUE(extension_prefs->HasDisableReason(
1711 extension_id,
1712 extensions::Extension::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
treib9afc6212015-10-30 18:49:581713 }
1714
1715 SupervisedUserService* supervised_user_service() {
1716 return SupervisedUserServiceFactory::GetForProfile(profile());
1717 }
1718
mamire9609642016-06-28 22:17:541719 static std::string RequestId(const std::string& extension_id,
1720 const std::string& version) {
1721 return SupervisedUserService::GetExtensionRequestId(
treib9afc6212015-10-30 18:49:581722 extension_id, base::Version(version));
1723 }
1724
1725 private:
1726 // This prevents the legacy supervised user init code from running.
1727 bool SetActive(bool active) override { return true; }
1728
1729 base::FilePath base_path() const {
1730 return data_dir().AppendASCII("permissions_increase");
1731 }
1732 base::FilePath dir_path(const std::string& version) const {
1733 return base_path().AppendASCII("v" + version);
1734 }
1735 base::FilePath pem_path() const {
1736 return base_path().AppendASCII("permissions.pem");
1737 }
treibb6af28cd2015-12-01 11:19:461738
1739 base::FieldTrialList field_trial_list_;
treib9afc6212015-10-30 18:49:581740};
1741
1742class MockPermissionRequestCreator : public PermissionRequestCreator {
1743 public:
1744 MockPermissionRequestCreator() {}
1745 ~MockPermissionRequestCreator() override {}
1746
1747 bool IsEnabled() const override { return true; }
1748
1749 void CreateURLAccessRequest(const GURL& url_requested,
1750 const SuccessCallback& callback) override {
1751 FAIL();
1752 }
1753
mamire9609642016-06-28 22:17:541754 MOCK_METHOD2(CreateExtensionInstallRequest,
1755 void(const std::string& id,
1756 const SupervisedUserService::SuccessCallback& callback));
1757
treib9afc6212015-10-30 18:49:581758 MOCK_METHOD2(CreateExtensionUpdateRequest,
1759 void(const std::string& id,
1760 const SupervisedUserService::SuccessCallback& callback));
1761
1762 private:
1763 DISALLOW_COPY_AND_ASSIGN(MockPermissionRequestCreator);
1764};
1765
1766TEST_F(ExtensionServiceTestSupervised, InstallOnlyAllowedByCustodian) {
1767 InitServices(true /* profile_is_supervised */);
mamire9609642016-06-28 22:17:541768 InitSupervisedUserInitiatedExtensionInstallFeature(false);
treib9afc6212015-10-30 18:49:581769
mamir192d7882016-06-22 17:10:161770 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
1771
treib9afc6212015-10-30 18:49:581772 base::FilePath path1 = data_dir().AppendASCII("good.crx");
1773 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
1774 const Extension* extensions[] = {
1775 InstallCRX(path1, INSTALL_FAILED),
mamir192d7882016-06-22 17:10:161776 InstallCRX(path2, INSTALL_NEW)
treib9afc6212015-10-30 18:49:581777 };
1778
1779 // Only the extension with the "installed by custodian" flag should have been
1780 // installed and enabled.
1781 EXPECT_FALSE(extensions[0]);
1782 ASSERT_TRUE(extensions[1]);
1783 EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id()));
mamirf7715a2a2016-07-04 13:05:081784 EXPECT_FALSE(IsPendingCustodianApproval(extensions[1]->id()));
treib9afc6212015-10-30 18:49:581785}
1786
mamir192d7882016-06-22 17:10:161787TEST_F(ExtensionServiceTestSupervised,
1788 DelegatedAndPreinstalledExtensionIsSUFirst) {
1789 InitServices(false /* profile_is_supervised */);
mamire9609642016-06-28 22:17:541790 InitSupervisedUserInitiatedExtensionInstallFeature(false);
mamir192d7882016-06-22 17:10:161791
1792 // Install an extension.
1793 base::FilePath path = data_dir().AppendASCII("good.crx");
1794 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1795 std::string id = extension->id();
1796 const std::string version("1.0.0.0");
1797 // It should be enabled.
1798 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1799
1800 // Now make the profile supervised.
1801 profile()->AsTestingProfile()->SetSupervisedUserId(
1802 supervised_users::kChildAccountSUID);
1803
1804 // It should not be enabled now (it is not loaded at all actually).
1805 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
1806
1807 // Simulate data sync with the "was_installed_by_custodian" flag set to 1.
1808 sync_pb::EntitySpecifics specifics;
1809 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1810 ext_specifics->set_id(id);
1811 ext_specifics->set_enabled(true);
1812 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
1813 ext_specifics->set_installed_by_custodian(true);
1814 ext_specifics->set_version(version);
1815
1816 SyncChangeList list =
1817 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
1818
1819 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1820
1821 // The extension should be enabled again.
1822 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1823 EXPECT_TRUE(extensions::util::WasInstalledByCustodian(id, profile()));
1824}
1825
1826TEST_F(ExtensionServiceTestSupervised,
1827 DelegatedAndPreinstalledExtensionSyncFirst) {
1828 InitServices(false /* profile_is_supervised */);
mamire9609642016-06-28 22:17:541829 InitSupervisedUserInitiatedExtensionInstallFeature(false);
mamir192d7882016-06-22 17:10:161830
1831 // Install an extension.
1832 base::FilePath path = data_dir().AppendASCII("good.crx");
1833 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1834 std::string id = extension->id();
1835 const std::string version("1.0.0.0");
1836
1837 // It should be enabled.
1838 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1839
1840 // Simulate data sync with the "was_installed_by_custodian" flag set to 1.
1841 sync_pb::EntitySpecifics specifics;
1842 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1843 ext_specifics->set_id(id);
1844 ext_specifics->set_enabled(true);
1845 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
1846 ext_specifics->set_installed_by_custodian(true);
1847 ext_specifics->set_version(version);
1848
1849 SyncChangeList list =
1850 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
1851
1852 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
mamir192d7882016-06-22 17:10:161853 // The extension should be enabled.
1854 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1855 EXPECT_TRUE(extensions::util::WasInstalledByCustodian(id, profile()));
1856}
1857
mamire9609642016-06-28 22:17:541858TEST_F(ExtensionServiceTestSupervised,
1859 InstallAllowedByCustodianAndSupervisedUser) {
1860 InitServices(true /* profile_is_supervised */);
1861 InitSupervisedUserInitiatedExtensionInstallFeature(true);
1862
1863 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
1864
1865 base::FilePath path1 = data_dir().AppendASCII("good.crx");
1866 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
1867 const Extension* extensions[] = {
1868 InstallCRX(path1, INSTALL_WITHOUT_LOAD),
1869 InstallCRX(path2, INSTALL_NEW)
1870 };
1871
1872 // Only the extension with the "installed by custodian" flag should have been
1873 // installed and enabled.
1874 // The extension missing the "installed by custodian" flag is a
1875 // supervised user initiated install and hence not enabled.
1876 ASSERT_TRUE(extensions[0]);
1877 ASSERT_TRUE(extensions[1]);
1878 EXPECT_TRUE(registry()->disabled_extensions().Contains(extensions[0]->id()));
mamirf7715a2a2016-07-04 13:05:081879 EXPECT_TRUE(IsPendingCustodianApproval(extensions[0]->id()));
mamire9609642016-06-28 22:17:541880 EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id()));
mamirf7715a2a2016-07-04 13:05:081881 EXPECT_FALSE(IsPendingCustodianApproval(extensions[1]->id()));
mamire9609642016-06-28 22:17:541882}
1883
1884TEST_F(ExtensionServiceTestSupervised,
1885 PreinstalledExtensionWithSUInitiatedInstalls) {
1886 InitServices(false /* profile_is_supervised */);
1887 InitSupervisedUserInitiatedExtensionInstallFeature(true);
1888
1889 // Install an extension.
1890 base::FilePath path = data_dir().AppendASCII("good.crx");
1891 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1892 std::string id = extension->id();
1893 // Make sure it's enabled.
1894 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1895
1896 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1897 supervised_user_service()->AddPermissionRequestCreator(
1898 base::WrapUnique(creator));
1899 const std::string version("1.0.0.0");
1900
1901 EXPECT_CALL(*creator, CreateExtensionInstallRequest(
1902 RequestId(good_crx, version), testing::_));
1903
1904 // Now make the profile supervised.
1905 profile()->AsTestingProfile()->SetSupervisedUserId(
1906 supervised_users::kChildAccountSUID);
1907
1908 Mock::VerifyAndClearExpectations(creator);
1909
1910 // The extension should not be enabled anymore.
1911 CheckDisabledForCustodianApproval(id);
mamirf7715a2a2016-07-04 13:05:081912 EXPECT_TRUE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:541913}
1914
1915TEST_F(ExtensionServiceTestSupervised,
1916 PreinstalledExtensionWithoutSUInitiatedInstalls) {
1917 InitServices(false /* profile_is_supervised */);
1918 InitSupervisedUserInitiatedExtensionInstallFeature(false);
1919
1920 // Install an extension.
1921 base::FilePath path = data_dir().AppendASCII("good.crx");
1922 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1923 std::string id = extension->id();
1924
1925 // Make sure it's enabled.
1926 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1927
1928 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1929 supervised_user_service()->AddPermissionRequestCreator(
1930 base::WrapUnique(creator));
1931 const std::string version("1.0.0.0");
1932
1933 // No request should be sent because supervised user initiated installs
1934 // are disabled.
1935 EXPECT_CALL(*creator, CreateExtensionInstallRequest(testing::_, testing::_))
1936 .Times(0);
1937
1938 // Now make the profile supervised.
1939 profile()->AsTestingProfile()->SetSupervisedUserId(
1940 supervised_users::kChildAccountSUID);
1941
1942 // The extension should not be loaded anymore.
1943 EXPECT_FALSE(registry()->GetInstalledExtension(id));
1944}
1945
1946TEST_F(ExtensionServiceTestSupervised, ExtensionApprovalBeforeInstallation) {
1947 // This tests the case when the sync entity flagging the extension as approved
1948 // arrives before the extension itself is installed.
1949 InitServices(true /* profile_is_supervised */);
1950 InitSupervisedUserInitiatedExtensionInstallFeature(true);
1951
1952 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1953 supervised_user_service()->AddPermissionRequestCreator(
1954 base::WrapUnique(creator));
1955
1956 std::string id = good_crx;
1957 std::string version("1.0.0.0");
1958
1959 SimulateCustodianApprovalChangeViaSync(id, version, SyncChange::ACTION_ADD);
1960
1961 // Now install an extension.
1962 base::FilePath path = data_dir().AppendASCII("good.crx");
1963 InstallCRX(path, INSTALL_NEW);
1964
1965 // No approval request should be sent.
1966 EXPECT_CALL(*creator, CreateExtensionInstallRequest(testing::_, testing::_))
1967 .Times(0);
1968
1969 // Make sure it's enabled.
1970 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:081971 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:541972}
1973
treib9afc6212015-10-30 18:49:581974TEST_F(ExtensionServiceTestSupervised, UpdateWithoutPermissionIncrease) {
1975 InitServices(true /* profile_is_supervised */);
1976
treib9afc6212015-10-30 18:49:581977 // Save the id, as the extension object will be destroyed during updating.
mamire9609642016-06-28 22:17:541978 std::string id = InstallNoPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:581979
1980 // Update to a new version.
mamire9609642016-06-28 22:17:541981 std::string version2("2");
1982 UpdateNoPermissionsTestExtension(id, version2, ENABLED);
treib9afc6212015-10-30 18:49:581983
1984 // The extension should still be there and enabled.
mamire9609642016-06-28 22:17:541985 const Extension* extension = registry()->enabled_extensions().GetByID(id);
treib9afc6212015-10-30 18:49:581986 ASSERT_TRUE(extension);
1987 // The version should have changed.
mamire9609642016-06-28 22:17:541988 EXPECT_EQ(*extension->version(), base::Version(version2));
mamirf7715a2a2016-07-04 13:05:081989 EXPECT_FALSE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:581990}
1991
treib9afc6212015-10-30 18:49:581992TEST_F(ExtensionServiceTestSupervised,
1993 UpdateWithPermissionIncreaseApprovalOldVersion) {
treib9afc6212015-10-30 18:49:581994 InitServices(true /* profile_is_supervised */);
1995
1996 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1997 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:221998 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:581999
2000 const std::string version1("1");
2001 const std::string version2("2");
2002
mamire9609642016-06-28 22:17:542003 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582004
2005 // Update to a new version with increased permissions.
2006 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542007 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582008 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542009 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082010 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582011
2012 // Simulate a custodian approval for re-enabling the extension coming in
2013 // through Sync, but set the old version. This can happen when there already
2014 // was a pending request for an earlier version of the extension.
2015 sync_pb::EntitySpecifics specifics;
2016 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2017 ext_specifics->set_id(id);
2018 ext_specifics->set_enabled(true);
2019 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
2020 ext_specifics->set_installed_by_custodian(true);
2021 ext_specifics->set_version(version1);
2022
2023 // Attempting to re-enable an old version should result in a permission
2024 // request for the current version.
2025 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542026 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582027
treib65f103042015-12-03 10:21:362028 SyncChangeList list =
2029 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2030
2031 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582032 // The re-enable should be ignored, since the version doesn't match.
2033 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2034 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
2035 id, base::Version(version1)));
2036 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
2037 id, base::Version(version2)));
mamire9609642016-06-28 22:17:542038 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082039 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582040}
2041
2042TEST_F(ExtensionServiceTestSupervised,
2043 UpdateWithPermissionIncreaseApprovalMatchingVersion) {
treib9afc6212015-10-30 18:49:582044 InitServices(true /* profile_is_supervised */);
2045
2046 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2047 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222048 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582049
mamire9609642016-06-28 22:17:542050 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582051
2052 // Update to a new version with increased permissions.
2053 const std::string version2("2");
2054 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542055 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582056 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542057 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082058 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582059
2060 // Simulate a custodian approval for re-enabling the extension coming in
2061 // through Sync.
2062 sync_pb::EntitySpecifics specifics;
2063 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2064 ext_specifics->set_id(id);
2065 ext_specifics->set_enabled(true);
2066 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
2067 ext_specifics->set_installed_by_custodian(true);
2068 ext_specifics->set_version(version2);
2069
treib65f103042015-12-03 10:21:362070 SyncChangeList list =
2071 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2072
2073 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582074 // The extension should have gotten re-enabled.
2075 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082076 EXPECT_FALSE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582077}
2078
2079TEST_F(ExtensionServiceTestSupervised,
2080 UpdateWithPermissionIncreaseApprovalNewVersion) {
treib9afc6212015-10-30 18:49:582081 InitServices(true /* profile_is_supervised */);
2082
2083 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2084 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222085 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582086
mamire9609642016-06-28 22:17:542087 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582088
2089 // Update to a new version with increased permissions.
2090 const std::string version2("2");
2091 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542092 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582093 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542094 Mock::VerifyAndClearExpectations(creator);
treib9afc6212015-10-30 18:49:582095
2096 // Simulate a custodian approval for re-enabling the extension coming in
2097 // through Sync. Set a newer version than we have installed.
2098 const std::string version3("3");
2099 sync_pb::EntitySpecifics specifics;
2100 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2101 ext_specifics->set_id(id);
2102 ext_specifics->set_enabled(true);
2103 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
2104 ext_specifics->set_installed_by_custodian(true);
2105 ext_specifics->set_version(version3);
2106
2107 // This should *not* result in a new permission request.
2108 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542109 RequestId(id, version3), testing::_))
treib9afc6212015-10-30 18:49:582110 .Times(0);
2111
treib65f103042015-12-03 10:21:362112 SyncChangeList list =
2113 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2114
2115 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582116 // The re-enable should be delayed until the extension is updated to the
2117 // matching version.
2118 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2119 EXPECT_TRUE(extension_sync_service()->HasPendingReenable(
2120 id, base::Version(version3)));
2121
2122 // Update to the matching version. Now the extension should get enabled.
2123 UpdatePermissionsTestExtension(id, version3, ENABLED);
2124}
2125
mamire9609642016-06-28 22:17:542126TEST_F(ExtensionServiceTestSupervised, SupervisedUserInitiatedInstalls) {
mamire9609642016-06-28 22:17:542127 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2128
2129 InitServices(true /* profile_is_supervised */);
2130
2131 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2132 supervised_user_service()->AddPermissionRequestCreator(
2133 base::WrapUnique(creator));
2134
2135 base::FilePath path = data_dir().AppendASCII("good.crx");
2136 std::string version("1.0.0.0");
2137
2138 EXPECT_CALL(*creator, CreateExtensionInstallRequest(
2139 RequestId(good_crx, version), testing::_));
2140
2141 // Should be installed but disabled, a request for approval should be sent.
2142 const Extension* extension = InstallCRX(path, INSTALL_WITHOUT_LOAD);
2143 ASSERT_TRUE(extension);
2144 ASSERT_EQ(extension->id(), good_crx);
2145 EXPECT_TRUE(registry()->disabled_extensions().Contains(good_crx));
2146 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082147 EXPECT_TRUE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542148
2149 SimulateCustodianApprovalChangeViaSync(good_crx, version,
2150 SyncChange::ACTION_ADD);
2151
2152 // The extension should be enabled now.
2153 EXPECT_TRUE(registry()->enabled_extensions().Contains(good_crx));
mamirf7715a2a2016-07-04 13:05:082154 EXPECT_FALSE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542155
2156 // Simulate approval removal coming via Sync.
2157 SimulateCustodianApprovalChangeViaSync(good_crx, version,
2158 SyncChange::ACTION_DELETE);
2159
2160 // The extension should be disabled now.
2161 EXPECT_TRUE(registry()->disabled_extensions().Contains(good_crx));
mamirf7715a2a2016-07-04 13:05:082162 EXPECT_TRUE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542163}
2164
2165TEST_F(ExtensionServiceTestSupervised,
2166 UpdateSUInitiatedInstallWithoutPermissionIncrease) {
mamire9609642016-06-28 22:17:542167 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2168
2169 InitServices(true /* profile_is_supervised */);
2170
2171 std::string id = InstallNoPermissionsTestExtension(false /* by_custodian */);
2172 std::string version1("1");
2173
2174 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2175
2176 // The extension should be enabled now.
2177 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2178
2179 std::string version2("2");
2180
2181 // Update to a new version.
2182 UpdateNoPermissionsTestExtension(id, version2, ENABLED);
2183
2184 // The extension should still be there and enabled.
2185 const Extension* extension = registry()->enabled_extensions().GetByID(id);
2186 ASSERT_TRUE(extension);
2187 // The version should have increased.
2188 EXPECT_EQ(1, extension->version()->CompareTo(base::Version(version1)));
2189
2190 // Check that the approved version has been updated in the prefs as well.
2191 // Prefs are updated via Sync. If the prefs are updated, then the new
2192 // approved version has been pushed to Sync as well.
2193 std::string approved_version;
2194 PrefService* pref_service = profile()->GetPrefs();
2195 const base::DictionaryValue* approved_extensions =
2196 pref_service->GetDictionary(prefs::kSupervisedUserApprovedExtensions);
2197 approved_extensions->GetStringWithoutPathExpansion(id, &approved_version);
2198
2199 EXPECT_EQ(base::Version(approved_version), *extension->version());
mamirf7715a2a2016-07-04 13:05:082200 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542201}
2202
2203TEST_F(ExtensionServiceTestSupervised,
2204 UpdateSUInitiatedInstallWithPermissionIncrease) {
mamire9609642016-06-28 22:17:542205 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2206
2207 InitServices(true /* profile_is_supervised */);
2208
2209 std::string id = InstallPermissionsTestExtension(false /* by_custodian */);
2210 std::string version1("1");
2211
2212 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2213
2214 // The extension should be enabled now.
2215 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2216
2217 std::string version3("3");
2218
2219 UpdatePermissionsTestExtension(id, version3, DISABLED);
2220
2221 // The extension should be disabled.
2222 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2223 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
2224 id, Extension::DISABLE_PERMISSIONS_INCREASE));
2225
2226 std::string version2("2");
2227 // Approve an older version
2228 SimulateCustodianApprovalChangeViaSync(id, version2,
2229 SyncChange::ACTION_UPDATE);
2230
2231 // The extension should remain disabled.
2232 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2233 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
2234 id, Extension::DISABLE_PERMISSIONS_INCREASE));
2235 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
2236 id, Extension::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
2237
mamirf7715a2a2016-07-04 13:05:082238 EXPECT_TRUE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542239 // Approve the latest version
2240 SimulateCustodianApprovalChangeViaSync(id, version3,
2241 SyncChange::ACTION_UPDATE);
2242
2243 // The extension should be enabled again.
2244 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082245 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542246}
2247
2248TEST_F(ExtensionServiceTestSupervised,
2249 UpdateSUInitiatedInstallWithPermissionIncreaseApprovalArrivesFirst) {
mamire9609642016-06-28 22:17:542250 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2251
2252 InitServices(true /* profile_is_supervised */);
2253
2254 std::string id = InstallPermissionsTestExtension(false /* by_custodian */);
2255
2256 std::string version1("1");
2257 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2258
2259 // The extension should be enabled now.
2260 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2261
2262 std::string version2("2");
2263 // Approve a newer version
2264 SimulateCustodianApprovalChangeViaSync(id, version2,
2265 SyncChange::ACTION_UPDATE);
2266
2267 // The extension should be disabled.
2268 CheckDisabledForCustodianApproval(id);
2269
2270 // Now update the extension to the same version that was approved.
2271 UpdatePermissionsTestExtension(id, version2, ENABLED);
2272 // The extension should be enabled again.
2273 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082274 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542275}
2276
treib9afc6212015-10-30 18:49:582277TEST_F(ExtensionServiceSyncTest, SyncUninstallByCustodianSkipsPolicy) {
2278 InitializeEmptyExtensionService();
2279 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:362280 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:142281 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
2282 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:582283
mamir192d7882016-06-22 17:10:162284 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
treib9afc6212015-10-30 18:49:582285 // Install two extensions.
2286 base::FilePath path1 = data_dir().AppendASCII("good.crx");
2287 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
2288 const Extension* extensions[] = {
2289 InstallCRX(path1, INSTALL_NEW),
mamir192d7882016-06-22 17:10:162290 InstallCRX(path2, INSTALL_NEW)
treib9afc6212015-10-30 18:49:582291 };
2292
2293 // Add a policy provider that will disallow any changes.
2294 extensions::TestManagementPolicyProvider provider(
2295 extensions::TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS);
2296 ExtensionSystem::Get(
2297 browser_context())->management_policy()->RegisterProvider(&provider);
2298
2299 // Create a sync deletion for each extension.
treib65f103042015-12-03 10:21:362300 SyncChangeList list;
treib9afc6212015-10-30 18:49:582301 for (size_t i = 0; i < arraysize(extensions); i++) {
2302 const std::string& id = extensions[i]->id();
2303 sync_pb::EntitySpecifics specifics;
2304 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2305 ext_specifics->set_id(id);
2306 ext_specifics->set_version("1.0");
2307 ext_specifics->set_installed_by_custodian(
mamir192d7882016-06-22 17:10:162308 extensions::util::WasInstalledByCustodian(id, profile()));
2309
treib9afc6212015-10-30 18:49:582310 syncer::SyncData sync_data =
2311 syncer::SyncData::CreateLocalData(id, "Name", specifics);
treib65f103042015-12-03 10:21:362312 list.push_back(SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, sync_data));
treib9afc6212015-10-30 18:49:582313 }
2314
2315 // Save the extension ids, as uninstalling destroys the Extension instance.
2316 std::string extension_ids[] = {
2317 extensions[0]->id(),
2318 extensions[1]->id()
2319 };
2320
2321 // Now apply the uninstallations.
treib65f103042015-12-03 10:21:362322 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582323
2324 // Uninstalling the extension without installed_by_custodian should have been
2325 // blocked by policy, so it should still be there.
2326 EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_ids[0]));
2327
2328 // But installed_by_custodian should result in bypassing the policy check.
2329 EXPECT_FALSE(
2330 registry()->GenerateInstalledExtensionsSet()->Contains(extension_ids[1]));
2331}
2332
rdevlin.cronin738501d2015-11-05 21:51:362333TEST_F(ExtensionServiceSyncTest, SyncExtensionHasAllhostsWithheld) {
2334 InitializeEmptyExtensionService();
asargente48ab752016-03-12 00:59:202335 StartSyncing(syncer::EXTENSIONS);
rdevlin.cronin738501d2015-11-05 21:51:362336
2337 // Create an extension that needs all-hosts.
2338 const std::string kName("extension");
2339 scoped_refptr<const Extension> extension =
2340 extensions::ExtensionBuilder()
limasdf3d102542015-12-09 03:58:452341 .SetLocation(Manifest::INTERNAL)
dcheng794d2bd2016-02-27 03:51:322342 .SetManifest(
limasdf3d102542015-12-09 03:58:452343 extensions::DictionaryBuilder()
2344 .Set("name", kName)
2345 .Set("description", "foo")
2346 .Set("manifest_version", 2)
2347 .Set("version", "1.0")
2348 .Set("permissions",
dcheng794d2bd2016-02-27 03:51:322349 extensions::ListBuilder().Append("*://*/*").Build())
2350 .Build())
limasdf3d102542015-12-09 03:58:452351 .SetID(crx_file::id_util::GenerateId(kName))
2352 .Build();
rdevlin.cronin738501d2015-11-05 21:51:362353
2354 // Install and enable it.
2355 service()->AddExtension(extension.get());
2356 service()->GrantPermissionsAndEnableExtension(extension.get());
2357 const std::string id = extension->id();
2358 EXPECT_TRUE(registry()->enabled_extensions().GetByID(id));
2359
2360 // Simulate a sync node coming in where the extension had all-hosts withheld.
2361 // This means that it should have all-hosts withheld on this machine, too.
rdevlin.cronin738501d2015-11-05 21:51:362362 sync_pb::EntitySpecifics specifics;
2363 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2364 ext_specifics->set_id(id);
2365 ext_specifics->set_name(kName);
2366 ext_specifics->set_version("1.0");
2367 ext_specifics->set_all_urls_enabled(false);
2368 ext_specifics->set_enabled(true);
rdevlin.cronin738501d2015-11-05 21:51:362369
treib65f103042015-12-03 10:21:362370 SyncChangeList list =
2371 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2372
2373 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
rdevlin.cronin738501d2015-11-05 21:51:362374
rdevlin.cronind01837b2016-08-17 01:37:182375 const Extension* enabled_extension =
2376 registry()->enabled_extensions().GetByID(id);
2377 ASSERT_TRUE(enabled_extension);
2378 ScriptingPermissionsModifier modifier(profile(), enabled_extension);
2379 EXPECT_FALSE(modifier.IsAllowedOnAllUrls());
2380 EXPECT_TRUE(modifier.HasSetAllowedOnAllUrls());
rdevlin.cronin738501d2015-11-05 21:51:362381}
2382
treib9afc6212015-10-30 18:49:582383#endif // defined(ENABLE_SUPERVISED_USERS)
asargente48ab752016-03-12 00:59:202384
2385// Tests sync behavior in the case of an item that starts out as an app and
2386// gets updated to become an extension.
2387TEST_F(ExtensionServiceSyncTest, AppToExtension) {
2388 InitializeEmptyExtensionService();
2389 service()->Init();
2390 ASSERT_TRUE(service()->is_ready());
2391
2392 // Install v1, which is an app.
2393 const Extension* v1 =
2394 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v1.crx"),
2395 INSTALL_NEW);
2396 EXPECT_TRUE(v1->is_app());
2397 EXPECT_FALSE(v1->is_extension());
2398 std::string id = v1->id();
2399
2400 StatefulChangeProcessor extensions_processor(syncer::ModelType::EXTENSIONS);
2401 StatefulChangeProcessor apps_processor(syncer::ModelType::APPS);
2402 extension_sync_service()->MergeDataAndStartSyncing(
2403 syncer::EXTENSIONS, syncer::SyncDataList(),
2404 extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222405 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202406 extension_sync_service()->MergeDataAndStartSyncing(
2407 syncer::APPS, syncer::SyncDataList(), apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222408 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202409
2410 // Check the app/extension change processors to be sure the right data was
2411 // added.
2412 EXPECT_TRUE(extensions_processor.changes().empty());
2413 EXPECT_TRUE(extensions_processor.data().empty());
2414 EXPECT_EQ(1u, apps_processor.data().size());
2415 ASSERT_EQ(1u, apps_processor.changes().size());
2416 const SyncChange& app_change = apps_processor.changes()[0];
2417 EXPECT_EQ(SyncChange::ACTION_ADD, app_change.change_type());
dchengc963c7142016-04-08 03:55:222418 std::unique_ptr<ExtensionSyncData> app_data =
asargente48ab752016-03-12 00:59:202419 ExtensionSyncData::CreateFromSyncData(app_change.sync_data());
2420 EXPECT_TRUE(app_data->is_app());
2421 EXPECT_EQ(id, app_data->id());
2422 EXPECT_EQ(*v1->version(), app_data->version());
2423
2424 // Update the app to v2, which is an extension.
2425 const Extension* v2 =
2426 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v2.crx"),
2427 INSTALL_UPDATED);
2428 EXPECT_FALSE(v2->is_app());
2429 EXPECT_TRUE(v2->is_extension());
2430 EXPECT_EQ(id, v2->id());
2431
2432 // Make sure we saw an extension item added.
2433 ASSERT_EQ(1u, extensions_processor.changes().size());
2434 const SyncChange& extension_change = extensions_processor.changes()[0];
2435 EXPECT_EQ(SyncChange::ACTION_ADD, extension_change.change_type());
dchengc963c7142016-04-08 03:55:222436 std::unique_ptr<ExtensionSyncData> extension_data =
asargente48ab752016-03-12 00:59:202437 ExtensionSyncData::CreateFromSyncData(extension_change.sync_data());
2438 EXPECT_FALSE(extension_data->is_app());
2439 EXPECT_EQ(id, extension_data->id());
2440 EXPECT_EQ(*v2->version(), extension_data->version());
2441
2442 // Get the current data from the change processors to use as the input to
2443 // the following call to MergeDataAndStartSyncing. This simulates what should
2444 // happen with sync.
2445 syncer::SyncDataList extensions_data =
2446 extensions_processor.GetAllSyncData(syncer::EXTENSIONS);
2447 syncer::SyncDataList apps_data = apps_processor.GetAllSyncData(syncer::APPS);
2448
2449 // Stop syncing, then start again.
2450 extension_sync_service()->StopSyncing(syncer::EXTENSIONS);
2451 extension_sync_service()->StopSyncing(syncer::APPS);
2452 extension_sync_service()->MergeDataAndStartSyncing(
2453 syncer::EXTENSIONS, extensions_data, extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222454 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202455 extension_sync_service()->MergeDataAndStartSyncing(
2456 syncer::APPS, apps_data, apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222457 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202458
2459 // Make sure we saw an app item deleted.
2460 bool found_delete = false;
2461 for (const auto& change : apps_processor.changes()) {
2462 if (change.change_type() == SyncChange::ACTION_DELETE) {
dchengc963c7142016-04-08 03:55:222463 std::unique_ptr<ExtensionSyncData> data =
asargente48ab752016-03-12 00:59:202464 ExtensionSyncData::CreateFromSyncChange(change);
2465 if (data->id() == id) {
2466 found_delete = true;
2467 break;
2468 }
2469 }
2470 }
2471 EXPECT_TRUE(found_delete);
2472
2473 // Make sure there is one extension, and there are no more apps.
2474 EXPECT_EQ(1u, extensions_processor.data().size());
2475 EXPECT_TRUE(apps_processor.data().empty());
2476}