blob: 551eab90a8b0461a44f190e4cad8cabac226a37e [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"
blundell7282b512015-11-09 07:21:1135#include "components/browser_sync/browser/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.
306 ProfileSyncService* sync_service =
307 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.
348 ProfileSyncService* sync_service =
349 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());
1424 const base::FilePath crx_path_v1 = crx_dir.path().AppendASCII("temp1.crx");
1425 PackCRX(path_v1, pem_path, crx_path_v1);
1426 const base::FilePath crx_path_v2 = crx_dir.path().AppendASCII("temp2.crx");
1427 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()
1565 : field_trial_list_(new base::MockEntropyProvider()) {}
1566
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:
treibb6af28cd2015-12-01 11:19:461584 void InitNeedCustodianApprovalFieldTrial(bool enabled) {
1585 // Group name doesn't matter.
1586 base::FieldTrialList::CreateFieldTrial(
1587 "SupervisedUserExtensionPermissionIncrease", "group");
1588 std::map<std::string, std::string> params;
1589 params["legacy_supervised_user"] = enabled ? "true" : "false";
1590 params["child_account"] = enabled ? "true" : "false";
1591 variations::AssociateVariationParams(
1592 "SupervisedUserExtensionPermissionIncrease", "group", params);
1593 }
1594
mamire9609642016-06-28 22:17:541595 void InitSupervisedUserInitiatedExtensionInstallFeature(bool enabled) {
1596 base::FeatureList::ClearInstanceForTesting();
1597 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
1598 if (enabled) {
1599 feature_list->InitializeFromCommandLine(
1600 "SupervisedUserInitiatedExtensionInstall", std::string());
1601 }
1602 base::FeatureList::SetInstance(std::move(feature_list));
1603 }
1604
mamirf7715a2a2016-07-04 13:05:081605 bool IsPendingCustodianApproval(const std::string& extension_id) {
1606 auto function = make_scoped_refptr(
1607 new WebstorePrivateIsPendingCustodianApprovalFunction());
1608
1609 std::unique_ptr<base::Value> result(RunFunctionAndReturnSingleResult(
1610 function.get(), "[\"" + extension_id + "\"]", browser_context()));
1611
1612 bool copy_bool_result = false;
1613 EXPECT_TRUE(result->GetAsBoolean(&copy_bool_result));
1614 return copy_bool_result;
1615 }
1616
treib9afc6212015-10-30 18:49:581617 void InitServices(bool profile_is_supervised) {
1618 ExtensionServiceInitParams params = CreateDefaultInitParams();
1619 params.profile_is_supervised = profile_is_supervised;
mamire9609642016-06-28 22:17:541620 // If profile is supervised, don't pass a pref file such that the testing
1621 // profile creates a pref service that uses SupervisedUserPrefStore.
1622 if (profile_is_supervised) {
1623 params.pref_file = base::FilePath();
1624 }
treib9afc6212015-10-30 18:49:581625 InitializeExtensionService(params);
asargente48ab752016-03-12 00:59:201626 StartSyncing(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581627
1628 supervised_user_service()->SetDelegate(this);
1629 supervised_user_service()->Init();
1630 }
1631
mamire9609642016-06-28 22:17:541632 std::string InstallPermissionsTestExtension(bool by_custodian) {
1633 return InstallTestExtension(permissions_increase, dir_path("1"), pem_path(),
1634 by_custodian);
treib9afc6212015-10-30 18:49:581635 }
1636
1637 void UpdatePermissionsTestExtension(const std::string& id,
1638 const std::string& version,
1639 UpdateState expected_state) {
mamire9609642016-06-28 22:17:541640 UpdateTestExtension(dir_path(version), pem_path(), id, version,
1641 expected_state);
1642 }
1643
1644 std::string InstallNoPermissionsTestExtension(bool by_custodian) {
1645 base::FilePath base_path = data_dir().AppendASCII("autoupdate");
1646 base::FilePath pem_path = base_path.AppendASCII("key.pem");
1647 base::FilePath dir_path = base_path.AppendASCII("v1");
1648
1649 return InstallTestExtension(autoupdate, dir_path, pem_path, by_custodian);
1650 }
1651
1652 void UpdateNoPermissionsTestExtension(const std::string& id,
1653 const std::string& version,
1654 UpdateState expected_state) {
1655 base::FilePath base_path = data_dir().AppendASCII("autoupdate");
1656 base::FilePath pem_path = base_path.AppendASCII("key.pem");
1657 base::FilePath dir_path = base_path.AppendASCII("v" + version);
1658
1659 UpdateTestExtension(dir_path, pem_path, id, version, expected_state);
1660 }
1661
1662 std::string InstallTestExtension(const std::string& id,
1663 const base::FilePath& dir_path,
1664 const base::FilePath& pem_path,
1665 bool by_custodian) {
1666 InstallState expected_state = INSTALL_WITHOUT_LOAD;
1667 if (by_custodian) {
1668 extensions::util::SetWasInstalledByCustodian(id, profile(), true);
1669 expected_state = INSTALL_NEW;
1670 }
1671 const Extension* extension =
1672 PackAndInstallCRX(dir_path, pem_path, expected_state);
1673 // The extension must now be installed.
1674 EXPECT_TRUE(extension);
1675 EXPECT_EQ(extension->id(), id);
1676 if (by_custodian) {
1677 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1678 } else {
1679 CheckDisabledForCustodianApproval(id);
1680 }
1681
1682 EXPECT_EQ(*extension->version(), base::Version("1"));
1683
1684 return id;
1685 }
1686
1687 void UpdateTestExtension(const base::FilePath& dir_path,
1688 const base::FilePath& pem_path,
1689 const std::string& id,
1690 const std::string& version,
1691 const UpdateState& expected_state) {
1692 PackCRXAndUpdateExtension(id, dir_path, pem_path, expected_state);
treib9afc6212015-10-30 18:49:581693 const Extension* extension = registry()->GetInstalledExtension(id);
1694 ASSERT_TRUE(extension);
1695 // The version should have been updated.
mamire9609642016-06-28 22:17:541696 EXPECT_EQ(*extension->version(), base::Version(version));
1697 }
1698
1699 // Simulate a custodian approval for enabling the extension coming in
1700 // through Sync by adding the approved version to the map of approved
1701 // extensions. It doesn't simulate a change in the disable reasons.
1702 void SimulateCustodianApprovalChangeViaSync(const std::string& extension_id,
1703 const std::string& version,
1704 SyncChange::SyncChangeType type) {
1705 std::string key = SupervisedUserSettingsService::MakeSplitSettingKey(
1706 supervised_users::kApprovedExtensions, extension_id);
1707 syncer::SyncData sync_data =
1708 SupervisedUserSettingsService::CreateSyncDataForSetting(
1709 key, base::StringValue(version));
1710
1711 SyncChangeList list(1, SyncChange(FROM_HERE, type, sync_data));
1712
1713 SupervisedUserSettingsService* supervised_user_settings_service =
1714 SupervisedUserSettingsServiceFactory::GetForProfile(profile());
1715 supervised_user_settings_service->ProcessSyncChanges(FROM_HERE, list);
1716 }
1717
1718 void CheckDisabledForCustodianApproval(const std::string& extension_id) {
1719 EXPECT_TRUE(registry()->disabled_extensions().Contains(extension_id));
1720 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile());
1721 EXPECT_TRUE(extension_prefs->HasDisableReason(
1722 extension_id,
1723 extensions::Extension::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
treib9afc6212015-10-30 18:49:581724 }
1725
1726 SupervisedUserService* supervised_user_service() {
1727 return SupervisedUserServiceFactory::GetForProfile(profile());
1728 }
1729
mamire9609642016-06-28 22:17:541730 static std::string RequestId(const std::string& extension_id,
1731 const std::string& version) {
1732 return SupervisedUserService::GetExtensionRequestId(
treib9afc6212015-10-30 18:49:581733 extension_id, base::Version(version));
1734 }
1735
1736 private:
1737 // This prevents the legacy supervised user init code from running.
1738 bool SetActive(bool active) override { return true; }
1739
1740 base::FilePath base_path() const {
1741 return data_dir().AppendASCII("permissions_increase");
1742 }
1743 base::FilePath dir_path(const std::string& version) const {
1744 return base_path().AppendASCII("v" + version);
1745 }
1746 base::FilePath pem_path() const {
1747 return base_path().AppendASCII("permissions.pem");
1748 }
treibb6af28cd2015-12-01 11:19:461749
1750 base::FieldTrialList field_trial_list_;
treib9afc6212015-10-30 18:49:581751};
1752
1753class MockPermissionRequestCreator : public PermissionRequestCreator {
1754 public:
1755 MockPermissionRequestCreator() {}
1756 ~MockPermissionRequestCreator() override {}
1757
1758 bool IsEnabled() const override { return true; }
1759
1760 void CreateURLAccessRequest(const GURL& url_requested,
1761 const SuccessCallback& callback) override {
1762 FAIL();
1763 }
1764
mamire9609642016-06-28 22:17:541765 MOCK_METHOD2(CreateExtensionInstallRequest,
1766 void(const std::string& id,
1767 const SupervisedUserService::SuccessCallback& callback));
1768
treib9afc6212015-10-30 18:49:581769 MOCK_METHOD2(CreateExtensionUpdateRequest,
1770 void(const std::string& id,
1771 const SupervisedUserService::SuccessCallback& callback));
1772
1773 private:
1774 DISALLOW_COPY_AND_ASSIGN(MockPermissionRequestCreator);
1775};
1776
1777TEST_F(ExtensionServiceTestSupervised, InstallOnlyAllowedByCustodian) {
1778 InitServices(true /* profile_is_supervised */);
mamire9609642016-06-28 22:17:541779 InitSupervisedUserInitiatedExtensionInstallFeature(false);
treib9afc6212015-10-30 18:49:581780
mamir192d7882016-06-22 17:10:161781 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
1782
treib9afc6212015-10-30 18:49:581783 base::FilePath path1 = data_dir().AppendASCII("good.crx");
1784 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
1785 const Extension* extensions[] = {
1786 InstallCRX(path1, INSTALL_FAILED),
mamir192d7882016-06-22 17:10:161787 InstallCRX(path2, INSTALL_NEW)
treib9afc6212015-10-30 18:49:581788 };
1789
1790 // Only the extension with the "installed by custodian" flag should have been
1791 // installed and enabled.
1792 EXPECT_FALSE(extensions[0]);
1793 ASSERT_TRUE(extensions[1]);
1794 EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id()));
mamirf7715a2a2016-07-04 13:05:081795 EXPECT_FALSE(IsPendingCustodianApproval(extensions[1]->id()));
treib9afc6212015-10-30 18:49:581796}
1797
mamir192d7882016-06-22 17:10:161798TEST_F(ExtensionServiceTestSupervised,
1799 DelegatedAndPreinstalledExtensionIsSUFirst) {
1800 InitServices(false /* profile_is_supervised */);
mamire9609642016-06-28 22:17:541801 InitSupervisedUserInitiatedExtensionInstallFeature(false);
mamir192d7882016-06-22 17:10:161802
1803 // Install an extension.
1804 base::FilePath path = data_dir().AppendASCII("good.crx");
1805 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1806 std::string id = extension->id();
1807 const std::string version("1.0.0.0");
1808 // It should be enabled.
1809 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1810
1811 // Now make the profile supervised.
1812 profile()->AsTestingProfile()->SetSupervisedUserId(
1813 supervised_users::kChildAccountSUID);
1814
1815 // It should not be enabled now (it is not loaded at all actually).
1816 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
1817
1818 // Simulate data sync with the "was_installed_by_custodian" flag set to 1.
1819 sync_pb::EntitySpecifics specifics;
1820 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1821 ext_specifics->set_id(id);
1822 ext_specifics->set_enabled(true);
1823 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
1824 ext_specifics->set_installed_by_custodian(true);
1825 ext_specifics->set_version(version);
1826
1827 SyncChangeList list =
1828 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
1829
1830 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1831
1832 // The extension should be enabled again.
1833 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1834 EXPECT_TRUE(extensions::util::WasInstalledByCustodian(id, profile()));
1835}
1836
1837TEST_F(ExtensionServiceTestSupervised,
1838 DelegatedAndPreinstalledExtensionSyncFirst) {
1839 InitServices(false /* profile_is_supervised */);
mamire9609642016-06-28 22:17:541840 InitSupervisedUserInitiatedExtensionInstallFeature(false);
mamir192d7882016-06-22 17:10:161841
1842 // Install an extension.
1843 base::FilePath path = data_dir().AppendASCII("good.crx");
1844 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1845 std::string id = extension->id();
1846 const std::string version("1.0.0.0");
1847
1848 // It should be enabled.
1849 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1850
1851 // Simulate data sync with the "was_installed_by_custodian" flag set to 1.
1852 sync_pb::EntitySpecifics specifics;
1853 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1854 ext_specifics->set_id(id);
1855 ext_specifics->set_enabled(true);
1856 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
1857 ext_specifics->set_installed_by_custodian(true);
1858 ext_specifics->set_version(version);
1859
1860 SyncChangeList list =
1861 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
1862
1863 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
mamir192d7882016-06-22 17:10:161864 // The extension should be enabled.
1865 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1866 EXPECT_TRUE(extensions::util::WasInstalledByCustodian(id, profile()));
1867}
1868
mamire9609642016-06-28 22:17:541869TEST_F(ExtensionServiceTestSupervised,
1870 InstallAllowedByCustodianAndSupervisedUser) {
1871 InitServices(true /* profile_is_supervised */);
1872 InitSupervisedUserInitiatedExtensionInstallFeature(true);
1873
1874 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
1875
1876 base::FilePath path1 = data_dir().AppendASCII("good.crx");
1877 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
1878 const Extension* extensions[] = {
1879 InstallCRX(path1, INSTALL_WITHOUT_LOAD),
1880 InstallCRX(path2, INSTALL_NEW)
1881 };
1882
1883 // Only the extension with the "installed by custodian" flag should have been
1884 // installed and enabled.
1885 // The extension missing the "installed by custodian" flag is a
1886 // supervised user initiated install and hence not enabled.
1887 ASSERT_TRUE(extensions[0]);
1888 ASSERT_TRUE(extensions[1]);
1889 EXPECT_TRUE(registry()->disabled_extensions().Contains(extensions[0]->id()));
mamirf7715a2a2016-07-04 13:05:081890 EXPECT_TRUE(IsPendingCustodianApproval(extensions[0]->id()));
mamire9609642016-06-28 22:17:541891 EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id()));
mamirf7715a2a2016-07-04 13:05:081892 EXPECT_FALSE(IsPendingCustodianApproval(extensions[1]->id()));
mamire9609642016-06-28 22:17:541893}
1894
1895TEST_F(ExtensionServiceTestSupervised,
1896 PreinstalledExtensionWithSUInitiatedInstalls) {
1897 InitServices(false /* profile_is_supervised */);
1898 InitSupervisedUserInitiatedExtensionInstallFeature(true);
1899
1900 // Install an extension.
1901 base::FilePath path = data_dir().AppendASCII("good.crx");
1902 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1903 std::string id = extension->id();
1904 // Make sure it's enabled.
1905 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1906
1907 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1908 supervised_user_service()->AddPermissionRequestCreator(
1909 base::WrapUnique(creator));
1910 const std::string version("1.0.0.0");
1911
1912 EXPECT_CALL(*creator, CreateExtensionInstallRequest(
1913 RequestId(good_crx, version), testing::_));
1914
1915 // Now make the profile supervised.
1916 profile()->AsTestingProfile()->SetSupervisedUserId(
1917 supervised_users::kChildAccountSUID);
1918
1919 Mock::VerifyAndClearExpectations(creator);
1920
1921 // The extension should not be enabled anymore.
1922 CheckDisabledForCustodianApproval(id);
mamirf7715a2a2016-07-04 13:05:081923 EXPECT_TRUE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:541924}
1925
1926TEST_F(ExtensionServiceTestSupervised,
1927 PreinstalledExtensionWithoutSUInitiatedInstalls) {
1928 InitServices(false /* profile_is_supervised */);
1929 InitSupervisedUserInitiatedExtensionInstallFeature(false);
1930
1931 // Install an extension.
1932 base::FilePath path = data_dir().AppendASCII("good.crx");
1933 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1934 std::string id = extension->id();
1935
1936 // Make sure it's enabled.
1937 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1938
1939 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1940 supervised_user_service()->AddPermissionRequestCreator(
1941 base::WrapUnique(creator));
1942 const std::string version("1.0.0.0");
1943
1944 // No request should be sent because supervised user initiated installs
1945 // are disabled.
1946 EXPECT_CALL(*creator, CreateExtensionInstallRequest(testing::_, testing::_))
1947 .Times(0);
1948
1949 // Now make the profile supervised.
1950 profile()->AsTestingProfile()->SetSupervisedUserId(
1951 supervised_users::kChildAccountSUID);
1952
1953 // The extension should not be loaded anymore.
1954 EXPECT_FALSE(registry()->GetInstalledExtension(id));
1955}
1956
1957TEST_F(ExtensionServiceTestSupervised, ExtensionApprovalBeforeInstallation) {
1958 // This tests the case when the sync entity flagging the extension as approved
1959 // arrives before the extension itself is installed.
1960 InitServices(true /* profile_is_supervised */);
1961 InitSupervisedUserInitiatedExtensionInstallFeature(true);
1962
1963 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1964 supervised_user_service()->AddPermissionRequestCreator(
1965 base::WrapUnique(creator));
1966
1967 std::string id = good_crx;
1968 std::string version("1.0.0.0");
1969
1970 SimulateCustodianApprovalChangeViaSync(id, version, SyncChange::ACTION_ADD);
1971
1972 // Now install an extension.
1973 base::FilePath path = data_dir().AppendASCII("good.crx");
1974 InstallCRX(path, INSTALL_NEW);
1975
1976 // No approval request should be sent.
1977 EXPECT_CALL(*creator, CreateExtensionInstallRequest(testing::_, testing::_))
1978 .Times(0);
1979
1980 // Make sure it's enabled.
1981 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:081982 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:541983}
1984
treib9afc6212015-10-30 18:49:581985TEST_F(ExtensionServiceTestSupervised, UpdateWithoutPermissionIncrease) {
1986 InitServices(true /* profile_is_supervised */);
1987
treib9afc6212015-10-30 18:49:581988 // Save the id, as the extension object will be destroyed during updating.
mamire9609642016-06-28 22:17:541989 std::string id = InstallNoPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:581990
1991 // Update to a new version.
mamire9609642016-06-28 22:17:541992 std::string version2("2");
1993 UpdateNoPermissionsTestExtension(id, version2, ENABLED);
treib9afc6212015-10-30 18:49:581994
1995 // The extension should still be there and enabled.
mamire9609642016-06-28 22:17:541996 const Extension* extension = registry()->enabled_extensions().GetByID(id);
treib9afc6212015-10-30 18:49:581997 ASSERT_TRUE(extension);
1998 // The version should have changed.
mamire9609642016-06-28 22:17:541999 EXPECT_EQ(*extension->version(), base::Version(version2));
mamirf7715a2a2016-07-04 13:05:082000 EXPECT_FALSE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582001}
2002
2003TEST_F(ExtensionServiceTestSupervised, UpdateWithPermissionIncreaseNoApproval) {
treibb6af28cd2015-12-01 11:19:462004 InitNeedCustodianApprovalFieldTrial(false);
treib9afc6212015-10-30 18:49:582005
2006 InitServices(true /* profile_is_supervised */);
2007
2008 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2009 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222010 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582011
mamire9609642016-06-28 22:17:542012 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582013
2014 // Update to a new version with increased permissions.
2015 // Since we don't require the custodian's approval, no permission request
2016 // should be created.
2017 const std::string version2("2");
2018 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542019 RequestId(id, version2), testing::_))
treib9afc6212015-10-30 18:49:582020 .Times(0);
2021 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamirf7715a2a2016-07-04 13:05:082022 EXPECT_FALSE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582023}
2024
2025TEST_F(ExtensionServiceTestSupervised,
2026 UpdateWithPermissionIncreaseApprovalOldVersion) {
treibb6af28cd2015-12-01 11:19:462027 InitNeedCustodianApprovalFieldTrial(true);
treib9afc6212015-10-30 18:49:582028
2029 InitServices(true /* profile_is_supervised */);
2030
2031 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2032 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222033 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582034
2035 const std::string version1("1");
2036 const std::string version2("2");
2037
mamire9609642016-06-28 22:17:542038 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582039
2040 // Update to a new version with increased permissions.
2041 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542042 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582043 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542044 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082045 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582046
2047 // Simulate a custodian approval for re-enabling the extension coming in
2048 // through Sync, but set the old version. This can happen when there already
2049 // was a pending request for an earlier version of the extension.
2050 sync_pb::EntitySpecifics specifics;
2051 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2052 ext_specifics->set_id(id);
2053 ext_specifics->set_enabled(true);
2054 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
2055 ext_specifics->set_installed_by_custodian(true);
2056 ext_specifics->set_version(version1);
2057
2058 // Attempting to re-enable an old version should result in a permission
2059 // request for the current version.
2060 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542061 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582062
treib65f103042015-12-03 10:21:362063 SyncChangeList list =
2064 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2065
2066 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582067 // The re-enable should be ignored, since the version doesn't match.
2068 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2069 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
2070 id, base::Version(version1)));
2071 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
2072 id, base::Version(version2)));
mamire9609642016-06-28 22:17:542073 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082074 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582075}
2076
2077TEST_F(ExtensionServiceTestSupervised,
2078 UpdateWithPermissionIncreaseApprovalMatchingVersion) {
treibb6af28cd2015-12-01 11:19:462079 InitNeedCustodianApprovalFieldTrial(true);
treib9afc6212015-10-30 18:49:582080
2081 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);
mamirf7715a2a2016-07-04 13:05:082095 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582096
2097 // Simulate a custodian approval for re-enabling the extension coming in
2098 // through Sync.
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(version2);
2106
treib65f103042015-12-03 10:21:362107 SyncChangeList list =
2108 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2109
2110 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582111 // The extension should have gotten re-enabled.
2112 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082113 EXPECT_FALSE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582114}
2115
2116TEST_F(ExtensionServiceTestSupervised,
2117 UpdateWithPermissionIncreaseApprovalNewVersion) {
treibb6af28cd2015-12-01 11:19:462118 InitNeedCustodianApprovalFieldTrial(true);
treib9afc6212015-10-30 18:49:582119
2120 InitServices(true /* profile_is_supervised */);
2121
2122 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2123 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222124 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582125
mamire9609642016-06-28 22:17:542126 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582127
2128 // Update to a new version with increased permissions.
2129 const std::string version2("2");
2130 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542131 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582132 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542133 Mock::VerifyAndClearExpectations(creator);
treib9afc6212015-10-30 18:49:582134
2135 // Simulate a custodian approval for re-enabling the extension coming in
2136 // through Sync. Set a newer version than we have installed.
2137 const std::string version3("3");
2138 sync_pb::EntitySpecifics specifics;
2139 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2140 ext_specifics->set_id(id);
2141 ext_specifics->set_enabled(true);
2142 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
2143 ext_specifics->set_installed_by_custodian(true);
2144 ext_specifics->set_version(version3);
2145
2146 // This should *not* result in a new permission request.
2147 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542148 RequestId(id, version3), testing::_))
treib9afc6212015-10-30 18:49:582149 .Times(0);
2150
treib65f103042015-12-03 10:21:362151 SyncChangeList list =
2152 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2153
2154 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582155 // The re-enable should be delayed until the extension is updated to the
2156 // matching version.
2157 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2158 EXPECT_TRUE(extension_sync_service()->HasPendingReenable(
2159 id, base::Version(version3)));
2160
2161 // Update to the matching version. Now the extension should get enabled.
2162 UpdatePermissionsTestExtension(id, version3, ENABLED);
2163}
2164
mamire9609642016-06-28 22:17:542165TEST_F(ExtensionServiceTestSupervised, SupervisedUserInitiatedInstalls) {
2166 InitNeedCustodianApprovalFieldTrial(true);
2167 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2168
2169 InitServices(true /* profile_is_supervised */);
2170
2171 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2172 supervised_user_service()->AddPermissionRequestCreator(
2173 base::WrapUnique(creator));
2174
2175 base::FilePath path = data_dir().AppendASCII("good.crx");
2176 std::string version("1.0.0.0");
2177
2178 EXPECT_CALL(*creator, CreateExtensionInstallRequest(
2179 RequestId(good_crx, version), testing::_));
2180
2181 // Should be installed but disabled, a request for approval should be sent.
2182 const Extension* extension = InstallCRX(path, INSTALL_WITHOUT_LOAD);
2183 ASSERT_TRUE(extension);
2184 ASSERT_EQ(extension->id(), good_crx);
2185 EXPECT_TRUE(registry()->disabled_extensions().Contains(good_crx));
2186 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082187 EXPECT_TRUE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542188
2189 SimulateCustodianApprovalChangeViaSync(good_crx, version,
2190 SyncChange::ACTION_ADD);
2191
2192 // The extension should be enabled now.
2193 EXPECT_TRUE(registry()->enabled_extensions().Contains(good_crx));
mamirf7715a2a2016-07-04 13:05:082194 EXPECT_FALSE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542195
2196 // Simulate approval removal coming via Sync.
2197 SimulateCustodianApprovalChangeViaSync(good_crx, version,
2198 SyncChange::ACTION_DELETE);
2199
2200 // The extension should be disabled now.
2201 EXPECT_TRUE(registry()->disabled_extensions().Contains(good_crx));
mamirf7715a2a2016-07-04 13:05:082202 EXPECT_TRUE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542203}
2204
2205TEST_F(ExtensionServiceTestSupervised,
2206 UpdateSUInitiatedInstallWithoutPermissionIncrease) {
2207 InitNeedCustodianApprovalFieldTrial(true);
2208 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2209
2210 InitServices(true /* profile_is_supervised */);
2211
2212 std::string id = InstallNoPermissionsTestExtension(false /* by_custodian */);
2213 std::string version1("1");
2214
2215 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2216
2217 // The extension should be enabled now.
2218 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2219
2220 std::string version2("2");
2221
2222 // Update to a new version.
2223 UpdateNoPermissionsTestExtension(id, version2, ENABLED);
2224
2225 // The extension should still be there and enabled.
2226 const Extension* extension = registry()->enabled_extensions().GetByID(id);
2227 ASSERT_TRUE(extension);
2228 // The version should have increased.
2229 EXPECT_EQ(1, extension->version()->CompareTo(base::Version(version1)));
2230
2231 // Check that the approved version has been updated in the prefs as well.
2232 // Prefs are updated via Sync. If the prefs are updated, then the new
2233 // approved version has been pushed to Sync as well.
2234 std::string approved_version;
2235 PrefService* pref_service = profile()->GetPrefs();
2236 const base::DictionaryValue* approved_extensions =
2237 pref_service->GetDictionary(prefs::kSupervisedUserApprovedExtensions);
2238 approved_extensions->GetStringWithoutPathExpansion(id, &approved_version);
2239
2240 EXPECT_EQ(base::Version(approved_version), *extension->version());
mamirf7715a2a2016-07-04 13:05:082241 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542242}
2243
2244TEST_F(ExtensionServiceTestSupervised,
2245 UpdateSUInitiatedInstallWithPermissionIncrease) {
2246 InitNeedCustodianApprovalFieldTrial(true);
2247 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2248
2249 InitServices(true /* profile_is_supervised */);
2250
2251 std::string id = InstallPermissionsTestExtension(false /* by_custodian */);
2252 std::string version1("1");
2253
2254 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2255
2256 // The extension should be enabled now.
2257 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2258
2259 std::string version3("3");
2260
2261 UpdatePermissionsTestExtension(id, version3, DISABLED);
2262
2263 // The extension should be disabled.
2264 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2265 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
2266 id, Extension::DISABLE_PERMISSIONS_INCREASE));
2267
2268 std::string version2("2");
2269 // Approve an older version
2270 SimulateCustodianApprovalChangeViaSync(id, version2,
2271 SyncChange::ACTION_UPDATE);
2272
2273 // The extension should remain disabled.
2274 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2275 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
2276 id, Extension::DISABLE_PERMISSIONS_INCREASE));
2277 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
2278 id, Extension::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
2279
mamirf7715a2a2016-07-04 13:05:082280 EXPECT_TRUE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542281 // Approve the latest version
2282 SimulateCustodianApprovalChangeViaSync(id, version3,
2283 SyncChange::ACTION_UPDATE);
2284
2285 // The extension should be enabled again.
2286 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082287 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542288}
2289
2290TEST_F(ExtensionServiceTestSupervised,
2291 UpdateSUInitiatedInstallWithPermissionIncreaseApprovalArrivesFirst) {
2292 InitNeedCustodianApprovalFieldTrial(true);
2293 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2294
2295 InitServices(true /* profile_is_supervised */);
2296
2297 std::string id = InstallPermissionsTestExtension(false /* by_custodian */);
2298
2299 std::string version1("1");
2300 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2301
2302 // The extension should be enabled now.
2303 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2304
2305 std::string version2("2");
2306 // Approve a newer version
2307 SimulateCustodianApprovalChangeViaSync(id, version2,
2308 SyncChange::ACTION_UPDATE);
2309
2310 // The extension should be disabled.
2311 CheckDisabledForCustodianApproval(id);
2312
2313 // Now update the extension to the same version that was approved.
2314 UpdatePermissionsTestExtension(id, version2, ENABLED);
2315 // The extension should be enabled again.
2316 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082317 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542318}
2319
treib9afc6212015-10-30 18:49:582320TEST_F(ExtensionServiceSyncTest, SyncUninstallByCustodianSkipsPolicy) {
2321 InitializeEmptyExtensionService();
2322 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:362323 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:142324 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
2325 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:582326
mamir192d7882016-06-22 17:10:162327 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
treib9afc6212015-10-30 18:49:582328 // Install two extensions.
2329 base::FilePath path1 = data_dir().AppendASCII("good.crx");
2330 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
2331 const Extension* extensions[] = {
2332 InstallCRX(path1, INSTALL_NEW),
mamir192d7882016-06-22 17:10:162333 InstallCRX(path2, INSTALL_NEW)
treib9afc6212015-10-30 18:49:582334 };
2335
2336 // Add a policy provider that will disallow any changes.
2337 extensions::TestManagementPolicyProvider provider(
2338 extensions::TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS);
2339 ExtensionSystem::Get(
2340 browser_context())->management_policy()->RegisterProvider(&provider);
2341
2342 // Create a sync deletion for each extension.
treib65f103042015-12-03 10:21:362343 SyncChangeList list;
treib9afc6212015-10-30 18:49:582344 for (size_t i = 0; i < arraysize(extensions); i++) {
2345 const std::string& id = extensions[i]->id();
2346 sync_pb::EntitySpecifics specifics;
2347 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2348 ext_specifics->set_id(id);
2349 ext_specifics->set_version("1.0");
2350 ext_specifics->set_installed_by_custodian(
mamir192d7882016-06-22 17:10:162351 extensions::util::WasInstalledByCustodian(id, profile()));
2352
treib9afc6212015-10-30 18:49:582353 syncer::SyncData sync_data =
2354 syncer::SyncData::CreateLocalData(id, "Name", specifics);
treib65f103042015-12-03 10:21:362355 list.push_back(SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, sync_data));
treib9afc6212015-10-30 18:49:582356 }
2357
2358 // Save the extension ids, as uninstalling destroys the Extension instance.
2359 std::string extension_ids[] = {
2360 extensions[0]->id(),
2361 extensions[1]->id()
2362 };
2363
2364 // Now apply the uninstallations.
treib65f103042015-12-03 10:21:362365 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582366
2367 // Uninstalling the extension without installed_by_custodian should have been
2368 // blocked by policy, so it should still be there.
2369 EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_ids[0]));
2370
2371 // But installed_by_custodian should result in bypassing the policy check.
2372 EXPECT_FALSE(
2373 registry()->GenerateInstalledExtensionsSet()->Contains(extension_ids[1]));
2374}
2375
rdevlin.cronin738501d2015-11-05 21:51:362376TEST_F(ExtensionServiceSyncTest, SyncExtensionHasAllhostsWithheld) {
2377 InitializeEmptyExtensionService();
asargente48ab752016-03-12 00:59:202378 StartSyncing(syncer::EXTENSIONS);
rdevlin.cronin738501d2015-11-05 21:51:362379
2380 // Create an extension that needs all-hosts.
2381 const std::string kName("extension");
2382 scoped_refptr<const Extension> extension =
2383 extensions::ExtensionBuilder()
limasdf3d102542015-12-09 03:58:452384 .SetLocation(Manifest::INTERNAL)
dcheng794d2bd2016-02-27 03:51:322385 .SetManifest(
limasdf3d102542015-12-09 03:58:452386 extensions::DictionaryBuilder()
2387 .Set("name", kName)
2388 .Set("description", "foo")
2389 .Set("manifest_version", 2)
2390 .Set("version", "1.0")
2391 .Set("permissions",
dcheng794d2bd2016-02-27 03:51:322392 extensions::ListBuilder().Append("*://*/*").Build())
2393 .Build())
limasdf3d102542015-12-09 03:58:452394 .SetID(crx_file::id_util::GenerateId(kName))
2395 .Build();
rdevlin.cronin738501d2015-11-05 21:51:362396
2397 // Install and enable it.
2398 service()->AddExtension(extension.get());
2399 service()->GrantPermissionsAndEnableExtension(extension.get());
2400 const std::string id = extension->id();
2401 EXPECT_TRUE(registry()->enabled_extensions().GetByID(id));
2402
2403 // Simulate a sync node coming in where the extension had all-hosts withheld.
2404 // This means that it should have all-hosts withheld on this machine, too.
rdevlin.cronin738501d2015-11-05 21:51:362405 sync_pb::EntitySpecifics specifics;
2406 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2407 ext_specifics->set_id(id);
2408 ext_specifics->set_name(kName);
2409 ext_specifics->set_version("1.0");
2410 ext_specifics->set_all_urls_enabled(false);
2411 ext_specifics->set_enabled(true);
rdevlin.cronin738501d2015-11-05 21:51:362412
treib65f103042015-12-03 10:21:362413 SyncChangeList list =
2414 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2415
2416 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
rdevlin.cronin738501d2015-11-05 21:51:362417
rdevlin.cronind01837b2016-08-17 01:37:182418 const Extension* enabled_extension =
2419 registry()->enabled_extensions().GetByID(id);
2420 ASSERT_TRUE(enabled_extension);
2421 ScriptingPermissionsModifier modifier(profile(), enabled_extension);
2422 EXPECT_FALSE(modifier.IsAllowedOnAllUrls());
2423 EXPECT_TRUE(modifier.HasSetAllowedOnAllUrls());
rdevlin.cronin738501d2015-11-05 21:51:362424}
2425
treib9afc6212015-10-30 18:49:582426#endif // defined(ENABLE_SUPERVISED_USERS)
asargente48ab752016-03-12 00:59:202427
2428// Tests sync behavior in the case of an item that starts out as an app and
2429// gets updated to become an extension.
2430TEST_F(ExtensionServiceSyncTest, AppToExtension) {
2431 InitializeEmptyExtensionService();
2432 service()->Init();
2433 ASSERT_TRUE(service()->is_ready());
2434
2435 // Install v1, which is an app.
2436 const Extension* v1 =
2437 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v1.crx"),
2438 INSTALL_NEW);
2439 EXPECT_TRUE(v1->is_app());
2440 EXPECT_FALSE(v1->is_extension());
2441 std::string id = v1->id();
2442
2443 StatefulChangeProcessor extensions_processor(syncer::ModelType::EXTENSIONS);
2444 StatefulChangeProcessor apps_processor(syncer::ModelType::APPS);
2445 extension_sync_service()->MergeDataAndStartSyncing(
2446 syncer::EXTENSIONS, syncer::SyncDataList(),
2447 extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222448 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202449 extension_sync_service()->MergeDataAndStartSyncing(
2450 syncer::APPS, syncer::SyncDataList(), apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222451 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202452
2453 // Check the app/extension change processors to be sure the right data was
2454 // added.
2455 EXPECT_TRUE(extensions_processor.changes().empty());
2456 EXPECT_TRUE(extensions_processor.data().empty());
2457 EXPECT_EQ(1u, apps_processor.data().size());
2458 ASSERT_EQ(1u, apps_processor.changes().size());
2459 const SyncChange& app_change = apps_processor.changes()[0];
2460 EXPECT_EQ(SyncChange::ACTION_ADD, app_change.change_type());
dchengc963c7142016-04-08 03:55:222461 std::unique_ptr<ExtensionSyncData> app_data =
asargente48ab752016-03-12 00:59:202462 ExtensionSyncData::CreateFromSyncData(app_change.sync_data());
2463 EXPECT_TRUE(app_data->is_app());
2464 EXPECT_EQ(id, app_data->id());
2465 EXPECT_EQ(*v1->version(), app_data->version());
2466
2467 // Update the app to v2, which is an extension.
2468 const Extension* v2 =
2469 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v2.crx"),
2470 INSTALL_UPDATED);
2471 EXPECT_FALSE(v2->is_app());
2472 EXPECT_TRUE(v2->is_extension());
2473 EXPECT_EQ(id, v2->id());
2474
2475 // Make sure we saw an extension item added.
2476 ASSERT_EQ(1u, extensions_processor.changes().size());
2477 const SyncChange& extension_change = extensions_processor.changes()[0];
2478 EXPECT_EQ(SyncChange::ACTION_ADD, extension_change.change_type());
dchengc963c7142016-04-08 03:55:222479 std::unique_ptr<ExtensionSyncData> extension_data =
asargente48ab752016-03-12 00:59:202480 ExtensionSyncData::CreateFromSyncData(extension_change.sync_data());
2481 EXPECT_FALSE(extension_data->is_app());
2482 EXPECT_EQ(id, extension_data->id());
2483 EXPECT_EQ(*v2->version(), extension_data->version());
2484
2485 // Get the current data from the change processors to use as the input to
2486 // the following call to MergeDataAndStartSyncing. This simulates what should
2487 // happen with sync.
2488 syncer::SyncDataList extensions_data =
2489 extensions_processor.GetAllSyncData(syncer::EXTENSIONS);
2490 syncer::SyncDataList apps_data = apps_processor.GetAllSyncData(syncer::APPS);
2491
2492 // Stop syncing, then start again.
2493 extension_sync_service()->StopSyncing(syncer::EXTENSIONS);
2494 extension_sync_service()->StopSyncing(syncer::APPS);
2495 extension_sync_service()->MergeDataAndStartSyncing(
2496 syncer::EXTENSIONS, extensions_data, extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222497 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202498 extension_sync_service()->MergeDataAndStartSyncing(
2499 syncer::APPS, apps_data, apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222500 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202501
2502 // Make sure we saw an app item deleted.
2503 bool found_delete = false;
2504 for (const auto& change : apps_processor.changes()) {
2505 if (change.change_type() == SyncChange::ACTION_DELETE) {
dchengc963c7142016-04-08 03:55:222506 std::unique_ptr<ExtensionSyncData> data =
asargente48ab752016-03-12 00:59:202507 ExtensionSyncData::CreateFromSyncChange(change);
2508 if (data->id() == id) {
2509 found_delete = true;
2510 break;
2511 }
2512 }
2513 }
2514 EXPECT_TRUE(found_delete);
2515
2516 // Make sure there is one extension, and there are no more apps.
2517 EXPECT_EQ(1u, extensions_processor.data().size());
2518 EXPECT_TRUE(apps_processor.data().empty());
2519}