blob: 8d91faa87b5eb1c7562a79d2734f2967b68abf3c [file] [log] [blame]
treib9afc6212015-10-30 18:49:581// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
avia2f4804a2015-12-24 23:11:135#include <stddef.h>
6
treibb6af28cd2015-12-01 11:19:467#include <map>
dchengc963c7142016-04-08 03:55:228#include <memory>
treib9afc6212015-10-30 18:49:589#include <string>
limasdf3d102542015-12-09 03:58:4510#include <utility>
treib9afc6212015-10-30 18:49:5811
12#include "base/bind.h"
13#include "base/command_line.h"
14#include "base/files/file_util.h"
avia2f4804a2015-12-24 23:11:1315#include "base/macros.h"
dchengc963c7142016-04-08 03:55:2216#include "base/memory/ptr_util.h"
treib9afc6212015-10-30 18:49:5817#include "base/memory/weak_ptr.h"
18#include "base/metrics/field_trial.h"
19#include "base/test/mock_entropy_provider.h"
asvitkineb1db8262016-11-08 09:48:2020#include "base/test/scoped_feature_list.h"
Evan Stade46d716d2017-06-02 20:50:0921#include "chrome/browser/chrome_notification_types.h"
mamirf7715a2a2016-07-04 13:05:0822#include "chrome/browser/extensions/api/webstore_private/webstore_private_api.h"
treib9afc6212015-10-30 18:49:5823#include "chrome/browser/extensions/component_loader.h"
24#include "chrome/browser/extensions/extension_service.h"
25#include "chrome/browser/extensions/extension_service_test_with_install.h"
26#include "chrome/browser/extensions/extension_sync_data.h"
27#include "chrome/browser/extensions/extension_sync_service.h"
28#include "chrome/browser/extensions/extension_util.h"
rdevlin.cronind01837b2016-08-17 01:37:1829#include "chrome/browser/extensions/scripting_permissions_modifier.h"
treib9afc6212015-10-30 18:49:5830#include "chrome/browser/extensions/updater/extension_updater.h"
treib9afc6212015-10-30 18:49:5831#include "chrome/browser/sync/profile_sync_service_factory.h"
Evan Stade46d716d2017-06-02 20:50:0932#include "chrome/browser/themes/theme_service.h"
33#include "chrome/browser/themes/theme_service_factory.h"
treib9afc6212015-10-30 18:49:5834#include "chrome/common/chrome_constants.h"
35#include "chrome/common/chrome_switches.h"
36#include "chrome/common/extensions/sync_helper.h"
brettw9e85ef42016-11-01 21:01:2437#include "chrome/common/features.h"
treib9afc6212015-10-30 18:49:5838#include "chrome/test/base/testing_profile.h"
maxbogue26f40222016-09-16 20:22:1839#include "components/browser_sync/profile_sync_service.h"
rdevlin.cronin738501d2015-11-05 21:51:3640#include "components/crx_file/id_util.h"
skym71603842016-10-10 18:17:3141#include "components/sync/model/fake_sync_change_processor.h"
42#include "components/sync/model/sync_change_processor_wrapper_for_test.h"
43#include "components/sync/model/sync_data.h"
44#include "components/sync/model/sync_error_factory_mock.h"
treibb6af28cd2015-12-01 11:19:4645#include "components/variations/variations_associated_data.h"
mamirf7715a2a2016-07-04 13:05:0846#include "extensions/browser/api_test_utils.h"
treib9afc6212015-10-30 18:49:5847#include "extensions/browser/app_sorting.h"
48#include "extensions/browser/extension_prefs.h"
49#include "extensions/browser/extension_registry.h"
50#include "extensions/browser/extension_system.h"
karandeepb810e33402017-04-05 23:41:2251#include "extensions/browser/extension_util.h"
treib9afc6212015-10-30 18:49:5852#include "extensions/browser/management_policy.h"
53#include "extensions/browser/test_management_policy.h"
54#include "extensions/common/constants.h"
rdevlin.cronin738501d2015-11-05 21:51:3655#include "extensions/common/extension_builder.h"
treib9afc6212015-10-30 18:49:5856#include "extensions/common/manifest_url_handlers.h"
57#include "extensions/common/permissions/permission_set.h"
rdevlin.cronin738501d2015-11-05 21:51:3658#include "extensions/common/value_builder.h"
treib9afc6212015-10-30 18:49:5859#include "testing/gtest/include/gtest/gtest.h"
60
brettw9e85ef42016-11-01 21:01:2461#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
treib9afc6212015-10-30 18:49:5862#include "chrome/browser/supervised_user/permission_request_creator.h"
63#include "chrome/browser/supervised_user/supervised_user_constants.h"
mamire9609642016-06-28 22:17:5464#include "chrome/browser/supervised_user/supervised_user_features.h"
treib9afc6212015-10-30 18:49:5865#include "chrome/browser/supervised_user/supervised_user_service.h"
66#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
mamire9609642016-06-28 22:17:5467#include "chrome/browser/supervised_user/supervised_user_settings_service.h"
68#include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
69#include "chrome/common/pref_names.h"
treib9afc6212015-10-30 18:49:5870#endif
71
mamirf7715a2a2016-07-04 13:05:0872using extensions::api_test_utils::RunFunctionAndReturnSingleResult;
treib9afc6212015-10-30 18:49:5873using extensions::AppSorting;
74using extensions::Extension;
75using extensions::ExtensionPrefs;
76using extensions::ExtensionSyncData;
77using extensions::ExtensionSystem;
78using extensions::Manifest;
79using extensions::PermissionSet;
rdevlin.cronind01837b2016-08-17 01:37:1880using extensions::ScriptingPermissionsModifier;
mamirf7715a2a2016-07-04 13:05:0881using extensions::WebstorePrivateIsPendingCustodianApprovalFunction;
treib65f103042015-12-03 10:21:3682using syncer::SyncChange;
83using syncer::SyncChangeList;
mamire9609642016-06-28 22:17:5484using testing::Mock;
treib65f103042015-12-03 10:21:3685
86namespace {
treib9afc6212015-10-30 18:49:5887
mamir192d7882016-06-22 17:10:1688const char autoupdate[] = "ogjcoiohnmldgjemafoockdghcjciccf";
treib9afc6212015-10-30 18:49:5889const char good0[] = "behllobkkfkfnphdnhnkndlbkcpglgmj";
90const char good2[] = "bjafgdebaacbbbecmhlhpofkepfkgcpa";
mamir192d7882016-06-22 17:10:1691const char good2048[] = "nmgjhmhbleinmjpbdhgajfjkbijcmgbh";
treib9afc6212015-10-30 18:49:5892const char good_crx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
93const char page_action[] = "obcimlgaoabeegjmmpldobjndiealpln";
mamir192d7882016-06-22 17:10:1694const char permissions_increase[] = "pgdpcfcocojkjfbgpiianjngphoopgmo";
treib9afc6212015-10-30 18:49:5895const char theme2_crx[] = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf";
96
treib65f103042015-12-03 10:21:3697SyncChangeList MakeSyncChangeList(const std::string& id,
98 const sync_pb::EntitySpecifics& specifics,
99 SyncChange::SyncChangeType change_type) {
100 syncer::SyncData sync_data =
101 syncer::SyncData::CreateLocalData(id, "Name", specifics);
102 return SyncChangeList(1, SyncChange(FROM_HERE, change_type, sync_data));
103}
104
asargente48ab752016-03-12 00:59:20105// This is a FakeSyncChangeProcessor specialization that maintains a store of
106// SyncData items in the superclass' data_ member variable, treating it like a
107// map keyed by the extension id from the SyncData. Each instance of this class
108// should only be used for one model type (which should be either extensions or
109// apps) to match how the real sync system handles things.
110class StatefulChangeProcessor : public syncer::FakeSyncChangeProcessor {
111 public:
112 explicit StatefulChangeProcessor(syncer::ModelType expected_type)
113 : expected_type_(expected_type) {
114 EXPECT_TRUE(expected_type == syncer::ModelType::EXTENSIONS ||
115 expected_type == syncer::ModelType::APPS);
116 }
117
118 ~StatefulChangeProcessor() override {}
119
120 // We let our parent class, FakeSyncChangeProcessor, handle saving the
121 // changes for us, but in addition we "apply" these changes by treating
122 // the FakeSyncChangeProcessor's SyncDataList as a map keyed by extension
123 // id.
124 syncer::SyncError ProcessSyncChanges(
125 const tracked_objects::Location& from_here,
126 const syncer::SyncChangeList& change_list) override {
127 syncer::FakeSyncChangeProcessor::ProcessSyncChanges(from_here, change_list);
128 for (const auto& change : change_list) {
129 syncer::SyncData sync_data = change.sync_data();
130 EXPECT_EQ(expected_type_, sync_data.GetDataType());
131
dchengc963c7142016-04-08 03:55:22132 std::unique_ptr<ExtensionSyncData> modified =
asargente48ab752016-03-12 00:59:20133 ExtensionSyncData::CreateFromSyncData(sync_data);
134
135 // Start by removing any existing entry for this extension id.
136 syncer::SyncDataList& data_list = data();
137 for (auto iter = data_list.begin(); iter != data_list.end(); ++iter) {
dchengc963c7142016-04-08 03:55:22138 std::unique_ptr<ExtensionSyncData> existing =
asargente48ab752016-03-12 00:59:20139 ExtensionSyncData::CreateFromSyncData(*iter);
140 if (existing->id() == modified->id()) {
141 data_list.erase(iter);
142 break;
143 }
144 }
145
146 // Now add in the new data for this id, if appropriate.
147 if (change.change_type() == SyncChange::ACTION_ADD ||
148 change.change_type() == SyncChange::ACTION_UPDATE) {
149 data_list.push_back(sync_data);
150 } else if (change.change_type() != SyncChange::ACTION_DELETE) {
151 ADD_FAILURE() << "Unexpected change type " << change.change_type();
152 }
153 }
154 return syncer::SyncError();
155 }
156
157 // We override this to help catch the error of trying to use a single
158 // StatefulChangeProcessor to process changes for both extensions and apps
159 // sync data.
160 syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override {
161 EXPECT_EQ(expected_type_, type);
162 return FakeSyncChangeProcessor::GetAllSyncData(type);
163 }
164
165 // This is a helper to vend a wrapped version of this object suitable for
166 // passing in to MergeDataAndStartSyncing, which takes a
dchengc963c7142016-04-08 03:55:22167 // std::unique_ptr<SyncChangeProcessor>, since in tests we typically don't
168 // want to
asargente48ab752016-03-12 00:59:20169 // give up ownership of a local change processor.
dchengc963c7142016-04-08 03:55:22170 std::unique_ptr<syncer::SyncChangeProcessor> GetWrapped() {
ricea91d6fc122016-08-30 08:47:14171 return base::MakeUnique<syncer::SyncChangeProcessorWrapperForTest>(this);
asargente48ab752016-03-12 00:59:20172 }
173
174 protected:
175 // The expected ModelType of changes that this processor will see.
176 syncer::ModelType expected_type_;
177
178 DISALLOW_COPY_AND_ASSIGN(StatefulChangeProcessor);
179};
180
treib65f103042015-12-03 10:21:36181} // namespace
182
treib9afc6212015-10-30 18:49:58183class ExtensionServiceSyncTest
184 : public extensions::ExtensionServiceTestWithInstall {
185 public:
186 void MockSyncStartFlare(bool* was_called,
187 syncer::ModelType* model_type_passed_in,
188 syncer::ModelType model_type) {
189 *was_called = true;
190 *model_type_passed_in = model_type;
191 }
192
asargente48ab752016-03-12 00:59:20193 // Helper to call MergeDataAndStartSyncing with no server data and dummy
194 // change processor / error factory.
195 void StartSyncing(syncer::ModelType type) {
196 ASSERT_TRUE(type == syncer::EXTENSIONS || type == syncer::APPS);
197 extension_sync_service()->MergeDataAndStartSyncing(
198 type, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14199 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
200 base::MakeUnique<syncer::SyncErrorFactoryMock>());
asargente48ab752016-03-12 00:59:20201 }
202
treib9afc6212015-10-30 18:49:58203 protected:
204 // Paths to some of the fake extensions.
205 base::FilePath good0_path() {
206 return data_dir()
207 .AppendASCII("good")
208 .AppendASCII("Extensions")
209 .AppendASCII(good0)
210 .AppendASCII("1.0.0.0");
211 }
212
213 ExtensionSyncService* extension_sync_service() {
214 return ExtensionSyncService::Get(profile());
215 }
216};
217
218TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledComponent) {
219 InitializeEmptyExtensionService();
220
221 bool flare_was_called = false;
222 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
223 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
224 extension_sync_service()->SetSyncStartFlareForTesting(
225 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
226 factory.GetWeakPtr(),
227 &flare_was_called, // Safe due to WeakPtrFactory scope.
228 &triggered_type)); // Safe due to WeakPtrFactory scope.
229
230 // Install a component extension.
231 std::string manifest;
232 ASSERT_TRUE(base::ReadFileToString(
233 good0_path().Append(extensions::kManifestFilename), &manifest));
234 service()->component_loader()->Add(manifest, good0_path());
235 ASSERT_FALSE(service()->is_ready());
236 service()->Init();
237 ASSERT_TRUE(service()->is_ready());
238
239 // Extensions added before service is_ready() don't trigger sync startup.
240 EXPECT_FALSE(flare_was_called);
241 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
242}
243
244TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledNormal) {
245 InitializeGoodInstalledExtensionService();
246
247 bool flare_was_called = false;
248 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
249 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
250 extension_sync_service()->SetSyncStartFlareForTesting(
251 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
252 factory.GetWeakPtr(),
253 &flare_was_called, // Safe due to WeakPtrFactory scope.
254 &triggered_type)); // Safe due to WeakPtrFactory scope.
255
256 ASSERT_FALSE(service()->is_ready());
257 service()->Init();
258 ASSERT_EQ(3u, loaded_.size());
259 ASSERT_TRUE(service()->is_ready());
260
261 // Extensions added before service is_ready() don't trigger sync startup.
262 EXPECT_FALSE(flare_was_called);
263 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
264}
265
266TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupOnInstall) {
267 InitializeEmptyExtensionService();
268 service()->Init();
269 ASSERT_TRUE(service()->is_ready());
270
271 bool flare_was_called = false;
272 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
273 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
274 extension_sync_service()->SetSyncStartFlareForTesting(
275 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
276 factory.GetWeakPtr(),
277 &flare_was_called, // Safe due to WeakPtrFactory scope.
278 &triggered_type)); // Safe due to WeakPtrFactory scope.
279
280 base::FilePath path = data_dir().AppendASCII("good.crx");
281 InstallCRX(path, INSTALL_NEW);
282
283 EXPECT_TRUE(flare_was_called);
284 EXPECT_EQ(syncer::EXTENSIONS, triggered_type);
285
286 // Reset.
287 flare_was_called = false;
288 triggered_type = syncer::UNSPECIFIED;
289
290 // Once sync starts, flare should no longer be invoked.
291 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36292 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14293 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
294 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58295 path = data_dir().AppendASCII("page_action.crx");
296 InstallCRX(path, INSTALL_NEW);
297 EXPECT_FALSE(flare_was_called);
298 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
299}
300
301TEST_F(ExtensionServiceSyncTest, DisableExtensionFromSync) {
302 // Start the extensions service with one external extension already installed.
303 base::FilePath source_install_dir =
304 data_dir().AppendASCII("good").AppendASCII("Extensions");
305 base::FilePath pref_path =
306 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
307
308 InitializeInstalledExtensionService(pref_path, source_install_dir);
309
310 // The user has enabled sync.
maxbogue0a379452016-09-22 21:35:05311 browser_sync::ProfileSyncService* sync_service =
treib9afc6212015-10-30 18:49:58312 ProfileSyncServiceFactory::GetForProfile(profile());
maxboguefe00952a2016-01-19 19:02:01313 sync_service->SetFirstSetupComplete();
treib9afc6212015-10-30 18:49:58314
315 service()->Init();
316 ASSERT_TRUE(service()->is_ready());
317
318 ASSERT_EQ(3u, loaded_.size());
319
320 // We start enabled.
321 const Extension* extension = service()->GetExtensionById(good0, true);
322 ASSERT_TRUE(extension);
323 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
324
325 // Sync starts up.
326 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36327 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14328 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
329 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58330
331 // Then sync data arrives telling us to disable |good0|.
332 ExtensionSyncData disable_good_crx(*extension, false,
333 Extension::DISABLE_USER_ACTION, false,
mamir192d7882016-06-22 17:10:16334 false, ExtensionSyncData::BOOLEAN_UNSET,
335 false);
treib65f103042015-12-03 10:21:36336 SyncChangeList list(
337 1, disable_good_crx.GetSyncChange(SyncChange::ACTION_UPDATE));
treib9afc6212015-10-30 18:49:58338 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
339
340 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
341}
342
343TEST_F(ExtensionServiceSyncTest, IgnoreSyncChangesWhenLocalStateIsMoreRecent) {
344 // Start the extension service with three extensions already installed.
345 base::FilePath source_install_dir =
346 data_dir().AppendASCII("good").AppendASCII("Extensions");
347 base::FilePath pref_path =
348 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
349
350 InitializeInstalledExtensionService(pref_path, source_install_dir);
351
352 // The user has enabled sync.
maxbogue0a379452016-09-22 21:35:05353 browser_sync::ProfileSyncService* sync_service =
treib9afc6212015-10-30 18:49:58354 ProfileSyncServiceFactory::GetForProfile(profile());
maxboguefe00952a2016-01-19 19:02:01355 sync_service->SetFirstSetupComplete();
treib9afc6212015-10-30 18:49:58356 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
357 extension_sync_service();
358
359 service()->Init();
360 ASSERT_TRUE(service()->is_ready());
361 ASSERT_EQ(3u, loaded_.size());
362
363 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
364 ASSERT_TRUE(service()->IsExtensionEnabled(good2));
365
366 // Disable and re-enable good0 before first sync data arrives.
367 service()->DisableExtension(good0, Extension::DISABLE_USER_ACTION);
368 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
369 service()->EnableExtension(good0);
370 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
371 // Disable good2 before first sync data arrives (good1 is considered
372 // non-syncable because it has plugin permission).
373 service()->DisableExtension(good2, Extension::DISABLE_USER_ACTION);
374 ASSERT_FALSE(service()->IsExtensionEnabled(good2));
375
376 const Extension* extension0 = service()->GetExtensionById(good0, true);
377 const Extension* extension2 = service()->GetExtensionById(good2, true);
378 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension0));
379 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension2));
380
381 // Now sync data comes in that says to disable good0 and enable good2.
382 ExtensionSyncData disable_good0(*extension0, false,
383 Extension::DISABLE_USER_ACTION, false, false,
mamir192d7882016-06-22 17:10:16384 ExtensionSyncData::BOOLEAN_UNSET, false);
treib9afc6212015-10-30 18:49:58385 ExtensionSyncData enable_good2(*extension2, true, Extension::DISABLE_NONE,
386 false, false,
mamir192d7882016-06-22 17:10:16387 ExtensionSyncData::BOOLEAN_UNSET, false);
treib9afc6212015-10-30 18:49:58388 syncer::SyncDataList sync_data;
389 sync_data.push_back(disable_good0.GetSyncData());
390 sync_data.push_back(enable_good2.GetSyncData());
391 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:22392 syncer::EXTENSIONS, sync_data,
ricea91d6fc122016-08-30 08:47:14393 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
394 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58395
396 // Both sync changes should be ignored, since the local state was changed
397 // before sync started, and so the local state is considered more recent.
398 EXPECT_TRUE(service()->IsExtensionEnabled(good0));
399 EXPECT_FALSE(service()->IsExtensionEnabled(good2));
400}
401
treibb794dd52015-12-01 18:47:14402TEST_F(ExtensionServiceSyncTest, DontSelfNotify) {
403 // Start the extension service with three extensions already installed.
404 base::FilePath source_install_dir =
405 data_dir().AppendASCII("good").AppendASCII("Extensions");
406 base::FilePath pref_path =
407 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
408
409 InitializeInstalledExtensionService(pref_path, source_install_dir);
410
411 // The user has enabled sync.
maxboguefe00952a2016-01-19 19:02:01412 ProfileSyncServiceFactory::GetForProfile(profile())->SetFirstSetupComplete();
treibb794dd52015-12-01 18:47:14413 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
414 extension_sync_service();
415
416 service()->Init();
417 ASSERT_TRUE(service()->is_ready());
418 ASSERT_EQ(3u, loaded_.size());
419 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
420
421 syncer::FakeSyncChangeProcessor* processor =
422 new syncer::FakeSyncChangeProcessor;
423 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:22424 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
ricea91d6fc122016-08-30 08:47:14425 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treibb794dd52015-12-01 18:47:14426
427 processor->changes().clear();
428
429 // Simulate various incoming sync changes, and make sure they don't result in
430 // any outgoing changes.
431
432 {
433 const Extension* extension = service()->GetExtensionById(good0, true);
434 ASSERT_TRUE(extension);
435
436 // Disable the extension.
437 ExtensionSyncData data(*extension, false, Extension::DISABLE_USER_ACTION,
mamir192d7882016-06-22 17:10:16438 false, false, ExtensionSyncData::BOOLEAN_UNSET,
439 false);
treib65f103042015-12-03 10:21:36440 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14441
442 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
443
444 EXPECT_TRUE(processor->changes().empty());
445 }
446
447 {
448 const Extension* extension = service()->GetExtensionById(good0, true);
449 ASSERT_TRUE(extension);
450
451 // Set incognito enabled to true.
452 ExtensionSyncData data(*extension, false, Extension::DISABLE_NONE, true,
mamir192d7882016-06-22 17:10:16453 false, ExtensionSyncData::BOOLEAN_UNSET, false);
treib65f103042015-12-03 10:21:36454 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14455
456 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
457
458 EXPECT_TRUE(processor->changes().empty());
459 }
460
461 {
462 const Extension* extension = service()->GetExtensionById(good0, true);
463 ASSERT_TRUE(extension);
464
465 // Add another disable reason.
466 ExtensionSyncData data(*extension, false,
467 Extension::DISABLE_USER_ACTION |
468 Extension::DISABLE_PERMISSIONS_INCREASE,
mamir192d7882016-06-22 17:10:16469 false, false, ExtensionSyncData::BOOLEAN_UNSET,
470 false);
treib65f103042015-12-03 10:21:36471 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14472
473 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
474
475 EXPECT_TRUE(processor->changes().empty());
476 }
477
478 {
479 const Extension* extension = service()->GetExtensionById(good0, true);
480 ASSERT_TRUE(extension);
481
482 // Uninstall the extension.
483 ExtensionSyncData data(*extension, false,
484 Extension::DISABLE_USER_ACTION |
485 Extension::DISABLE_PERMISSIONS_INCREASE,
mamir192d7882016-06-22 17:10:16486 false, false, ExtensionSyncData::BOOLEAN_UNSET,
487 false);
treib65f103042015-12-03 10:21:36488 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_DELETE));
treibb794dd52015-12-01 18:47:14489
490 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
491
492 EXPECT_TRUE(processor->changes().empty());
493 }
494}
495
treib9afc6212015-10-30 18:49:58496TEST_F(ExtensionServiceSyncTest, GetSyncData) {
497 InitializeEmptyExtensionService();
498 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
499 const Extension* extension = service()->GetInstalledExtension(good_crx);
500 ASSERT_TRUE(extension);
501
502 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36503 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14504 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
505 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58506
507 syncer::SyncDataList list =
508 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
509 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22510 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58511 ExtensionSyncData::CreateFromSyncData(list[0]);
512 ASSERT_TRUE(data.get());
513 EXPECT_EQ(extension->id(), data->id());
514 EXPECT_FALSE(data->uninstalled());
515 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
516 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
517 data->incognito_enabled());
518 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
robpercivaldcd8b102016-01-25 19:39:00519 EXPECT_EQ(data->version(), *extension->version());
treib9afc6212015-10-30 18:49:58520 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
521 data->update_url());
522 EXPECT_EQ(extension->name(), data->name());
523}
524
treib29e1b9b12015-11-11 08:50:56525TEST_F(ExtensionServiceSyncTest, GetSyncDataDisableReasons) {
526 InitializeEmptyExtensionService();
527 const Extension* extension =
528 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
529 ASSERT_TRUE(extension);
530
treib29e1b9b12015-11-11 08:50:56531 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36532 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14533 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
534 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib29e1b9b12015-11-11 08:50:56535
536 {
537 syncer::SyncDataList list =
538 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
539 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22540 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56541 ExtensionSyncData::CreateFromSyncData(list[0]);
542 ASSERT_TRUE(data.get());
543 EXPECT_TRUE(data->enabled());
544 EXPECT_TRUE(data->supports_disable_reasons());
545 EXPECT_EQ(Extension::DISABLE_NONE, data->disable_reasons());
546 }
547
548 // Syncable disable reason, should propagate to sync.
549 service()->DisableExtension(good_crx, Extension::DISABLE_USER_ACTION);
550 {
551 syncer::SyncDataList list =
552 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
553 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22554 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56555 ExtensionSyncData::CreateFromSyncData(list[0]);
556 ASSERT_TRUE(data.get());
557 EXPECT_FALSE(data->enabled());
558 EXPECT_TRUE(data->supports_disable_reasons());
559 EXPECT_EQ(Extension::DISABLE_USER_ACTION, data->disable_reasons());
560 }
561 service()->EnableExtension(good_crx);
562
563 // Non-syncable disable reason. The sync data should still say "enabled".
564 service()->DisableExtension(good_crx, Extension::DISABLE_RELOAD);
565 {
566 syncer::SyncDataList list =
567 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
568 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22569 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56570 ExtensionSyncData::CreateFromSyncData(list[0]);
571 ASSERT_TRUE(data.get());
572 EXPECT_TRUE(data->enabled());
573 EXPECT_TRUE(data->supports_disable_reasons());
574 EXPECT_EQ(Extension::DISABLE_NONE, data->disable_reasons());
575 }
576 service()->EnableExtension(good_crx);
577
578 // Both a syncable and a non-syncable disable reason, only the former should
579 // propagate to sync.
580 service()->DisableExtension(
581 good_crx, Extension::DISABLE_USER_ACTION | Extension::DISABLE_RELOAD);
582 {
583 syncer::SyncDataList list =
584 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
585 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22586 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56587 ExtensionSyncData::CreateFromSyncData(list[0]);
588 ASSERT_TRUE(data.get());
589 EXPECT_FALSE(data->enabled());
590 EXPECT_TRUE(data->supports_disable_reasons());
591 EXPECT_EQ(Extension::DISABLE_USER_ACTION, data->disable_reasons());
592 }
593 service()->EnableExtension(good_crx);
594}
595
treib9afc6212015-10-30 18:49:58596TEST_F(ExtensionServiceSyncTest, GetSyncDataTerminated) {
597 InitializeEmptyExtensionService();
598 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
599 TerminateExtension(good_crx);
600 const Extension* extension = service()->GetInstalledExtension(good_crx);
601 ASSERT_TRUE(extension);
602
treib9afc6212015-10-30 18:49:58603 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36604 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14605 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
606 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58607
608 syncer::SyncDataList list =
609 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
610 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22611 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58612 ExtensionSyncData::CreateFromSyncData(list[0]);
613 ASSERT_TRUE(data.get());
614 EXPECT_EQ(extension->id(), data->id());
615 EXPECT_FALSE(data->uninstalled());
616 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
617 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
618 data->incognito_enabled());
619 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
robpercivaldcd8b102016-01-25 19:39:00620 EXPECT_EQ(data->version(), *extension->version());
treib9afc6212015-10-30 18:49:58621 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
622 data->update_url());
623 EXPECT_EQ(extension->name(), data->name());
624}
625
626TEST_F(ExtensionServiceSyncTest, GetSyncDataFilter) {
627 InitializeEmptyExtensionService();
628 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
629 const Extension* extension = service()->GetInstalledExtension(good_crx);
630 ASSERT_TRUE(extension);
631
treib9afc6212015-10-30 18:49:58632 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36633 syncer::APPS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14634 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
635 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58636
637 syncer::SyncDataList list =
638 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
639 ASSERT_EQ(list.size(), 0U);
640}
641
642TEST_F(ExtensionServiceSyncTest, GetSyncExtensionDataUserSettings) {
643 InitializeEmptyExtensionService();
644 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
645 const Extension* extension = service()->GetInstalledExtension(good_crx);
646 ASSERT_TRUE(extension);
647
treib9afc6212015-10-30 18:49:58648 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36649 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14650 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
651 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58652
653 {
654 syncer::SyncDataList list =
655 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
656 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22657 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58658 ExtensionSyncData::CreateFromSyncData(list[0]);
659 ASSERT_TRUE(data.get());
660 EXPECT_TRUE(data->enabled());
661 EXPECT_FALSE(data->incognito_enabled());
662 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
663 }
664
665 service()->DisableExtension(good_crx, Extension::DISABLE_USER_ACTION);
666 {
667 syncer::SyncDataList list =
668 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
669 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22670 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58671 ExtensionSyncData::CreateFromSyncData(list[0]);
672 ASSERT_TRUE(data.get());
673 EXPECT_FALSE(data->enabled());
674 EXPECT_FALSE(data->incognito_enabled());
675 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
676 }
677
678 extensions::util::SetIsIncognitoEnabled(good_crx, profile(), true);
rdevlin.cronind01837b2016-08-17 01:37:18679 ScriptingPermissionsModifier permissions_modifier(
680 profile(), registry()->GetExtensionById(
681 good_crx, extensions::ExtensionRegistry::EVERYTHING));
682 permissions_modifier.SetAllowedOnAllUrls(false);
treib9afc6212015-10-30 18:49:58683 {
684 syncer::SyncDataList list =
685 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
686 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22687 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58688 ExtensionSyncData::CreateFromSyncData(list[0]);
689 ASSERT_TRUE(data.get());
690 EXPECT_FALSE(data->enabled());
691 EXPECT_TRUE(data->incognito_enabled());
692 EXPECT_EQ(ExtensionSyncData::BOOLEAN_FALSE, data->all_urls_enabled());
693 }
694
695 service()->EnableExtension(good_crx);
rdevlin.cronind01837b2016-08-17 01:37:18696 permissions_modifier.SetAllowedOnAllUrls(true);
treib9afc6212015-10-30 18:49:58697 {
698 syncer::SyncDataList list =
699 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
700 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22701 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58702 ExtensionSyncData::CreateFromSyncData(list[0]);
703 ASSERT_TRUE(data.get());
704 EXPECT_TRUE(data->enabled());
705 EXPECT_TRUE(data->incognito_enabled());
706 EXPECT_EQ(ExtensionSyncData::BOOLEAN_TRUE, data->all_urls_enabled());
707 }
708}
709
710TEST_F(ExtensionServiceSyncTest, SyncForUninstalledExternalExtension) {
711 InitializeEmptyExtensionService();
catmullings22bc2372016-11-02 19:59:35712 InstallCRX(data_dir().AppendASCII("good.crx"), Manifest::EXTERNAL_PREF,
713 INSTALL_NEW, Extension::NO_FLAGS);
treib9afc6212015-10-30 18:49:58714 const Extension* extension = service()->GetInstalledExtension(good_crx);
715 ASSERT_TRUE(extension);
716
treib9afc6212015-10-30 18:49:58717 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36718 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14719 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
720 base::MakeUnique<syncer::SyncErrorFactoryMock>());
asargente48ab752016-03-12 00:59:20721 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:58722
723 UninstallExtension(good_crx, false);
724 EXPECT_TRUE(
725 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
726
727 sync_pb::EntitySpecifics specifics;
728 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
729 sync_pb::ExtensionSpecifics* extension_specifics =
730 app_specifics->mutable_extension();
731 extension_specifics->set_id(good_crx);
732 extension_specifics->set_version("1.0");
733 extension_specifics->set_enabled(true);
734
treib65f103042015-12-03 10:21:36735 SyncChangeList list =
736 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:58737
738 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
739 EXPECT_TRUE(
740 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
741}
742
743TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettings) {
744 InitializeEmptyExtensionService();
745 const Extension* app =
746 PackAndInstallCRX(data_dir().AppendASCII("app"), INSTALL_NEW);
747 ASSERT_TRUE(app);
748 ASSERT_TRUE(app->is_app());
749
treib9afc6212015-10-30 18:49:58750 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36751 syncer::APPS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14752 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
753 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58754
755 syncer::StringOrdinal initial_ordinal =
756 syncer::StringOrdinal::CreateInitialOrdinal();
757 {
758 syncer::SyncDataList list =
759 extension_sync_service()->GetAllSyncData(syncer::APPS);
760 ASSERT_EQ(list.size(), 1U);
761
dchengc963c7142016-04-08 03:55:22762 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58763 ExtensionSyncData::CreateFromSyncData(list[0]);
764 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->app_launch_ordinal()));
765 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
766 }
767
deepak.m14ba69e62015-11-17 05:42:12768 AppSorting* sorting = ExtensionSystem::Get(profile())->app_sorting();
treib9afc6212015-10-30 18:49:58769 sorting->SetAppLaunchOrdinal(app->id(), initial_ordinal.CreateAfter());
770 {
771 syncer::SyncDataList list =
772 extension_sync_service()->GetAllSyncData(syncer::APPS);
773 ASSERT_EQ(list.size(), 1U);
774
dchengc963c7142016-04-08 03:55:22775 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58776 ExtensionSyncData::CreateFromSyncData(list[0]);
777 ASSERT_TRUE(app_sync_data.get());
778 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
779 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
780 }
781
782 sorting->SetPageOrdinal(app->id(), initial_ordinal.CreateAfter());
783 {
784 syncer::SyncDataList list =
785 extension_sync_service()->GetAllSyncData(syncer::APPS);
786 ASSERT_EQ(list.size(), 1U);
787
dchengc963c7142016-04-08 03:55:22788 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58789 ExtensionSyncData::CreateFromSyncData(list[0]);
790 ASSERT_TRUE(app_sync_data.get());
791 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
792 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->page_ordinal()));
793 }
794}
795
796// TODO (rdevlin.cronin): The OnExtensionMoved() method has been removed from
797// ExtensionService, so this test probably needs a new home. Unfortunately, it
798// relies pretty heavily on things like InitializeExtension[Sync]Service() and
799// PackAndInstallCRX(). When we clean up a bit more, this should move out.
800TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettingsOnExtensionMoved) {
801 InitializeEmptyExtensionService();
802 const size_t kAppCount = 3;
803 const Extension* apps[kAppCount];
804 apps[0] = PackAndInstallCRX(data_dir().AppendASCII("app1"), INSTALL_NEW);
805 apps[1] = PackAndInstallCRX(data_dir().AppendASCII("app2"), INSTALL_NEW);
806 apps[2] = PackAndInstallCRX(data_dir().AppendASCII("app4"), INSTALL_NEW);
807 for (size_t i = 0; i < kAppCount; ++i) {
808 ASSERT_TRUE(apps[i]);
809 ASSERT_TRUE(apps[i]->is_app());
810 }
811
treib9afc6212015-10-30 18:49:58812 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36813 syncer::APPS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22814 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
815 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58816
deepak.m14ba69e62015-11-17 05:42:12817 ExtensionSystem::Get(service()->GetBrowserContext())
treib9afc6212015-10-30 18:49:58818 ->app_sorting()
819 ->OnExtensionMoved(apps[0]->id(), apps[1]->id(), apps[2]->id());
820 {
821 syncer::SyncDataList list =
822 extension_sync_service()->GetAllSyncData(syncer::APPS);
823 ASSERT_EQ(list.size(), 3U);
824
dchengc963c7142016-04-08 03:55:22825 std::unique_ptr<ExtensionSyncData> data[kAppCount];
treib9afc6212015-10-30 18:49:58826 for (size_t i = 0; i < kAppCount; ++i) {
827 data[i] = ExtensionSyncData::CreateFromSyncData(list[i]);
828 ASSERT_TRUE(data[i].get());
829 }
830
831 // The sync data is not always in the same order our apps were installed in,
832 // so we do that sorting here so we can make sure the values are changed as
833 // expected.
834 syncer::StringOrdinal app_launch_ordinals[kAppCount];
835 for (size_t i = 0; i < kAppCount; ++i) {
836 for (size_t j = 0; j < kAppCount; ++j) {
837 if (apps[i]->id() == data[j]->id())
838 app_launch_ordinals[i] = data[j]->app_launch_ordinal();
839 }
840 }
841
842 EXPECT_TRUE(app_launch_ordinals[1].LessThan(app_launch_ordinals[0]));
843 EXPECT_TRUE(app_launch_ordinals[0].LessThan(app_launch_ordinals[2]));
844 }
845}
846
847TEST_F(ExtensionServiceSyncTest, GetSyncDataList) {
848 InitializeEmptyExtensionService();
849 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
850 InstallCRX(data_dir().AppendASCII("page_action.crx"), INSTALL_NEW);
851 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
852 InstallCRX(data_dir().AppendASCII("theme2.crx"), INSTALL_NEW);
853
treib9afc6212015-10-30 18:49:58854 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36855 syncer::APPS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14856 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
857 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58858 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36859 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14860 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
861 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58862
863 service()->DisableExtension(page_action, Extension::DISABLE_USER_ACTION);
864 TerminateExtension(theme2_crx);
865
866 EXPECT_EQ(0u, extension_sync_service()->GetAllSyncData(syncer::APPS).size());
867 EXPECT_EQ(
868 2u, extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS).size());
869}
870
871TEST_F(ExtensionServiceSyncTest, ProcessSyncDataUninstall) {
872 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:58873 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36874 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14875 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
876 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58877
878 sync_pb::EntitySpecifics specifics;
879 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
880 ext_specifics->set_id(good_crx);
881 ext_specifics->set_version("1.0");
treib65f103042015-12-03 10:21:36882
883 SyncChangeList list =
884 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:58885
886 // Should do nothing.
887 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
888 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
889
890 // Install the extension.
891 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
892 InstallCRX(extension_path, INSTALL_NEW);
893 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
894
895 // Should uninstall the extension.
896 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
897 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
898
899 // Should again do nothing.
900 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
901 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
902}
903
904TEST_F(ExtensionServiceSyncTest, ProcessSyncDataWrongType) {
905 InitializeEmptyExtensionService();
asargente48ab752016-03-12 00:59:20906 StartSyncing(syncer::EXTENSIONS);
907 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:58908
909 // Install the extension.
910 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
911 InstallCRX(extension_path, INSTALL_NEW);
912 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
913
914 sync_pb::EntitySpecifics specifics;
915 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
916 sync_pb::ExtensionSpecifics* extension_specifics =
917 app_specifics->mutable_extension();
918 extension_specifics->set_id(good_crx);
919 extension_specifics->set_version(
920 service()->GetInstalledExtension(good_crx)->version()->GetString());
921
922 {
923 extension_specifics->set_enabled(true);
treib65f103042015-12-03 10:21:36924
925 SyncChangeList list =
926 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:58927
928 // Should do nothing
929 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
930 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
931 }
932
933 {
934 extension_specifics->set_enabled(false);
treib65f103042015-12-03 10:21:36935
936 SyncChangeList list =
937 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:58938
939 // Should again do nothing.
940 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
941 EXPECT_TRUE(service()->GetExtensionById(good_crx, false));
942 }
943}
944
945TEST_F(ExtensionServiceSyncTest, ProcessSyncDataSettings) {
946 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:58947 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36948 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:14949 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
950 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:58951
952 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
953 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
954 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
rdevlin.cronind01837b2016-08-17 01:37:18955 // Returns a ScriptingPermissionsModifier for the extension. We use this
956 // because various parts of this test reload the extension, making keeping a
957 // ptr to it inviable.
958 auto get_permissions_modifier = [this]() {
959 const Extension* extension = registry()->GetExtensionById(
960 good_crx, extensions::ExtensionRegistry::EVERYTHING);
961 return base::MakeUnique<ScriptingPermissionsModifier>(profile(), extension);
962 };
963 EXPECT_FALSE(get_permissions_modifier()->HasSetAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:58964 const bool kDefaultAllowedScripting =
rdevlin.cronind01837b2016-08-17 01:37:18965 ScriptingPermissionsModifier::DefaultAllowedOnAllUrls();
treib9afc6212015-10-30 18:49:58966 EXPECT_EQ(kDefaultAllowedScripting,
rdevlin.cronind01837b2016-08-17 01:37:18967 get_permissions_modifier()->IsAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:58968
969 sync_pb::EntitySpecifics specifics;
970 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
971 ext_specifics->set_id(good_crx);
972 ext_specifics->set_version(
973 service()->GetInstalledExtension(good_crx)->version()->GetString());
974 ext_specifics->set_enabled(false);
975
976 {
treib65f103042015-12-03 10:21:36977 SyncChangeList list =
978 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
979
treib9afc6212015-10-30 18:49:58980 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
981 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
982 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
rdevlin.cronind01837b2016-08-17 01:37:18983 EXPECT_FALSE(get_permissions_modifier()->HasSetAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:58984 EXPECT_EQ(kDefaultAllowedScripting,
rdevlin.cronind01837b2016-08-17 01:37:18985 get_permissions_modifier()->IsAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:58986 }
987
988 {
989 ext_specifics->set_enabled(true);
990 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:36991
992 SyncChangeList list =
993 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
994
treib9afc6212015-10-30 18:49:58995 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
996 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
997 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
998 }
999
1000 {
1001 ext_specifics->set_enabled(false);
1002 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361003
1004 SyncChangeList list =
1005 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1006
treib9afc6212015-10-30 18:49:581007 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1008 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1009 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1010 }
1011
1012 {
1013 ext_specifics->set_enabled(true);
1014 ext_specifics->set_all_urls_enabled(!kDefaultAllowedScripting);
treib65f103042015-12-03 10:21:361015
1016 SyncChangeList list =
1017 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1018
treib9afc6212015-10-30 18:49:581019 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1020 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
rdevlin.cronind01837b2016-08-17 01:37:181021 EXPECT_TRUE(get_permissions_modifier()->HasSetAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:581022 EXPECT_EQ(!kDefaultAllowedScripting,
rdevlin.cronind01837b2016-08-17 01:37:181023 get_permissions_modifier()->IsAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:581024 }
1025
1026 {
1027 ext_specifics->set_all_urls_enabled(kDefaultAllowedScripting);
treib65f103042015-12-03 10:21:361028
1029 SyncChangeList list =
1030 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1031
treib9afc6212015-10-30 18:49:581032 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1033 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
rdevlin.cronind01837b2016-08-17 01:37:181034 EXPECT_TRUE(get_permissions_modifier()->HasSetAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:581035 EXPECT_EQ(kDefaultAllowedScripting,
rdevlin.cronind01837b2016-08-17 01:37:181036 get_permissions_modifier()->IsAllowedOnAllUrls());
treib9afc6212015-10-30 18:49:581037 }
1038
1039 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1040}
1041
1042TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNewExtension) {
1043 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581044 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361045 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141046 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1047 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581048
1049 const base::FilePath path = data_dir().AppendASCII("good.crx");
1050 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1051
1052 struct TestCase {
1053 const char* name; // For failure output only.
1054 bool sync_enabled; // The "enabled" flag coming in from Sync.
1055 // The disable reason(s) coming in from Sync, or -1 for "not set".
1056 int sync_disable_reasons;
1057 // The disable reason(s) that should be set on the installed extension.
1058 // This will usually be the same as |sync_disable_reasons|, but see the
1059 // "Legacy" case.
1060 int expect_disable_reasons;
1061 // Whether the extension's permissions should be auto-granted during
1062 // installation.
1063 bool expect_permissions_granted;
1064 } test_cases[] = {
1065 // Standard case: Extension comes in enabled; permissions should be granted
1066 // during installation.
1067 { "Standard", true, 0, 0, true },
1068 // If the extension comes in disabled, its permissions should still be
1069 // granted (the user already approved them on another machine).
1070 { "Disabled", false, Extension::DISABLE_USER_ACTION,
1071 Extension::DISABLE_USER_ACTION, true },
1072 // Legacy case (<M45): No disable reasons come in from Sync (see
1073 // crbug.com/484214). After installation, the reason should be set to
treib3b91e9f2015-11-04 11:29:411074 // DISABLE_USER_ACTION (default assumption).
1075 { "Legacy", false, -1, Extension::DISABLE_USER_ACTION, true },
treib9afc6212015-10-30 18:49:581076 // If the extension came in disabled due to a permissions increase, then the
1077 // user has *not* approved the permissions, and they shouldn't be granted.
1078 // crbug.com/484214
1079 { "PermissionsIncrease", false, Extension::DISABLE_PERMISSIONS_INCREASE,
1080 Extension::DISABLE_PERMISSIONS_INCREASE, false },
1081 };
1082
1083 for (const TestCase& test_case : test_cases) {
1084 SCOPED_TRACE(test_case.name);
1085
1086 sync_pb::EntitySpecifics specifics;
1087 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1088 ext_specifics->set_id(good_crx);
1089 ext_specifics->set_version(base::Version("1").GetString());
1090 ext_specifics->set_enabled(test_case.sync_enabled);
1091 if (test_case.sync_disable_reasons != -1)
1092 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1093
treib65f103042015-12-03 10:21:361094 SyncChangeList list =
1095 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1096
treib9afc6212015-10-30 18:49:581097 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1098
1099 ASSERT_TRUE(service()->pending_extension_manager()->IsIdPending(good_crx));
1100 UpdateExtension(good_crx, path, test_case.sync_enabled ? ENABLED
1101 : DISABLED);
1102 EXPECT_EQ(test_case.expect_disable_reasons,
1103 prefs->GetDisableReasons(good_crx));
dchengc963c7142016-04-08 03:55:221104 std::unique_ptr<const PermissionSet> permissions =
treib9afc6212015-10-30 18:49:581105 prefs->GetGrantedPermissions(good_crx);
1106 EXPECT_EQ(test_case.expect_permissions_granted, !permissions->IsEmpty());
1107 ASSERT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1108
1109 // Remove the extension again, so we can install it again for the next case.
1110 UninstallExtension(good_crx, false,
1111 test_case.sync_enabled ? Extension::ENABLED
1112 : Extension::DISABLED);
1113 }
1114}
1115
1116TEST_F(ExtensionServiceSyncTest, ProcessSyncDataTerminatedExtension) {
1117 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581118 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361119 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141120 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1121 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581122
1123 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1124 TerminateExtension(good_crx);
1125 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1126 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1127
1128 sync_pb::EntitySpecifics specifics;
1129 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1130 ext_specifics->set_id(good_crx);
1131 ext_specifics->set_version(
1132 service()->GetInstalledExtension(good_crx)->version()->GetString());
1133 ext_specifics->set_enabled(false);
1134 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361135
1136 SyncChangeList list =
1137 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581138
1139 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1140 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1141 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1142
1143 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1144}
1145
1146TEST_F(ExtensionServiceSyncTest, ProcessSyncDataVersionCheck) {
1147 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581148 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361149 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141150 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1151 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581152
1153 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1154 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1155 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1156
1157 sync_pb::EntitySpecifics specifics;
1158 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1159 ext_specifics->set_id(good_crx);
1160 ext_specifics->set_enabled(true);
1161
1162 const base::Version installed_version =
1163 *service()->GetInstalledExtension(good_crx)->version();
1164
1165 {
1166 ext_specifics->set_version(installed_version.GetString());
treib65f103042015-12-03 10:21:361167
1168 SyncChangeList list =
1169 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581170
1171 // Should do nothing if extension version == sync version.
1172 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1173 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1174 // Make sure the version we'll send back to sync didn't change.
1175 syncer::SyncDataList data =
1176 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1177 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221178 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581179 ExtensionSyncData::CreateFromSyncData(data[0]);
1180 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001181 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581182 }
1183
1184 // Should do nothing if extension version > sync version.
1185 {
1186 ext_specifics->set_version("0.0.0.0");
treib65f103042015-12-03 10:21:361187
1188 SyncChangeList list =
1189 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581190
1191 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1192 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1193 // Make sure the version we'll send back to sync didn't change.
1194 syncer::SyncDataList data =
1195 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1196 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221197 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581198 ExtensionSyncData::CreateFromSyncData(data[0]);
1199 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001200 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581201 }
1202
1203 // Should kick off an update if extension version < sync version.
1204 {
1205 const base::Version new_version("9.9.9.9");
1206 ext_specifics->set_version(new_version.GetString());
treib65f103042015-12-03 10:21:361207
1208 SyncChangeList list =
1209 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581210
1211 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1212 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1213 // Make sure that we'll send the NEW version back to sync, even though we
1214 // haven't actually updated yet. This is to prevent the data in sync from
1215 // flip-flopping back and forth until all clients are up to date.
1216 syncer::SyncDataList data =
1217 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1218 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221219 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581220 ExtensionSyncData::CreateFromSyncData(data[0]);
1221 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001222 EXPECT_EQ(new_version, extension_data->version());
treib9afc6212015-10-30 18:49:581223 }
1224
1225 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1226}
1227
1228TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNotInstalled) {
1229 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581230 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361231 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141232 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1233 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581234
1235 sync_pb::EntitySpecifics specifics;
1236 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1237 ext_specifics->set_id(good_crx);
1238 ext_specifics->set_enabled(false);
1239 ext_specifics->set_incognito_enabled(true);
1240 ext_specifics->set_update_url("http://www.google.com/");
1241 ext_specifics->set_version("1.2.3.4");
treib65f103042015-12-03 10:21:361242
1243 SyncChangeList list =
1244 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581245
1246 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1247 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1248 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1249 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1250 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1251 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1252
1253 const extensions::PendingExtensionInfo* info;
1254 EXPECT_TRUE(
1255 (info = service()->pending_extension_manager()->GetById(good_crx)));
1256 EXPECT_EQ(ext_specifics->update_url(), info->update_url().spec());
1257 EXPECT_TRUE(info->is_from_sync());
1258 EXPECT_EQ(Manifest::INTERNAL, info->install_source());
1259 // TODO(akalin): Figure out a way to test |info.ShouldAllowInstall()|.
1260}
1261
1262TEST_F(ExtensionServiceSyncTest, ProcessSyncDataEnableDisable) {
1263 InitializeEmptyExtensionService();
1264 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361265 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141266 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1267 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581268
1269 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1270
1271 struct TestCase {
1272 const char* name; // For failure output only.
1273 // Set of disable reasons before any Sync data comes in. If this is != 0,
1274 // the extension is disabled.
1275 int previous_disable_reasons;
1276 bool sync_enable; // The enabled flag coming in from Sync.
1277 // The disable reason(s) coming in from Sync, or -1 for "not set".
1278 int sync_disable_reasons;
1279 // The expected set of disable reasons after processing the Sync update. The
1280 // extension should be disabled iff this is != 0.
1281 int expect_disable_reasons;
1282 } test_cases[] = {
1283 { "NopEnable", 0, true, 0, 0 },
1284 { "NopDisable", Extension::DISABLE_USER_ACTION, false,
1285 Extension::DISABLE_USER_ACTION, Extension::DISABLE_USER_ACTION },
treib29e1b9b12015-11-11 08:50:561286 { "Enable", Extension::DISABLE_USER_ACTION, true, 0, 0 },
treib9afc6212015-10-30 18:49:581287 { "Disable", 0, false, Extension::DISABLE_USER_ACTION,
1288 Extension::DISABLE_USER_ACTION },
treib9afc6212015-10-30 18:49:581289 { "AddDisableReason", Extension::DISABLE_REMOTE_INSTALL, false,
1290 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION,
1291 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION },
treib9afc6212015-10-30 18:49:581292 { "RemoveDisableReason",
1293 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION, false,
1294 Extension::DISABLE_USER_ACTION, Extension::DISABLE_USER_ACTION },
treib29e1b9b12015-11-11 08:50:561295 { "PreserveLocalDisableReason", Extension::DISABLE_RELOAD, true, 0,
1296 Extension::DISABLE_RELOAD },
1297 { "PreserveOnlyLocalDisableReason",
1298 Extension::DISABLE_USER_ACTION | Extension::DISABLE_RELOAD, true, 0,
1299 Extension::DISABLE_RELOAD },
1300
1301 // Interaction with Chrome clients <=M44, which don't sync disable_reasons
1302 // at all (any existing reasons are preserved).
1303 { "M44Enable", Extension::DISABLE_USER_ACTION, true, -1, 0 },
1304 // An M44 client enables an extension that had been disabled on a new
1305 // client. The disable reasons are still be there, but should be ignored.
1306 { "M44ReEnable", Extension::DISABLE_USER_ACTION, true,
1307 Extension::DISABLE_USER_ACTION, 0 },
1308 { "M44Disable", 0, false, -1, Extension::DISABLE_USER_ACTION },
1309 { "M44ReDisable", 0, false, 0, Extension::DISABLE_USER_ACTION },
1310 { "M44AlreadyDisabledByUser", Extension::DISABLE_USER_ACTION, false, -1,
1311 Extension::DISABLE_USER_ACTION},
1312 { "M44AlreadyDisabledWithOtherReason", Extension::DISABLE_REMOTE_INSTALL,
1313 false, -1,
1314 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION },
treib9afc6212015-10-30 18:49:581315 };
1316
1317 for (const TestCase& test_case : test_cases) {
1318 SCOPED_TRACE(test_case.name);
1319
1320 std::string id;
1321 std::string version;
1322 // Don't keep |extension| around longer than necessary.
1323 {
1324 const Extension* extension =
1325 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1326 // The extension should now be installed and enabled.
1327 ASSERT_TRUE(extension);
1328 id = extension->id();
1329 version = extension->VersionString();
1330 }
1331 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1332
1333 // Disable it if the test case says so.
1334 if (test_case.previous_disable_reasons) {
1335 service()->DisableExtension(id, test_case.previous_disable_reasons);
1336 ASSERT_TRUE(registry()->disabled_extensions().Contains(id));
1337 }
1338
1339 // Now a sync update comes in.
1340 sync_pb::EntitySpecifics specifics;
1341 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1342 ext_specifics->set_id(id);
1343 ext_specifics->set_enabled(test_case.sync_enable);
1344 ext_specifics->set_version(version);
1345 if (test_case.sync_disable_reasons != -1)
1346 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1347
treib65f103042015-12-03 10:21:361348 SyncChangeList list =
1349 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1350
treib9afc6212015-10-30 18:49:581351 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1352
1353 // Check expectations.
1354 const bool expect_enabled = !test_case.expect_disable_reasons;
1355 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1356 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
1357
1358 // Remove the extension again, so we can install it again for the next case.
1359 UninstallExtension(id, false, expect_enabled ? Extension::ENABLED
1360 : Extension::DISABLED);
1361 }
1362}
1363
1364TEST_F(ExtensionServiceSyncTest, ProcessSyncDataDeferredEnable) {
1365 InitializeEmptyExtensionService();
1366 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361367 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141368 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1369 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581370
1371 base::FilePath base_path = data_dir().AppendASCII("permissions_increase");
1372 base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1373
1374 base::FilePath path = base_path.AppendASCII("v1");
1375 const Extension* extension = PackAndInstallCRX(path, pem_path, INSTALL_NEW);
1376 // The extension must now be installed and enabled.
1377 ASSERT_TRUE(extension);
1378 ASSERT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
1379
1380 // Save the id, as the extension object will be destroyed during updating.
1381 std::string id = extension->id();
1382
1383 // Update to a new version with increased permissions.
1384 path = base_path.AppendASCII("v2");
1385 PackCRXAndUpdateExtension(id, path, pem_path, DISABLED);
1386
1387 // Now a sync update comes in, telling us to re-enable a *newer* version.
1388 sync_pb::EntitySpecifics specifics;
1389 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1390 ext_specifics->set_id(id);
1391 ext_specifics->set_version("3");
1392 ext_specifics->set_enabled(true);
1393 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
1394
treib65f103042015-12-03 10:21:361395 SyncChangeList list =
1396 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1397
treib9afc6212015-10-30 18:49:581398 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1399
1400 // Since the version didn't match, the extension should still be disabled.
1401 EXPECT_TRUE(registry()->disabled_extensions().Contains(id));
1402
1403 // After we update to the matching version, the extension should get enabled.
1404 path = base_path.AppendASCII("v3");
1405 PackCRXAndUpdateExtension(id, path, pem_path, ENABLED);
1406}
1407
atuchin2eb18eb2017-03-02 07:22:151408class ExtensionServiceSyncCustomGalleryTest : public ExtensionServiceSyncTest {
1409 public:
1410 void SetUp() override {
1411 ExtensionServiceSyncTest::SetUp();
treib9afc6212015-10-30 18:49:581412
atuchin2eb18eb2017-03-02 07:22:151413 // This is the update URL specified in the permissions test extension.
1414 // Setting it here is necessary to make the extension considered syncable.
1415 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1416 switches::kAppsGalleryUpdateURL,
1417 "http://localhost/autoupdate/updates.xml");
1418 }
1419};
1420
1421TEST_F(ExtensionServiceSyncCustomGalleryTest,
1422 ProcessSyncDataPermissionApproval) {
treib9afc6212015-10-30 18:49:581423 InitializeEmptyExtensionService();
1424 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361425 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:141426 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
1427 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:581428
1429 const base::FilePath base_path =
1430 data_dir().AppendASCII("permissions_increase");
1431 const base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1432 const base::FilePath path_v1 = base_path.AppendASCII("v1");
1433 const base::FilePath path_v2 = base_path.AppendASCII("v2");
1434
1435 base::ScopedTempDir crx_dir;
1436 ASSERT_TRUE(crx_dir.CreateUniqueTempDir());
vabr9142fe22016-09-08 13:19:221437 const base::FilePath crx_path_v1 = crx_dir.GetPath().AppendASCII("temp1.crx");
treib9afc6212015-10-30 18:49:581438 PackCRX(path_v1, pem_path, crx_path_v1);
vabr9142fe22016-09-08 13:19:221439 const base::FilePath crx_path_v2 = crx_dir.GetPath().AppendASCII("temp2.crx");
treib9afc6212015-10-30 18:49:581440 PackCRX(path_v2, pem_path, crx_path_v2);
1441
1442 const std::string v1("1");
1443 const std::string v2("2");
1444
1445 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1446
1447 struct TestCase {
1448 const char* name; // For failure output only.
1449 const std::string& sync_version; // The version coming in from Sync.
1450 // The disable reason(s) coming in from Sync, or -1 for "not set".
1451 int sync_disable_reasons;
1452 // The expected set of disable reasons after processing the Sync update. The
1453 // extension should be enabled iff this is 0.
1454 int expect_disable_reasons;
1455 // Whether the extension's permissions should be auto-granted.
1456 bool expect_permissions_granted;
1457 } test_cases[] = {
1458 // Sync tells us to re-enable an older version. No permissions should be
1459 // granted, since we can't be sure if the user actually approved the right
1460 // set of permissions.
1461 { "OldVersion", v1, 0, Extension::DISABLE_PERMISSIONS_INCREASE, false },
1462 // Legacy case: Sync tells us to re-enable the extension, but doesn't
1463 // specify disable reasons. No permissions should be granted.
1464 { "Legacy", v2, -1, Extension::DISABLE_PERMISSIONS_INCREASE, false },
1465 // Sync tells us to re-enable the extension and explicitly removes the
1466 // disable reasons. Now the extension should have its permissions granted.
1467 { "GrantPermissions", v2, 0, Extension::DISABLE_NONE, true },
1468 };
1469
1470 for (const TestCase& test_case : test_cases) {
1471 SCOPED_TRACE(test_case.name);
1472
1473 std::string id;
1474 // Don't keep |extension| around longer than necessary (it'll be destroyed
1475 // during updating).
1476 {
1477 const Extension* extension = InstallCRX(crx_path_v1, INSTALL_NEW);
1478 // The extension should now be installed and enabled.
1479 ASSERT_TRUE(extension);
1480 ASSERT_EQ(v1, extension->VersionString());
1481 id = extension->id();
1482 }
1483 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1484
dchengc963c7142016-04-08 03:55:221485 std::unique_ptr<const PermissionSet> granted_permissions_v1 =
treib9afc6212015-10-30 18:49:581486 prefs->GetGrantedPermissions(id);
1487
1488 // Update to a new version with increased permissions.
1489 UpdateExtension(id, crx_path_v2, DISABLED);
1490
1491 // Now the extension should be disabled due to a permissions increase.
1492 {
1493 const Extension* extension =
1494 registry()->disabled_extensions().GetByID(id);
1495 ASSERT_TRUE(extension);
1496 ASSERT_EQ(v2, extension->VersionString());
1497 }
1498 ASSERT_TRUE(prefs->HasDisableReason(
1499 id, Extension::DISABLE_PERMISSIONS_INCREASE));
1500
1501 // No new permissions should have been granted.
dchengc963c7142016-04-08 03:55:221502 std::unique_ptr<const PermissionSet> granted_permissions_v2 =
treib9afc6212015-10-30 18:49:581503 prefs->GetGrantedPermissions(id);
1504 ASSERT_EQ(*granted_permissions_v1, *granted_permissions_v2);
1505
1506 // Now a sync update comes in.
1507 sync_pb::EntitySpecifics specifics;
1508 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1509 ext_specifics->set_id(id);
1510 ext_specifics->set_enabled(true);
1511 ext_specifics->set_version(test_case.sync_version);
1512 if (test_case.sync_disable_reasons != -1)
1513 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1514
treib65f103042015-12-03 10:21:361515 SyncChangeList list =
1516 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1517
treib9afc6212015-10-30 18:49:581518 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1519
1520 // Check expectations.
1521 const bool expect_enabled = !test_case.expect_disable_reasons;
1522 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1523 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
dchengc963c7142016-04-08 03:55:221524 std::unique_ptr<const PermissionSet> granted_permissions =
treib9afc6212015-10-30 18:49:581525 prefs->GetGrantedPermissions(id);
1526 if (test_case.expect_permissions_granted) {
dchengc963c7142016-04-08 03:55:221527 std::unique_ptr<const PermissionSet> active_permissions =
treib9afc6212015-10-30 18:49:581528 prefs->GetActivePermissions(id);
1529 EXPECT_EQ(*granted_permissions, *active_permissions);
1530 } else {
1531 EXPECT_EQ(*granted_permissions, *granted_permissions_v1);
1532 }
1533
1534 // Remove the extension again, so we can install it again for the next case.
1535 UninstallExtension(id, false, expect_enabled ? Extension::ENABLED
1536 : Extension::DISABLED);
1537 }
1538}
1539
treib227b2582015-12-09 09:28:261540// Regression test for crbug.com/558299
1541TEST_F(ExtensionServiceSyncTest, DontSyncThemes) {
1542 InitializeEmptyExtensionService();
1543
1544 // The user has enabled sync.
maxboguefe00952a2016-01-19 19:02:011545 ProfileSyncServiceFactory::GetForProfile(profile())->SetFirstSetupComplete();
treib227b2582015-12-09 09:28:261546 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
1547 extension_sync_service();
1548
1549 service()->Init();
1550 ASSERT_TRUE(service()->is_ready());
1551
1552 syncer::FakeSyncChangeProcessor* processor =
1553 new syncer::FakeSyncChangeProcessor;
1554 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:221555 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
1556 base::WrapUnique(new syncer::SyncErrorFactoryMock));
treib227b2582015-12-09 09:28:261557
1558 processor->changes().clear();
1559
1560 // Sanity check: Installing an extension should result in a sync change.
1561 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1562 EXPECT_EQ(1u, processor->changes().size());
1563
1564 processor->changes().clear();
1565
1566 // Installing a theme should not result in a sync change (themes are handled
1567 // separately by ThemeSyncableService).
1568 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
Evan Stade46d716d2017-06-02 20:50:091569 content::WindowedNotificationObserver theme_change_observer(
1570 chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
1571 content::Source<ThemeService>(
1572 ThemeServiceFactory::GetForProfile(profile())));
1573 theme_change_observer.Wait();
treib227b2582015-12-09 09:28:261574 EXPECT_TRUE(processor->changes().empty());
1575}
1576
brettw9e85ef42016-11-01 21:01:241577#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
treib9afc6212015-10-30 18:49:581578
atuchin2eb18eb2017-03-02 07:22:151579class ExtensionServiceTestSupervised
1580 : public ExtensionServiceSyncCustomGalleryTest,
1581 public SupervisedUserService::Delegate {
treib9afc6212015-10-30 18:49:581582 public:
treibb6af28cd2015-12-01 11:19:461583 ExtensionServiceTestSupervised()
robliao79393ffb2016-09-21 18:45:291584 : field_trial_list_(base::MakeUnique<base::MockEntropyProvider>()) {}
treibb6af28cd2015-12-01 11:19:461585
treib9afc6212015-10-30 18:49:581586 void TearDown() override {
1587 supervised_user_service()->SetDelegate(nullptr);
1588
atuchin2eb18eb2017-03-02 07:22:151589 ExtensionServiceSyncCustomGalleryTest::TearDown();
treib9afc6212015-10-30 18:49:581590 }
1591
1592 protected:
mamire9609642016-06-28 22:17:541593 void InitSupervisedUserInitiatedExtensionInstallFeature(bool enabled) {
mamire9609642016-06-28 22:17:541594 if (enabled) {
asvitkineb1db8262016-11-08 09:48:201595 scoped_feature_list_.InitAndEnableFeature(
1596 supervised_users::kSupervisedUserInitiatedExtensionInstall);
mamire9609642016-06-28 22:17:541597 }
mamire9609642016-06-28 22:17:541598 }
1599
mamirf7715a2a2016-07-04 13:05:081600 bool IsPendingCustodianApproval(const std::string& extension_id) {
1601 auto function = make_scoped_refptr(
1602 new WebstorePrivateIsPendingCustodianApprovalFunction());
1603
1604 std::unique_ptr<base::Value> result(RunFunctionAndReturnSingleResult(
1605 function.get(), "[\"" + extension_id + "\"]", browser_context()));
1606
1607 bool copy_bool_result = false;
1608 EXPECT_TRUE(result->GetAsBoolean(&copy_bool_result));
1609 return copy_bool_result;
1610 }
1611
treib9afc6212015-10-30 18:49:581612 void InitServices(bool profile_is_supervised) {
1613 ExtensionServiceInitParams params = CreateDefaultInitParams();
1614 params.profile_is_supervised = profile_is_supervised;
mamire9609642016-06-28 22:17:541615 // If profile is supervised, don't pass a pref file such that the testing
1616 // profile creates a pref service that uses SupervisedUserPrefStore.
1617 if (profile_is_supervised) {
1618 params.pref_file = base::FilePath();
1619 }
treib9afc6212015-10-30 18:49:581620 InitializeExtensionService(params);
asargente48ab752016-03-12 00:59:201621 StartSyncing(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581622
1623 supervised_user_service()->SetDelegate(this);
1624 supervised_user_service()->Init();
1625 }
1626
mamire9609642016-06-28 22:17:541627 std::string InstallPermissionsTestExtension(bool by_custodian) {
1628 return InstallTestExtension(permissions_increase, dir_path("1"), pem_path(),
1629 by_custodian);
treib9afc6212015-10-30 18:49:581630 }
1631
1632 void UpdatePermissionsTestExtension(const std::string& id,
1633 const std::string& version,
1634 UpdateState expected_state) {
mamire9609642016-06-28 22:17:541635 UpdateTestExtension(dir_path(version), pem_path(), id, version,
1636 expected_state);
1637 }
1638
1639 std::string InstallNoPermissionsTestExtension(bool by_custodian) {
1640 base::FilePath base_path = data_dir().AppendASCII("autoupdate");
1641 base::FilePath pem_path = base_path.AppendASCII("key.pem");
1642 base::FilePath dir_path = base_path.AppendASCII("v1");
1643
1644 return InstallTestExtension(autoupdate, dir_path, pem_path, by_custodian);
1645 }
1646
1647 void UpdateNoPermissionsTestExtension(const std::string& id,
1648 const std::string& version,
1649 UpdateState expected_state) {
1650 base::FilePath base_path = data_dir().AppendASCII("autoupdate");
1651 base::FilePath pem_path = base_path.AppendASCII("key.pem");
1652 base::FilePath dir_path = base_path.AppendASCII("v" + version);
1653
1654 UpdateTestExtension(dir_path, pem_path, id, version, expected_state);
1655 }
1656
1657 std::string InstallTestExtension(const std::string& id,
1658 const base::FilePath& dir_path,
1659 const base::FilePath& pem_path,
1660 bool by_custodian) {
1661 InstallState expected_state = INSTALL_WITHOUT_LOAD;
1662 if (by_custodian) {
1663 extensions::util::SetWasInstalledByCustodian(id, profile(), true);
1664 expected_state = INSTALL_NEW;
1665 }
1666 const Extension* extension =
1667 PackAndInstallCRX(dir_path, pem_path, expected_state);
1668 // The extension must now be installed.
1669 EXPECT_TRUE(extension);
1670 EXPECT_EQ(extension->id(), id);
1671 if (by_custodian) {
1672 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1673 } else {
1674 CheckDisabledForCustodianApproval(id);
1675 }
1676
1677 EXPECT_EQ(*extension->version(), base::Version("1"));
1678
1679 return id;
1680 }
1681
1682 void UpdateTestExtension(const base::FilePath& dir_path,
1683 const base::FilePath& pem_path,
1684 const std::string& id,
1685 const std::string& version,
1686 const UpdateState& expected_state) {
1687 PackCRXAndUpdateExtension(id, dir_path, pem_path, expected_state);
treib9afc6212015-10-30 18:49:581688 const Extension* extension = registry()->GetInstalledExtension(id);
1689 ASSERT_TRUE(extension);
1690 // The version should have been updated.
mamire9609642016-06-28 22:17:541691 EXPECT_EQ(*extension->version(), base::Version(version));
1692 }
1693
1694 // Simulate a custodian approval for enabling the extension coming in
1695 // through Sync by adding the approved version to the map of approved
1696 // extensions. It doesn't simulate a change in the disable reasons.
1697 void SimulateCustodianApprovalChangeViaSync(const std::string& extension_id,
1698 const std::string& version,
1699 SyncChange::SyncChangeType type) {
1700 std::string key = SupervisedUserSettingsService::MakeSplitSettingKey(
1701 supervised_users::kApprovedExtensions, extension_id);
1702 syncer::SyncData sync_data =
1703 SupervisedUserSettingsService::CreateSyncDataForSetting(
jdoerrie122c4da2017-03-06 11:12:041704 key, base::Value(version));
mamire9609642016-06-28 22:17:541705
1706 SyncChangeList list(1, SyncChange(FROM_HERE, type, sync_data));
1707
1708 SupervisedUserSettingsService* supervised_user_settings_service =
1709 SupervisedUserSettingsServiceFactory::GetForProfile(profile());
1710 supervised_user_settings_service->ProcessSyncChanges(FROM_HERE, list);
1711 }
1712
1713 void CheckDisabledForCustodianApproval(const std::string& extension_id) {
1714 EXPECT_TRUE(registry()->disabled_extensions().Contains(extension_id));
1715 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile());
1716 EXPECT_TRUE(extension_prefs->HasDisableReason(
1717 extension_id,
1718 extensions::Extension::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
treib9afc6212015-10-30 18:49:581719 }
1720
1721 SupervisedUserService* supervised_user_service() {
1722 return SupervisedUserServiceFactory::GetForProfile(profile());
1723 }
1724
mamire9609642016-06-28 22:17:541725 static std::string RequestId(const std::string& extension_id,
1726 const std::string& version) {
1727 return SupervisedUserService::GetExtensionRequestId(
treib9afc6212015-10-30 18:49:581728 extension_id, base::Version(version));
1729 }
1730
1731 private:
1732 // This prevents the legacy supervised user init code from running.
1733 bool SetActive(bool active) override { return true; }
1734
1735 base::FilePath base_path() const {
1736 return data_dir().AppendASCII("permissions_increase");
1737 }
1738 base::FilePath dir_path(const std::string& version) const {
1739 return base_path().AppendASCII("v" + version);
1740 }
1741 base::FilePath pem_path() const {
1742 return base_path().AppendASCII("permissions.pem");
1743 }
treibb6af28cd2015-12-01 11:19:461744
1745 base::FieldTrialList field_trial_list_;
asvitkineb1db8262016-11-08 09:48:201746 base::test::ScopedFeatureList scoped_feature_list_;
treib9afc6212015-10-30 18:49:581747};
1748
1749class MockPermissionRequestCreator : public PermissionRequestCreator {
1750 public:
1751 MockPermissionRequestCreator() {}
1752 ~MockPermissionRequestCreator() override {}
1753
1754 bool IsEnabled() const override { return true; }
1755
1756 void CreateURLAccessRequest(const GURL& url_requested,
1757 const SuccessCallback& callback) override {
1758 FAIL();
1759 }
1760
mamire9609642016-06-28 22:17:541761 MOCK_METHOD2(CreateExtensionInstallRequest,
1762 void(const std::string& id,
1763 const SupervisedUserService::SuccessCallback& callback));
1764
treib9afc6212015-10-30 18:49:581765 MOCK_METHOD2(CreateExtensionUpdateRequest,
1766 void(const std::string& id,
1767 const SupervisedUserService::SuccessCallback& callback));
1768
1769 private:
1770 DISALLOW_COPY_AND_ASSIGN(MockPermissionRequestCreator);
1771};
1772
1773TEST_F(ExtensionServiceTestSupervised, InstallOnlyAllowedByCustodian) {
1774 InitServices(true /* profile_is_supervised */);
mamire9609642016-06-28 22:17:541775 InitSupervisedUserInitiatedExtensionInstallFeature(false);
treib9afc6212015-10-30 18:49:581776
mamir192d7882016-06-22 17:10:161777 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
1778
treib9afc6212015-10-30 18:49:581779 base::FilePath path1 = data_dir().AppendASCII("good.crx");
1780 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
1781 const Extension* extensions[] = {
1782 InstallCRX(path1, INSTALL_FAILED),
mamir192d7882016-06-22 17:10:161783 InstallCRX(path2, INSTALL_NEW)
treib9afc6212015-10-30 18:49:581784 };
1785
1786 // Only the extension with the "installed by custodian" flag should have been
1787 // installed and enabled.
1788 EXPECT_FALSE(extensions[0]);
1789 ASSERT_TRUE(extensions[1]);
1790 EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id()));
mamirf7715a2a2016-07-04 13:05:081791 EXPECT_FALSE(IsPendingCustodianApproval(extensions[1]->id()));
treib9afc6212015-10-30 18:49:581792}
1793
mamir192d7882016-06-22 17:10:161794TEST_F(ExtensionServiceTestSupervised,
1795 DelegatedAndPreinstalledExtensionIsSUFirst) {
1796 InitServices(false /* profile_is_supervised */);
mamire9609642016-06-28 22:17:541797 InitSupervisedUserInitiatedExtensionInstallFeature(false);
mamir192d7882016-06-22 17:10:161798
1799 // Install an extension.
1800 base::FilePath path = data_dir().AppendASCII("good.crx");
1801 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1802 std::string id = extension->id();
1803 const std::string version("1.0.0.0");
1804 // It should be enabled.
1805 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1806
1807 // Now make the profile supervised.
1808 profile()->AsTestingProfile()->SetSupervisedUserId(
1809 supervised_users::kChildAccountSUID);
1810
1811 // It should not be enabled now (it is not loaded at all actually).
1812 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
1813
1814 // Simulate data sync with the "was_installed_by_custodian" flag set to 1.
1815 sync_pb::EntitySpecifics specifics;
1816 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1817 ext_specifics->set_id(id);
1818 ext_specifics->set_enabled(true);
1819 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
1820 ext_specifics->set_installed_by_custodian(true);
1821 ext_specifics->set_version(version);
1822
1823 SyncChangeList list =
1824 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
1825
1826 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1827
1828 // The extension should be enabled again.
1829 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1830 EXPECT_TRUE(extensions::util::WasInstalledByCustodian(id, profile()));
1831}
1832
1833TEST_F(ExtensionServiceTestSupervised,
1834 DelegatedAndPreinstalledExtensionSyncFirst) {
1835 InitServices(false /* profile_is_supervised */);
mamire9609642016-06-28 22:17:541836 InitSupervisedUserInitiatedExtensionInstallFeature(false);
mamir192d7882016-06-22 17:10:161837
1838 // Install an extension.
1839 base::FilePath path = data_dir().AppendASCII("good.crx");
1840 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1841 std::string id = extension->id();
1842 const std::string version("1.0.0.0");
1843
1844 // It should be enabled.
1845 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1846
1847 // Simulate data sync with the "was_installed_by_custodian" flag set to 1.
1848 sync_pb::EntitySpecifics specifics;
1849 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1850 ext_specifics->set_id(id);
1851 ext_specifics->set_enabled(true);
1852 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
1853 ext_specifics->set_installed_by_custodian(true);
1854 ext_specifics->set_version(version);
1855
1856 SyncChangeList list =
1857 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
1858
1859 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
mamir192d7882016-06-22 17:10:161860 // The extension should be enabled.
1861 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1862 EXPECT_TRUE(extensions::util::WasInstalledByCustodian(id, profile()));
1863}
1864
mamire9609642016-06-28 22:17:541865TEST_F(ExtensionServiceTestSupervised,
1866 InstallAllowedByCustodianAndSupervisedUser) {
1867 InitServices(true /* profile_is_supervised */);
1868 InitSupervisedUserInitiatedExtensionInstallFeature(true);
1869
1870 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
1871
1872 base::FilePath path1 = data_dir().AppendASCII("good.crx");
1873 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
1874 const Extension* extensions[] = {
1875 InstallCRX(path1, INSTALL_WITHOUT_LOAD),
1876 InstallCRX(path2, INSTALL_NEW)
1877 };
1878
1879 // Only the extension with the "installed by custodian" flag should have been
1880 // installed and enabled.
1881 // The extension missing the "installed by custodian" flag is a
1882 // supervised user initiated install and hence not enabled.
1883 ASSERT_TRUE(extensions[0]);
1884 ASSERT_TRUE(extensions[1]);
1885 EXPECT_TRUE(registry()->disabled_extensions().Contains(extensions[0]->id()));
mamirf7715a2a2016-07-04 13:05:081886 EXPECT_TRUE(IsPendingCustodianApproval(extensions[0]->id()));
mamire9609642016-06-28 22:17:541887 EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id()));
mamirf7715a2a2016-07-04 13:05:081888 EXPECT_FALSE(IsPendingCustodianApproval(extensions[1]->id()));
mamire9609642016-06-28 22:17:541889}
1890
1891TEST_F(ExtensionServiceTestSupervised,
1892 PreinstalledExtensionWithSUInitiatedInstalls) {
1893 InitServices(false /* profile_is_supervised */);
1894 InitSupervisedUserInitiatedExtensionInstallFeature(true);
1895
1896 // Install an extension.
1897 base::FilePath path = data_dir().AppendASCII("good.crx");
1898 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1899 std::string id = extension->id();
1900 // Make sure it's enabled.
1901 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1902
1903 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1904 supervised_user_service()->AddPermissionRequestCreator(
1905 base::WrapUnique(creator));
1906 const std::string version("1.0.0.0");
1907
1908 EXPECT_CALL(*creator, CreateExtensionInstallRequest(
1909 RequestId(good_crx, version), testing::_));
1910
1911 // Now make the profile supervised.
1912 profile()->AsTestingProfile()->SetSupervisedUserId(
1913 supervised_users::kChildAccountSUID);
1914
1915 Mock::VerifyAndClearExpectations(creator);
1916
1917 // The extension should not be enabled anymore.
1918 CheckDisabledForCustodianApproval(id);
mamirf7715a2a2016-07-04 13:05:081919 EXPECT_TRUE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:541920}
1921
1922TEST_F(ExtensionServiceTestSupervised,
1923 PreinstalledExtensionWithoutSUInitiatedInstalls) {
1924 InitServices(false /* profile_is_supervised */);
1925 InitSupervisedUserInitiatedExtensionInstallFeature(false);
1926
1927 // Install an extension.
1928 base::FilePath path = data_dir().AppendASCII("good.crx");
1929 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1930 std::string id = extension->id();
1931
1932 // Make sure it's enabled.
1933 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1934
1935 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1936 supervised_user_service()->AddPermissionRequestCreator(
1937 base::WrapUnique(creator));
1938 const std::string version("1.0.0.0");
1939
1940 // No request should be sent because supervised user initiated installs
1941 // are disabled.
1942 EXPECT_CALL(*creator, CreateExtensionInstallRequest(testing::_, testing::_))
1943 .Times(0);
1944
1945 // Now make the profile supervised.
1946 profile()->AsTestingProfile()->SetSupervisedUserId(
1947 supervised_users::kChildAccountSUID);
1948
1949 // The extension should not be loaded anymore.
1950 EXPECT_FALSE(registry()->GetInstalledExtension(id));
1951}
1952
1953TEST_F(ExtensionServiceTestSupervised, ExtensionApprovalBeforeInstallation) {
1954 // This tests the case when the sync entity flagging the extension as approved
1955 // arrives before the extension itself is installed.
1956 InitServices(true /* profile_is_supervised */);
1957 InitSupervisedUserInitiatedExtensionInstallFeature(true);
1958
1959 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1960 supervised_user_service()->AddPermissionRequestCreator(
1961 base::WrapUnique(creator));
1962
1963 std::string id = good_crx;
1964 std::string version("1.0.0.0");
1965
1966 SimulateCustodianApprovalChangeViaSync(id, version, SyncChange::ACTION_ADD);
1967
1968 // Now install an extension.
1969 base::FilePath path = data_dir().AppendASCII("good.crx");
1970 InstallCRX(path, INSTALL_NEW);
1971
1972 // No approval request should be sent.
1973 EXPECT_CALL(*creator, CreateExtensionInstallRequest(testing::_, testing::_))
1974 .Times(0);
1975
1976 // Make sure it's enabled.
1977 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:081978 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:541979}
1980
treib9afc6212015-10-30 18:49:581981TEST_F(ExtensionServiceTestSupervised, UpdateWithoutPermissionIncrease) {
1982 InitServices(true /* profile_is_supervised */);
1983
treib9afc6212015-10-30 18:49:581984 // Save the id, as the extension object will be destroyed during updating.
mamire9609642016-06-28 22:17:541985 std::string id = InstallNoPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:581986
1987 // Update to a new version.
mamire9609642016-06-28 22:17:541988 std::string version2("2");
1989 UpdateNoPermissionsTestExtension(id, version2, ENABLED);
treib9afc6212015-10-30 18:49:581990
1991 // The extension should still be there and enabled.
mamire9609642016-06-28 22:17:541992 const Extension* extension = registry()->enabled_extensions().GetByID(id);
treib9afc6212015-10-30 18:49:581993 ASSERT_TRUE(extension);
1994 // The version should have changed.
mamire9609642016-06-28 22:17:541995 EXPECT_EQ(*extension->version(), base::Version(version2));
mamirf7715a2a2016-07-04 13:05:081996 EXPECT_FALSE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:581997}
1998
treib9afc6212015-10-30 18:49:581999TEST_F(ExtensionServiceTestSupervised,
2000 UpdateWithPermissionIncreaseApprovalOldVersion) {
treib9afc6212015-10-30 18:49:582001 InitServices(true /* profile_is_supervised */);
2002
2003 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2004 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222005 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582006
2007 const std::string version1("1");
2008 const std::string version2("2");
2009
mamire9609642016-06-28 22:17:542010 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582011
2012 // Update to a new version with increased permissions.
2013 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542014 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582015 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542016 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082017 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582018
2019 // Simulate a custodian approval for re-enabling the extension coming in
2020 // through Sync, but set the old version. This can happen when there already
2021 // was a pending request for an earlier version of the extension.
2022 sync_pb::EntitySpecifics specifics;
2023 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2024 ext_specifics->set_id(id);
2025 ext_specifics->set_enabled(true);
2026 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
2027 ext_specifics->set_installed_by_custodian(true);
2028 ext_specifics->set_version(version1);
2029
2030 // Attempting to re-enable an old version should result in a permission
2031 // request for the current version.
2032 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542033 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582034
treib65f103042015-12-03 10:21:362035 SyncChangeList list =
2036 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2037
2038 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582039 // The re-enable should be ignored, since the version doesn't match.
2040 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2041 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
2042 id, base::Version(version1)));
2043 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
2044 id, base::Version(version2)));
mamire9609642016-06-28 22:17:542045 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082046 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582047}
2048
2049TEST_F(ExtensionServiceTestSupervised,
2050 UpdateWithPermissionIncreaseApprovalMatchingVersion) {
treib9afc6212015-10-30 18:49:582051 InitServices(true /* profile_is_supervised */);
2052
2053 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2054 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222055 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582056
mamire9609642016-06-28 22:17:542057 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582058
2059 // Update to a new version with increased permissions.
2060 const std::string version2("2");
2061 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542062 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582063 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542064 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082065 EXPECT_TRUE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582066
2067 // Simulate a custodian approval for re-enabling the extension coming in
2068 // through Sync.
2069 sync_pb::EntitySpecifics specifics;
2070 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2071 ext_specifics->set_id(id);
2072 ext_specifics->set_enabled(true);
2073 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
2074 ext_specifics->set_installed_by_custodian(true);
2075 ext_specifics->set_version(version2);
2076
treib65f103042015-12-03 10:21:362077 SyncChangeList list =
2078 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2079
2080 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582081 // The extension should have gotten re-enabled.
2082 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082083 EXPECT_FALSE(IsPendingCustodianApproval(id));
treib9afc6212015-10-30 18:49:582084}
2085
2086TEST_F(ExtensionServiceTestSupervised,
2087 UpdateWithPermissionIncreaseApprovalNewVersion) {
treib9afc6212015-10-30 18:49:582088 InitServices(true /* profile_is_supervised */);
2089
2090 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2091 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222092 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582093
mamire9609642016-06-28 22:17:542094 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582095
2096 // Update to a new version with increased permissions.
2097 const std::string version2("2");
2098 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542099 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582100 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542101 Mock::VerifyAndClearExpectations(creator);
treib9afc6212015-10-30 18:49:582102
2103 // Simulate a custodian approval for re-enabling the extension coming in
2104 // through Sync. Set a newer version than we have installed.
2105 const std::string version3("3");
2106 sync_pb::EntitySpecifics specifics;
2107 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2108 ext_specifics->set_id(id);
2109 ext_specifics->set_enabled(true);
2110 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
2111 ext_specifics->set_installed_by_custodian(true);
2112 ext_specifics->set_version(version3);
2113
2114 // This should *not* result in a new permission request.
2115 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542116 RequestId(id, version3), testing::_))
treib9afc6212015-10-30 18:49:582117 .Times(0);
2118
treib65f103042015-12-03 10:21:362119 SyncChangeList list =
2120 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2121
2122 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582123 // The re-enable should be delayed until the extension is updated to the
2124 // matching version.
2125 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2126 EXPECT_TRUE(extension_sync_service()->HasPendingReenable(
2127 id, base::Version(version3)));
2128
2129 // Update to the matching version. Now the extension should get enabled.
2130 UpdatePermissionsTestExtension(id, version3, ENABLED);
2131}
2132
mamire9609642016-06-28 22:17:542133TEST_F(ExtensionServiceTestSupervised, SupervisedUserInitiatedInstalls) {
mamire9609642016-06-28 22:17:542134 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2135
2136 InitServices(true /* profile_is_supervised */);
2137
2138 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2139 supervised_user_service()->AddPermissionRequestCreator(
2140 base::WrapUnique(creator));
2141
2142 base::FilePath path = data_dir().AppendASCII("good.crx");
2143 std::string version("1.0.0.0");
2144
2145 EXPECT_CALL(*creator, CreateExtensionInstallRequest(
2146 RequestId(good_crx, version), testing::_));
2147
2148 // Should be installed but disabled, a request for approval should be sent.
2149 const Extension* extension = InstallCRX(path, INSTALL_WITHOUT_LOAD);
2150 ASSERT_TRUE(extension);
2151 ASSERT_EQ(extension->id(), good_crx);
2152 EXPECT_TRUE(registry()->disabled_extensions().Contains(good_crx));
2153 Mock::VerifyAndClearExpectations(creator);
mamirf7715a2a2016-07-04 13:05:082154 EXPECT_TRUE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542155
2156 SimulateCustodianApprovalChangeViaSync(good_crx, version,
2157 SyncChange::ACTION_ADD);
2158
2159 // The extension should be enabled now.
2160 EXPECT_TRUE(registry()->enabled_extensions().Contains(good_crx));
mamirf7715a2a2016-07-04 13:05:082161 EXPECT_FALSE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542162
2163 // Simulate approval removal coming via Sync.
2164 SimulateCustodianApprovalChangeViaSync(good_crx, version,
2165 SyncChange::ACTION_DELETE);
2166
2167 // The extension should be disabled now.
2168 EXPECT_TRUE(registry()->disabled_extensions().Contains(good_crx));
mamirf7715a2a2016-07-04 13:05:082169 EXPECT_TRUE(IsPendingCustodianApproval(extension->id()));
mamire9609642016-06-28 22:17:542170}
2171
2172TEST_F(ExtensionServiceTestSupervised,
2173 UpdateSUInitiatedInstallWithoutPermissionIncrease) {
mamire9609642016-06-28 22:17:542174 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2175
2176 InitServices(true /* profile_is_supervised */);
2177
2178 std::string id = InstallNoPermissionsTestExtension(false /* by_custodian */);
2179 std::string version1("1");
2180
2181 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2182
2183 // The extension should be enabled now.
2184 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2185
2186 std::string version2("2");
2187
2188 // Update to a new version.
2189 UpdateNoPermissionsTestExtension(id, version2, ENABLED);
2190
2191 // The extension should still be there and enabled.
2192 const Extension* extension = registry()->enabled_extensions().GetByID(id);
2193 ASSERT_TRUE(extension);
2194 // The version should have increased.
2195 EXPECT_EQ(1, extension->version()->CompareTo(base::Version(version1)));
2196
2197 // Check that the approved version has been updated in the prefs as well.
2198 // Prefs are updated via Sync. If the prefs are updated, then the new
2199 // approved version has been pushed to Sync as well.
2200 std::string approved_version;
2201 PrefService* pref_service = profile()->GetPrefs();
2202 const base::DictionaryValue* approved_extensions =
2203 pref_service->GetDictionary(prefs::kSupervisedUserApprovedExtensions);
2204 approved_extensions->GetStringWithoutPathExpansion(id, &approved_version);
2205
2206 EXPECT_EQ(base::Version(approved_version), *extension->version());
mamirf7715a2a2016-07-04 13:05:082207 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542208}
2209
2210TEST_F(ExtensionServiceTestSupervised,
2211 UpdateSUInitiatedInstallWithPermissionIncrease) {
mamire9609642016-06-28 22:17:542212 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2213
2214 InitServices(true /* profile_is_supervised */);
2215
2216 std::string id = InstallPermissionsTestExtension(false /* by_custodian */);
2217 std::string version1("1");
2218
2219 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2220
2221 // The extension should be enabled now.
2222 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2223
2224 std::string version3("3");
2225
2226 UpdatePermissionsTestExtension(id, version3, DISABLED);
2227
2228 // The extension should be disabled.
2229 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2230 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
2231 id, Extension::DISABLE_PERMISSIONS_INCREASE));
2232
2233 std::string version2("2");
2234 // Approve an older version
2235 SimulateCustodianApprovalChangeViaSync(id, version2,
2236 SyncChange::ACTION_UPDATE);
2237
2238 // The extension should remain disabled.
2239 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2240 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
2241 id, Extension::DISABLE_PERMISSIONS_INCREASE));
2242 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
2243 id, Extension::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
2244
mamirf7715a2a2016-07-04 13:05:082245 EXPECT_TRUE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542246 // Approve the latest version
2247 SimulateCustodianApprovalChangeViaSync(id, version3,
2248 SyncChange::ACTION_UPDATE);
2249
2250 // The extension should be enabled again.
2251 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082252 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542253}
2254
2255TEST_F(ExtensionServiceTestSupervised,
2256 UpdateSUInitiatedInstallWithPermissionIncreaseApprovalArrivesFirst) {
mamire9609642016-06-28 22:17:542257 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2258
2259 InitServices(true /* profile_is_supervised */);
2260
2261 std::string id = InstallPermissionsTestExtension(false /* by_custodian */);
2262
2263 std::string version1("1");
2264 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2265
2266 // The extension should be enabled now.
2267 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2268
2269 std::string version2("2");
2270 // Approve a newer version
2271 SimulateCustodianApprovalChangeViaSync(id, version2,
2272 SyncChange::ACTION_UPDATE);
2273
2274 // The extension should be disabled.
2275 CheckDisabledForCustodianApproval(id);
2276
2277 // Now update the extension to the same version that was approved.
2278 UpdatePermissionsTestExtension(id, version2, ENABLED);
2279 // The extension should be enabled again.
2280 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
mamirf7715a2a2016-07-04 13:05:082281 EXPECT_FALSE(IsPendingCustodianApproval(id));
mamire9609642016-06-28 22:17:542282}
2283
treib9afc6212015-10-30 18:49:582284TEST_F(ExtensionServiceSyncTest, SyncUninstallByCustodianSkipsPolicy) {
2285 InitializeEmptyExtensionService();
2286 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:362287 syncer::EXTENSIONS, syncer::SyncDataList(),
ricea91d6fc122016-08-30 08:47:142288 base::MakeUnique<syncer::FakeSyncChangeProcessor>(),
2289 base::MakeUnique<syncer::SyncErrorFactoryMock>());
treib9afc6212015-10-30 18:49:582290
mamir192d7882016-06-22 17:10:162291 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
treib9afc6212015-10-30 18:49:582292 // Install two extensions.
2293 base::FilePath path1 = data_dir().AppendASCII("good.crx");
2294 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
2295 const Extension* extensions[] = {
2296 InstallCRX(path1, INSTALL_NEW),
mamir192d7882016-06-22 17:10:162297 InstallCRX(path2, INSTALL_NEW)
treib9afc6212015-10-30 18:49:582298 };
2299
2300 // Add a policy provider that will disallow any changes.
2301 extensions::TestManagementPolicyProvider provider(
2302 extensions::TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS);
2303 ExtensionSystem::Get(
2304 browser_context())->management_policy()->RegisterProvider(&provider);
2305
2306 // Create a sync deletion for each extension.
treib65f103042015-12-03 10:21:362307 SyncChangeList list;
treib9afc6212015-10-30 18:49:582308 for (size_t i = 0; i < arraysize(extensions); i++) {
2309 const std::string& id = extensions[i]->id();
2310 sync_pb::EntitySpecifics specifics;
2311 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2312 ext_specifics->set_id(id);
2313 ext_specifics->set_version("1.0");
2314 ext_specifics->set_installed_by_custodian(
mamir192d7882016-06-22 17:10:162315 extensions::util::WasInstalledByCustodian(id, profile()));
2316
treib9afc6212015-10-30 18:49:582317 syncer::SyncData sync_data =
2318 syncer::SyncData::CreateLocalData(id, "Name", specifics);
treib65f103042015-12-03 10:21:362319 list.push_back(SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, sync_data));
treib9afc6212015-10-30 18:49:582320 }
2321
2322 // Save the extension ids, as uninstalling destroys the Extension instance.
2323 std::string extension_ids[] = {
2324 extensions[0]->id(),
2325 extensions[1]->id()
2326 };
2327
2328 // Now apply the uninstallations.
treib65f103042015-12-03 10:21:362329 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582330
2331 // Uninstalling the extension without installed_by_custodian should have been
2332 // blocked by policy, so it should still be there.
2333 EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_ids[0]));
2334
2335 // But installed_by_custodian should result in bypassing the policy check.
2336 EXPECT_FALSE(
2337 registry()->GenerateInstalledExtensionsSet()->Contains(extension_ids[1]));
2338}
2339
rdevlin.cronin738501d2015-11-05 21:51:362340TEST_F(ExtensionServiceSyncTest, SyncExtensionHasAllhostsWithheld) {
2341 InitializeEmptyExtensionService();
asargente48ab752016-03-12 00:59:202342 StartSyncing(syncer::EXTENSIONS);
rdevlin.cronin738501d2015-11-05 21:51:362343
2344 // Create an extension that needs all-hosts.
2345 const std::string kName("extension");
2346 scoped_refptr<const Extension> extension =
2347 extensions::ExtensionBuilder()
limasdf3d102542015-12-09 03:58:452348 .SetLocation(Manifest::INTERNAL)
dcheng794d2bd2016-02-27 03:51:322349 .SetManifest(
limasdf3d102542015-12-09 03:58:452350 extensions::DictionaryBuilder()
2351 .Set("name", kName)
2352 .Set("description", "foo")
2353 .Set("manifest_version", 2)
2354 .Set("version", "1.0")
2355 .Set("permissions",
dcheng794d2bd2016-02-27 03:51:322356 extensions::ListBuilder().Append("*://*/*").Build())
2357 .Build())
limasdf3d102542015-12-09 03:58:452358 .SetID(crx_file::id_util::GenerateId(kName))
2359 .Build();
rdevlin.cronin738501d2015-11-05 21:51:362360
2361 // Install and enable it.
2362 service()->AddExtension(extension.get());
2363 service()->GrantPermissionsAndEnableExtension(extension.get());
2364 const std::string id = extension->id();
2365 EXPECT_TRUE(registry()->enabled_extensions().GetByID(id));
2366
2367 // Simulate a sync node coming in where the extension had all-hosts withheld.
2368 // This means that it should have all-hosts withheld on this machine, too.
rdevlin.cronin738501d2015-11-05 21:51:362369 sync_pb::EntitySpecifics specifics;
2370 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2371 ext_specifics->set_id(id);
2372 ext_specifics->set_name(kName);
2373 ext_specifics->set_version("1.0");
2374 ext_specifics->set_all_urls_enabled(false);
2375 ext_specifics->set_enabled(true);
rdevlin.cronin738501d2015-11-05 21:51:362376
treib65f103042015-12-03 10:21:362377 SyncChangeList list =
2378 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2379
2380 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
rdevlin.cronin738501d2015-11-05 21:51:362381
rdevlin.cronind01837b2016-08-17 01:37:182382 const Extension* enabled_extension =
2383 registry()->enabled_extensions().GetByID(id);
2384 ASSERT_TRUE(enabled_extension);
2385 ScriptingPermissionsModifier modifier(profile(), enabled_extension);
2386 EXPECT_FALSE(modifier.IsAllowedOnAllUrls());
2387 EXPECT_TRUE(modifier.HasSetAllowedOnAllUrls());
rdevlin.cronin738501d2015-11-05 21:51:362388}
2389
brettw9e85ef42016-11-01 21:01:242390#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
asargente48ab752016-03-12 00:59:202391
2392// Tests sync behavior in the case of an item that starts out as an app and
2393// gets updated to become an extension.
2394TEST_F(ExtensionServiceSyncTest, AppToExtension) {
2395 InitializeEmptyExtensionService();
2396 service()->Init();
2397 ASSERT_TRUE(service()->is_ready());
2398
2399 // Install v1, which is an app.
2400 const Extension* v1 =
2401 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v1.crx"),
2402 INSTALL_NEW);
2403 EXPECT_TRUE(v1->is_app());
2404 EXPECT_FALSE(v1->is_extension());
2405 std::string id = v1->id();
2406
2407 StatefulChangeProcessor extensions_processor(syncer::ModelType::EXTENSIONS);
2408 StatefulChangeProcessor apps_processor(syncer::ModelType::APPS);
2409 extension_sync_service()->MergeDataAndStartSyncing(
2410 syncer::EXTENSIONS, syncer::SyncDataList(),
2411 extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222412 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202413 extension_sync_service()->MergeDataAndStartSyncing(
2414 syncer::APPS, syncer::SyncDataList(), apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222415 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202416
2417 // Check the app/extension change processors to be sure the right data was
2418 // added.
2419 EXPECT_TRUE(extensions_processor.changes().empty());
2420 EXPECT_TRUE(extensions_processor.data().empty());
2421 EXPECT_EQ(1u, apps_processor.data().size());
2422 ASSERT_EQ(1u, apps_processor.changes().size());
2423 const SyncChange& app_change = apps_processor.changes()[0];
2424 EXPECT_EQ(SyncChange::ACTION_ADD, app_change.change_type());
dchengc963c7142016-04-08 03:55:222425 std::unique_ptr<ExtensionSyncData> app_data =
asargente48ab752016-03-12 00:59:202426 ExtensionSyncData::CreateFromSyncData(app_change.sync_data());
2427 EXPECT_TRUE(app_data->is_app());
2428 EXPECT_EQ(id, app_data->id());
2429 EXPECT_EQ(*v1->version(), app_data->version());
2430
2431 // Update the app to v2, which is an extension.
2432 const Extension* v2 =
2433 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v2.crx"),
2434 INSTALL_UPDATED);
2435 EXPECT_FALSE(v2->is_app());
2436 EXPECT_TRUE(v2->is_extension());
2437 EXPECT_EQ(id, v2->id());
2438
2439 // Make sure we saw an extension item added.
2440 ASSERT_EQ(1u, extensions_processor.changes().size());
2441 const SyncChange& extension_change = extensions_processor.changes()[0];
2442 EXPECT_EQ(SyncChange::ACTION_ADD, extension_change.change_type());
dchengc963c7142016-04-08 03:55:222443 std::unique_ptr<ExtensionSyncData> extension_data =
asargente48ab752016-03-12 00:59:202444 ExtensionSyncData::CreateFromSyncData(extension_change.sync_data());
2445 EXPECT_FALSE(extension_data->is_app());
2446 EXPECT_EQ(id, extension_data->id());
2447 EXPECT_EQ(*v2->version(), extension_data->version());
2448
2449 // Get the current data from the change processors to use as the input to
2450 // the following call to MergeDataAndStartSyncing. This simulates what should
2451 // happen with sync.
2452 syncer::SyncDataList extensions_data =
2453 extensions_processor.GetAllSyncData(syncer::EXTENSIONS);
2454 syncer::SyncDataList apps_data = apps_processor.GetAllSyncData(syncer::APPS);
2455
2456 // Stop syncing, then start again.
2457 extension_sync_service()->StopSyncing(syncer::EXTENSIONS);
2458 extension_sync_service()->StopSyncing(syncer::APPS);
2459 extension_sync_service()->MergeDataAndStartSyncing(
2460 syncer::EXTENSIONS, extensions_data, extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222461 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202462 extension_sync_service()->MergeDataAndStartSyncing(
2463 syncer::APPS, apps_data, apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222464 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202465
2466 // Make sure we saw an app item deleted.
2467 bool found_delete = false;
2468 for (const auto& change : apps_processor.changes()) {
2469 if (change.change_type() == SyncChange::ACTION_DELETE) {
dchengc963c7142016-04-08 03:55:222470 std::unique_ptr<ExtensionSyncData> data =
asargente48ab752016-03-12 00:59:202471 ExtensionSyncData::CreateFromSyncChange(change);
2472 if (data->id() == id) {
2473 found_delete = true;
2474 break;
2475 }
2476 }
2477 }
2478 EXPECT_TRUE(found_delete);
2479
2480 // Make sure there is one extension, and there are no more apps.
2481 EXPECT_EQ(1u, extensions_processor.data().size());
2482 EXPECT_TRUE(apps_processor.data().empty());
2483}