blob: bad69abdfb99bab7ce8d1f9ea55cb1f754f93395 [file] [log] [blame]
treib9afc6212015-10-30 18:49:581// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
avia2f4804a2015-12-24 23:11:135#include <stddef.h>
6
treibb6af28cd2015-12-01 11:19:467#include <map>
dchengc963c7142016-04-08 03:55:228#include <memory>
treib9afc6212015-10-30 18:49:589#include <string>
limasdf3d102542015-12-09 03:58:4510#include <utility>
treib9afc6212015-10-30 18:49:5811
12#include "base/bind.h"
13#include "base/command_line.h"
mamire9609642016-06-28 22:17:5414#include "base/feature_list.h"
treib9afc6212015-10-30 18:49:5815#include "base/files/file_util.h"
avia2f4804a2015-12-24 23:11:1316#include "base/macros.h"
dchengc963c7142016-04-08 03:55:2217#include "base/memory/ptr_util.h"
treib9afc6212015-10-30 18:49:5818#include "base/memory/weak_ptr.h"
19#include "base/metrics/field_trial.h"
20#include "base/test/mock_entropy_provider.h"
21#include "chrome/browser/extensions/component_loader.h"
22#include "chrome/browser/extensions/extension_service.h"
23#include "chrome/browser/extensions/extension_service_test_with_install.h"
24#include "chrome/browser/extensions/extension_sync_data.h"
25#include "chrome/browser/extensions/extension_sync_service.h"
26#include "chrome/browser/extensions/extension_util.h"
27#include "chrome/browser/extensions/updater/extension_updater.h"
treib9afc6212015-10-30 18:49:5828#include "chrome/browser/sync/profile_sync_service_factory.h"
29#include "chrome/common/chrome_constants.h"
30#include "chrome/common/chrome_switches.h"
31#include "chrome/common/extensions/sync_helper.h"
32#include "chrome/test/base/testing_profile.h"
blundell7282b512015-11-09 07:21:1133#include "components/browser_sync/browser/profile_sync_service.h"
rdevlin.cronin738501d2015-11-05 21:51:3634#include "components/crx_file/id_util.h"
treibb6af28cd2015-12-01 11:19:4635#include "components/variations/variations_associated_data.h"
treib9afc6212015-10-30 18:49:5836#include "extensions/browser/app_sorting.h"
37#include "extensions/browser/extension_prefs.h"
38#include "extensions/browser/extension_registry.h"
39#include "extensions/browser/extension_system.h"
40#include "extensions/browser/management_policy.h"
41#include "extensions/browser/test_management_policy.h"
42#include "extensions/common/constants.h"
rdevlin.cronin738501d2015-11-05 21:51:3643#include "extensions/common/extension_builder.h"
treib9afc6212015-10-30 18:49:5844#include "extensions/common/manifest_url_handlers.h"
45#include "extensions/common/permissions/permission_set.h"
rdevlin.cronin738501d2015-11-05 21:51:3646#include "extensions/common/value_builder.h"
treib9afc6212015-10-30 18:49:5847#include "sync/api/fake_sync_change_processor.h"
asargente48ab752016-03-12 00:59:2048#include "sync/api/sync_change_processor_wrapper_for_test.h"
treib9afc6212015-10-30 18:49:5849#include "sync/api/sync_data.h"
50#include "sync/api/sync_error_factory_mock.h"
51#include "testing/gtest/include/gtest/gtest.h"
52
53#if defined(ENABLE_SUPERVISED_USERS)
54#include "chrome/browser/supervised_user/permission_request_creator.h"
55#include "chrome/browser/supervised_user/supervised_user_constants.h"
mamire9609642016-06-28 22:17:5456#include "chrome/browser/supervised_user/supervised_user_features.h"
treib9afc6212015-10-30 18:49:5857#include "chrome/browser/supervised_user/supervised_user_service.h"
58#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
mamire9609642016-06-28 22:17:5459#include "chrome/browser/supervised_user/supervised_user_settings_service.h"
60#include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h"
61#include "chrome/common/pref_names.h"
treib9afc6212015-10-30 18:49:5862#endif
63
64using extensions::AppSorting;
65using extensions::Extension;
66using extensions::ExtensionPrefs;
67using extensions::ExtensionSyncData;
68using extensions::ExtensionSystem;
69using extensions::Manifest;
70using extensions::PermissionSet;
treib65f103042015-12-03 10:21:3671using syncer::SyncChange;
72using syncer::SyncChangeList;
mamire9609642016-06-28 22:17:5473using testing::Mock;
treib65f103042015-12-03 10:21:3674
75namespace {
treib9afc6212015-10-30 18:49:5876
mamir192d7882016-06-22 17:10:1677const char autoupdate[] = "ogjcoiohnmldgjemafoockdghcjciccf";
treib9afc6212015-10-30 18:49:5878const char good0[] = "behllobkkfkfnphdnhnkndlbkcpglgmj";
79const char good2[] = "bjafgdebaacbbbecmhlhpofkepfkgcpa";
mamir192d7882016-06-22 17:10:1680const char good2048[] = "nmgjhmhbleinmjpbdhgajfjkbijcmgbh";
treib9afc6212015-10-30 18:49:5881const char good_crx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
82const char page_action[] = "obcimlgaoabeegjmmpldobjndiealpln";
mamir192d7882016-06-22 17:10:1683const char permissions_increase[] = "pgdpcfcocojkjfbgpiianjngphoopgmo";
treib9afc6212015-10-30 18:49:5884const char theme2_crx[] = "pjpgmfcmabopnnfonnhmdjglfpjjfkbf";
85
treib65f103042015-12-03 10:21:3686SyncChangeList MakeSyncChangeList(const std::string& id,
87 const sync_pb::EntitySpecifics& specifics,
88 SyncChange::SyncChangeType change_type) {
89 syncer::SyncData sync_data =
90 syncer::SyncData::CreateLocalData(id, "Name", specifics);
91 return SyncChangeList(1, SyncChange(FROM_HERE, change_type, sync_data));
92}
93
asargente48ab752016-03-12 00:59:2094// This is a FakeSyncChangeProcessor specialization that maintains a store of
95// SyncData items in the superclass' data_ member variable, treating it like a
96// map keyed by the extension id from the SyncData. Each instance of this class
97// should only be used for one model type (which should be either extensions or
98// apps) to match how the real sync system handles things.
99class StatefulChangeProcessor : public syncer::FakeSyncChangeProcessor {
100 public:
101 explicit StatefulChangeProcessor(syncer::ModelType expected_type)
102 : expected_type_(expected_type) {
103 EXPECT_TRUE(expected_type == syncer::ModelType::EXTENSIONS ||
104 expected_type == syncer::ModelType::APPS);
105 }
106
107 ~StatefulChangeProcessor() override {}
108
109 // We let our parent class, FakeSyncChangeProcessor, handle saving the
110 // changes for us, but in addition we "apply" these changes by treating
111 // the FakeSyncChangeProcessor's SyncDataList as a map keyed by extension
112 // id.
113 syncer::SyncError ProcessSyncChanges(
114 const tracked_objects::Location& from_here,
115 const syncer::SyncChangeList& change_list) override {
116 syncer::FakeSyncChangeProcessor::ProcessSyncChanges(from_here, change_list);
117 for (const auto& change : change_list) {
118 syncer::SyncData sync_data = change.sync_data();
119 EXPECT_EQ(expected_type_, sync_data.GetDataType());
120
dchengc963c7142016-04-08 03:55:22121 std::unique_ptr<ExtensionSyncData> modified =
asargente48ab752016-03-12 00:59:20122 ExtensionSyncData::CreateFromSyncData(sync_data);
123
124 // Start by removing any existing entry for this extension id.
125 syncer::SyncDataList& data_list = data();
126 for (auto iter = data_list.begin(); iter != data_list.end(); ++iter) {
dchengc963c7142016-04-08 03:55:22127 std::unique_ptr<ExtensionSyncData> existing =
asargente48ab752016-03-12 00:59:20128 ExtensionSyncData::CreateFromSyncData(*iter);
129 if (existing->id() == modified->id()) {
130 data_list.erase(iter);
131 break;
132 }
133 }
134
135 // Now add in the new data for this id, if appropriate.
136 if (change.change_type() == SyncChange::ACTION_ADD ||
137 change.change_type() == SyncChange::ACTION_UPDATE) {
138 data_list.push_back(sync_data);
139 } else if (change.change_type() != SyncChange::ACTION_DELETE) {
140 ADD_FAILURE() << "Unexpected change type " << change.change_type();
141 }
142 }
143 return syncer::SyncError();
144 }
145
146 // We override this to help catch the error of trying to use a single
147 // StatefulChangeProcessor to process changes for both extensions and apps
148 // sync data.
149 syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override {
150 EXPECT_EQ(expected_type_, type);
151 return FakeSyncChangeProcessor::GetAllSyncData(type);
152 }
153
154 // This is a helper to vend a wrapped version of this object suitable for
155 // passing in to MergeDataAndStartSyncing, which takes a
dchengc963c7142016-04-08 03:55:22156 // std::unique_ptr<SyncChangeProcessor>, since in tests we typically don't
157 // want to
asargente48ab752016-03-12 00:59:20158 // give up ownership of a local change processor.
dchengc963c7142016-04-08 03:55:22159 std::unique_ptr<syncer::SyncChangeProcessor> GetWrapped() {
160 return base::WrapUnique(
161 new syncer::SyncChangeProcessorWrapperForTest(this));
asargente48ab752016-03-12 00:59:20162 }
163
164 protected:
165 // The expected ModelType of changes that this processor will see.
166 syncer::ModelType expected_type_;
167
168 DISALLOW_COPY_AND_ASSIGN(StatefulChangeProcessor);
169};
170
treib65f103042015-12-03 10:21:36171} // namespace
172
treib9afc6212015-10-30 18:49:58173class ExtensionServiceSyncTest
174 : public extensions::ExtensionServiceTestWithInstall {
175 public:
176 void MockSyncStartFlare(bool* was_called,
177 syncer::ModelType* model_type_passed_in,
178 syncer::ModelType model_type) {
179 *was_called = true;
180 *model_type_passed_in = model_type;
181 }
182
asargente48ab752016-03-12 00:59:20183 // Helper to call MergeDataAndStartSyncing with no server data and dummy
184 // change processor / error factory.
185 void StartSyncing(syncer::ModelType type) {
186 ASSERT_TRUE(type == syncer::EXTENSIONS || type == syncer::APPS);
187 extension_sync_service()->MergeDataAndStartSyncing(
188 type, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22189 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
190 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:20191 }
192
treib9afc6212015-10-30 18:49:58193 protected:
194 // Paths to some of the fake extensions.
195 base::FilePath good0_path() {
196 return data_dir()
197 .AppendASCII("good")
198 .AppendASCII("Extensions")
199 .AppendASCII(good0)
200 .AppendASCII("1.0.0.0");
201 }
202
203 ExtensionSyncService* extension_sync_service() {
204 return ExtensionSyncService::Get(profile());
205 }
206};
207
208TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledComponent) {
209 InitializeEmptyExtensionService();
210
211 bool flare_was_called = false;
212 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
213 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
214 extension_sync_service()->SetSyncStartFlareForTesting(
215 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
216 factory.GetWeakPtr(),
217 &flare_was_called, // Safe due to WeakPtrFactory scope.
218 &triggered_type)); // Safe due to WeakPtrFactory scope.
219
220 // Install a component extension.
221 std::string manifest;
222 ASSERT_TRUE(base::ReadFileToString(
223 good0_path().Append(extensions::kManifestFilename), &manifest));
224 service()->component_loader()->Add(manifest, good0_path());
225 ASSERT_FALSE(service()->is_ready());
226 service()->Init();
227 ASSERT_TRUE(service()->is_ready());
228
229 // Extensions added before service is_ready() don't trigger sync startup.
230 EXPECT_FALSE(flare_was_called);
231 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
232}
233
234TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupPreInstalledNormal) {
235 InitializeGoodInstalledExtensionService();
236
237 bool flare_was_called = false;
238 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
239 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
240 extension_sync_service()->SetSyncStartFlareForTesting(
241 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
242 factory.GetWeakPtr(),
243 &flare_was_called, // Safe due to WeakPtrFactory scope.
244 &triggered_type)); // Safe due to WeakPtrFactory scope.
245
246 ASSERT_FALSE(service()->is_ready());
247 service()->Init();
248 ASSERT_EQ(3u, loaded_.size());
249 ASSERT_TRUE(service()->is_ready());
250
251 // Extensions added before service is_ready() don't trigger sync startup.
252 EXPECT_FALSE(flare_was_called);
253 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
254}
255
256TEST_F(ExtensionServiceSyncTest, DeferredSyncStartupOnInstall) {
257 InitializeEmptyExtensionService();
258 service()->Init();
259 ASSERT_TRUE(service()->is_ready());
260
261 bool flare_was_called = false;
262 syncer::ModelType triggered_type(syncer::UNSPECIFIED);
263 base::WeakPtrFactory<ExtensionServiceSyncTest> factory(this);
264 extension_sync_service()->SetSyncStartFlareForTesting(
265 base::Bind(&ExtensionServiceSyncTest::MockSyncStartFlare,
266 factory.GetWeakPtr(),
267 &flare_was_called, // Safe due to WeakPtrFactory scope.
268 &triggered_type)); // Safe due to WeakPtrFactory scope.
269
270 base::FilePath path = data_dir().AppendASCII("good.crx");
271 InstallCRX(path, INSTALL_NEW);
272
273 EXPECT_TRUE(flare_was_called);
274 EXPECT_EQ(syncer::EXTENSIONS, triggered_type);
275
276 // Reset.
277 flare_was_called = false;
278 triggered_type = syncer::UNSPECIFIED;
279
280 // Once sync starts, flare should no longer be invoked.
281 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36282 syncer::EXTENSIONS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22283 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
284 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58285 path = data_dir().AppendASCII("page_action.crx");
286 InstallCRX(path, INSTALL_NEW);
287 EXPECT_FALSE(flare_was_called);
288 ASSERT_EQ(syncer::UNSPECIFIED, triggered_type);
289}
290
291TEST_F(ExtensionServiceSyncTest, DisableExtensionFromSync) {
292 // Start the extensions service with one external extension already installed.
293 base::FilePath source_install_dir =
294 data_dir().AppendASCII("good").AppendASCII("Extensions");
295 base::FilePath pref_path =
296 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
297
298 InitializeInstalledExtensionService(pref_path, source_install_dir);
299
300 // The user has enabled sync.
301 ProfileSyncService* sync_service =
302 ProfileSyncServiceFactory::GetForProfile(profile());
maxboguefe00952a2016-01-19 19:02:01303 sync_service->SetFirstSetupComplete();
treib9afc6212015-10-30 18:49:58304
305 service()->Init();
306 ASSERT_TRUE(service()->is_ready());
307
308 ASSERT_EQ(3u, loaded_.size());
309
310 // We start enabled.
311 const Extension* extension = service()->GetExtensionById(good0, true);
312 ASSERT_TRUE(extension);
313 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
314
315 // Sync starts up.
316 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36317 syncer::EXTENSIONS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22318 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
319 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58320
321 // Then sync data arrives telling us to disable |good0|.
322 ExtensionSyncData disable_good_crx(*extension, false,
323 Extension::DISABLE_USER_ACTION, false,
mamir192d7882016-06-22 17:10:16324 false, ExtensionSyncData::BOOLEAN_UNSET,
325 false);
treib65f103042015-12-03 10:21:36326 SyncChangeList list(
327 1, disable_good_crx.GetSyncChange(SyncChange::ACTION_UPDATE));
treib9afc6212015-10-30 18:49:58328 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
329
330 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
331}
332
333TEST_F(ExtensionServiceSyncTest, IgnoreSyncChangesWhenLocalStateIsMoreRecent) {
334 // Start the extension service with three extensions already installed.
335 base::FilePath source_install_dir =
336 data_dir().AppendASCII("good").AppendASCII("Extensions");
337 base::FilePath pref_path =
338 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
339
340 InitializeInstalledExtensionService(pref_path, source_install_dir);
341
342 // The user has enabled sync.
343 ProfileSyncService* sync_service =
344 ProfileSyncServiceFactory::GetForProfile(profile());
maxboguefe00952a2016-01-19 19:02:01345 sync_service->SetFirstSetupComplete();
treib9afc6212015-10-30 18:49:58346 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
347 extension_sync_service();
348
349 service()->Init();
350 ASSERT_TRUE(service()->is_ready());
351 ASSERT_EQ(3u, loaded_.size());
352
353 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
354 ASSERT_TRUE(service()->IsExtensionEnabled(good2));
355
356 // Disable and re-enable good0 before first sync data arrives.
357 service()->DisableExtension(good0, Extension::DISABLE_USER_ACTION);
358 ASSERT_FALSE(service()->IsExtensionEnabled(good0));
359 service()->EnableExtension(good0);
360 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
361 // Disable good2 before first sync data arrives (good1 is considered
362 // non-syncable because it has plugin permission).
363 service()->DisableExtension(good2, Extension::DISABLE_USER_ACTION);
364 ASSERT_FALSE(service()->IsExtensionEnabled(good2));
365
366 const Extension* extension0 = service()->GetExtensionById(good0, true);
367 const Extension* extension2 = service()->GetExtensionById(good2, true);
368 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension0));
369 ASSERT_TRUE(extensions::sync_helper::IsSyncable(extension2));
370
371 // Now sync data comes in that says to disable good0 and enable good2.
372 ExtensionSyncData disable_good0(*extension0, false,
373 Extension::DISABLE_USER_ACTION, false, false,
mamir192d7882016-06-22 17:10:16374 ExtensionSyncData::BOOLEAN_UNSET, false);
treib9afc6212015-10-30 18:49:58375 ExtensionSyncData enable_good2(*extension2, true, Extension::DISABLE_NONE,
376 false, false,
mamir192d7882016-06-22 17:10:16377 ExtensionSyncData::BOOLEAN_UNSET, false);
treib9afc6212015-10-30 18:49:58378 syncer::SyncDataList sync_data;
379 sync_data.push_back(disable_good0.GetSyncData());
380 sync_data.push_back(enable_good2.GetSyncData());
381 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:22382 syncer::EXTENSIONS, sync_data,
383 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
384 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58385
386 // Both sync changes should be ignored, since the local state was changed
387 // before sync started, and so the local state is considered more recent.
388 EXPECT_TRUE(service()->IsExtensionEnabled(good0));
389 EXPECT_FALSE(service()->IsExtensionEnabled(good2));
390}
391
treibb794dd52015-12-01 18:47:14392TEST_F(ExtensionServiceSyncTest, DontSelfNotify) {
393 // Start the extension service with three extensions already installed.
394 base::FilePath source_install_dir =
395 data_dir().AppendASCII("good").AppendASCII("Extensions");
396 base::FilePath pref_path =
397 source_install_dir.DirName().Append(chrome::kPreferencesFilename);
398
399 InitializeInstalledExtensionService(pref_path, source_install_dir);
400
401 // The user has enabled sync.
maxboguefe00952a2016-01-19 19:02:01402 ProfileSyncServiceFactory::GetForProfile(profile())->SetFirstSetupComplete();
treibb794dd52015-12-01 18:47:14403 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
404 extension_sync_service();
405
406 service()->Init();
407 ASSERT_TRUE(service()->is_ready());
408 ASSERT_EQ(3u, loaded_.size());
409 ASSERT_TRUE(service()->IsExtensionEnabled(good0));
410
411 syncer::FakeSyncChangeProcessor* processor =
412 new syncer::FakeSyncChangeProcessor;
413 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:22414 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
415 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treibb794dd52015-12-01 18:47:14416
417 processor->changes().clear();
418
419 // Simulate various incoming sync changes, and make sure they don't result in
420 // any outgoing changes.
421
422 {
423 const Extension* extension = service()->GetExtensionById(good0, true);
424 ASSERT_TRUE(extension);
425
426 // Disable the extension.
427 ExtensionSyncData data(*extension, false, Extension::DISABLE_USER_ACTION,
mamir192d7882016-06-22 17:10:16428 false, false, ExtensionSyncData::BOOLEAN_UNSET,
429 false);
treib65f103042015-12-03 10:21:36430 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14431
432 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
433
434 EXPECT_TRUE(processor->changes().empty());
435 }
436
437 {
438 const Extension* extension = service()->GetExtensionById(good0, true);
439 ASSERT_TRUE(extension);
440
441 // Set incognito enabled to true.
442 ExtensionSyncData data(*extension, false, Extension::DISABLE_NONE, true,
mamir192d7882016-06-22 17:10:16443 false, ExtensionSyncData::BOOLEAN_UNSET, false);
treib65f103042015-12-03 10:21:36444 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14445
446 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
447
448 EXPECT_TRUE(processor->changes().empty());
449 }
450
451 {
452 const Extension* extension = service()->GetExtensionById(good0, true);
453 ASSERT_TRUE(extension);
454
455 // Add another disable reason.
456 ExtensionSyncData data(*extension, false,
457 Extension::DISABLE_USER_ACTION |
458 Extension::DISABLE_PERMISSIONS_INCREASE,
mamir192d7882016-06-22 17:10:16459 false, false, ExtensionSyncData::BOOLEAN_UNSET,
460 false);
treib65f103042015-12-03 10:21:36461 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_UPDATE));
treibb794dd52015-12-01 18:47:14462
463 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
464
465 EXPECT_TRUE(processor->changes().empty());
466 }
467
468 {
469 const Extension* extension = service()->GetExtensionById(good0, true);
470 ASSERT_TRUE(extension);
471
472 // Uninstall the extension.
473 ExtensionSyncData data(*extension, false,
474 Extension::DISABLE_USER_ACTION |
475 Extension::DISABLE_PERMISSIONS_INCREASE,
mamir192d7882016-06-22 17:10:16476 false, false, ExtensionSyncData::BOOLEAN_UNSET,
477 false);
treib65f103042015-12-03 10:21:36478 SyncChangeList list(1, data.GetSyncChange(SyncChange::ACTION_DELETE));
treibb794dd52015-12-01 18:47:14479
480 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
481
482 EXPECT_TRUE(processor->changes().empty());
483 }
484}
485
treib9afc6212015-10-30 18:49:58486TEST_F(ExtensionServiceSyncTest, GetSyncData) {
487 InitializeEmptyExtensionService();
488 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
489 const Extension* extension = service()->GetInstalledExtension(good_crx);
490 ASSERT_TRUE(extension);
491
492 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36493 syncer::EXTENSIONS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22494 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
495 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58496
497 syncer::SyncDataList list =
498 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
499 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22500 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58501 ExtensionSyncData::CreateFromSyncData(list[0]);
502 ASSERT_TRUE(data.get());
503 EXPECT_EQ(extension->id(), data->id());
504 EXPECT_FALSE(data->uninstalled());
505 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
506 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
507 data->incognito_enabled());
508 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
robpercivaldcd8b102016-01-25 19:39:00509 EXPECT_EQ(data->version(), *extension->version());
treib9afc6212015-10-30 18:49:58510 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
511 data->update_url());
512 EXPECT_EQ(extension->name(), data->name());
513}
514
treib29e1b9b12015-11-11 08:50:56515TEST_F(ExtensionServiceSyncTest, GetSyncDataDisableReasons) {
516 InitializeEmptyExtensionService();
517 const Extension* extension =
518 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
519 ASSERT_TRUE(extension);
520
treib29e1b9b12015-11-11 08:50:56521 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36522 syncer::EXTENSIONS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22523 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
524 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib29e1b9b12015-11-11 08:50:56525
526 {
527 syncer::SyncDataList list =
528 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
529 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22530 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56531 ExtensionSyncData::CreateFromSyncData(list[0]);
532 ASSERT_TRUE(data.get());
533 EXPECT_TRUE(data->enabled());
534 EXPECT_TRUE(data->supports_disable_reasons());
535 EXPECT_EQ(Extension::DISABLE_NONE, data->disable_reasons());
536 }
537
538 // Syncable disable reason, should propagate to sync.
539 service()->DisableExtension(good_crx, Extension::DISABLE_USER_ACTION);
540 {
541 syncer::SyncDataList list =
542 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
543 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22544 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56545 ExtensionSyncData::CreateFromSyncData(list[0]);
546 ASSERT_TRUE(data.get());
547 EXPECT_FALSE(data->enabled());
548 EXPECT_TRUE(data->supports_disable_reasons());
549 EXPECT_EQ(Extension::DISABLE_USER_ACTION, data->disable_reasons());
550 }
551 service()->EnableExtension(good_crx);
552
553 // Non-syncable disable reason. The sync data should still say "enabled".
554 service()->DisableExtension(good_crx, Extension::DISABLE_RELOAD);
555 {
556 syncer::SyncDataList list =
557 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
558 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22559 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56560 ExtensionSyncData::CreateFromSyncData(list[0]);
561 ASSERT_TRUE(data.get());
562 EXPECT_TRUE(data->enabled());
563 EXPECT_TRUE(data->supports_disable_reasons());
564 EXPECT_EQ(Extension::DISABLE_NONE, data->disable_reasons());
565 }
566 service()->EnableExtension(good_crx);
567
568 // Both a syncable and a non-syncable disable reason, only the former should
569 // propagate to sync.
570 service()->DisableExtension(
571 good_crx, Extension::DISABLE_USER_ACTION | Extension::DISABLE_RELOAD);
572 {
573 syncer::SyncDataList list =
574 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
575 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22576 std::unique_ptr<ExtensionSyncData> data =
treib29e1b9b12015-11-11 08:50:56577 ExtensionSyncData::CreateFromSyncData(list[0]);
578 ASSERT_TRUE(data.get());
579 EXPECT_FALSE(data->enabled());
580 EXPECT_TRUE(data->supports_disable_reasons());
581 EXPECT_EQ(Extension::DISABLE_USER_ACTION, data->disable_reasons());
582 }
583 service()->EnableExtension(good_crx);
584}
585
treib9afc6212015-10-30 18:49:58586TEST_F(ExtensionServiceSyncTest, GetSyncDataTerminated) {
587 InitializeEmptyExtensionService();
588 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
589 TerminateExtension(good_crx);
590 const Extension* extension = service()->GetInstalledExtension(good_crx);
591 ASSERT_TRUE(extension);
592
treib9afc6212015-10-30 18:49:58593 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36594 syncer::EXTENSIONS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22595 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
596 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58597
598 syncer::SyncDataList list =
599 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
600 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22601 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58602 ExtensionSyncData::CreateFromSyncData(list[0]);
603 ASSERT_TRUE(data.get());
604 EXPECT_EQ(extension->id(), data->id());
605 EXPECT_FALSE(data->uninstalled());
606 EXPECT_EQ(service()->IsExtensionEnabled(good_crx), data->enabled());
607 EXPECT_EQ(extensions::util::IsIncognitoEnabled(good_crx, profile()),
608 data->incognito_enabled());
609 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
robpercivaldcd8b102016-01-25 19:39:00610 EXPECT_EQ(data->version(), *extension->version());
treib9afc6212015-10-30 18:49:58611 EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(extension),
612 data->update_url());
613 EXPECT_EQ(extension->name(), data->name());
614}
615
616TEST_F(ExtensionServiceSyncTest, GetSyncDataFilter) {
617 InitializeEmptyExtensionService();
618 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
619 const Extension* extension = service()->GetInstalledExtension(good_crx);
620 ASSERT_TRUE(extension);
621
treib9afc6212015-10-30 18:49:58622 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36623 syncer::APPS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22624 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
625 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58626
627 syncer::SyncDataList list =
628 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
629 ASSERT_EQ(list.size(), 0U);
630}
631
632TEST_F(ExtensionServiceSyncTest, GetSyncExtensionDataUserSettings) {
633 InitializeEmptyExtensionService();
634 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
635 const Extension* extension = service()->GetInstalledExtension(good_crx);
636 ASSERT_TRUE(extension);
637
treib9afc6212015-10-30 18:49:58638 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36639 syncer::EXTENSIONS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22640 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
641 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58642
643 {
644 syncer::SyncDataList list =
645 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
646 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22647 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58648 ExtensionSyncData::CreateFromSyncData(list[0]);
649 ASSERT_TRUE(data.get());
650 EXPECT_TRUE(data->enabled());
651 EXPECT_FALSE(data->incognito_enabled());
652 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
653 }
654
655 service()->DisableExtension(good_crx, Extension::DISABLE_USER_ACTION);
656 {
657 syncer::SyncDataList list =
658 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
659 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22660 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58661 ExtensionSyncData::CreateFromSyncData(list[0]);
662 ASSERT_TRUE(data.get());
663 EXPECT_FALSE(data->enabled());
664 EXPECT_FALSE(data->incognito_enabled());
665 EXPECT_EQ(ExtensionSyncData::BOOLEAN_UNSET, data->all_urls_enabled());
666 }
667
668 extensions::util::SetIsIncognitoEnabled(good_crx, profile(), true);
669 extensions::util::SetAllowedScriptingOnAllUrls(
670 good_crx, profile(), false);
671 {
672 syncer::SyncDataList list =
673 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
674 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22675 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58676 ExtensionSyncData::CreateFromSyncData(list[0]);
677 ASSERT_TRUE(data.get());
678 EXPECT_FALSE(data->enabled());
679 EXPECT_TRUE(data->incognito_enabled());
680 EXPECT_EQ(ExtensionSyncData::BOOLEAN_FALSE, data->all_urls_enabled());
681 }
682
683 service()->EnableExtension(good_crx);
684 extensions::util::SetAllowedScriptingOnAllUrls(
685 good_crx, profile(), true);
686 {
687 syncer::SyncDataList list =
688 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
689 ASSERT_EQ(list.size(), 1U);
dchengc963c7142016-04-08 03:55:22690 std::unique_ptr<ExtensionSyncData> data =
treib9afc6212015-10-30 18:49:58691 ExtensionSyncData::CreateFromSyncData(list[0]);
692 ASSERT_TRUE(data.get());
693 EXPECT_TRUE(data->enabled());
694 EXPECT_TRUE(data->incognito_enabled());
695 EXPECT_EQ(ExtensionSyncData::BOOLEAN_TRUE, data->all_urls_enabled());
696 }
697}
698
699TEST_F(ExtensionServiceSyncTest, SyncForUninstalledExternalExtension) {
700 InitializeEmptyExtensionService();
701 InstallCRXWithLocation(
702 data_dir().AppendASCII("good.crx"), Manifest::EXTERNAL_PREF, INSTALL_NEW);
703 const Extension* extension = service()->GetInstalledExtension(good_crx);
704 ASSERT_TRUE(extension);
705
treib9afc6212015-10-30 18:49:58706 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36707 syncer::EXTENSIONS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22708 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
709 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:20710 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:58711
712 UninstallExtension(good_crx, false);
713 EXPECT_TRUE(
714 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
715
716 sync_pb::EntitySpecifics specifics;
717 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
718 sync_pb::ExtensionSpecifics* extension_specifics =
719 app_specifics->mutable_extension();
720 extension_specifics->set_id(good_crx);
721 extension_specifics->set_version("1.0");
722 extension_specifics->set_enabled(true);
723
treib65f103042015-12-03 10:21:36724 SyncChangeList list =
725 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:58726
727 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
728 EXPECT_TRUE(
729 ExtensionPrefs::Get(profile())->IsExternalExtensionUninstalled(good_crx));
730}
731
732TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettings) {
733 InitializeEmptyExtensionService();
734 const Extension* app =
735 PackAndInstallCRX(data_dir().AppendASCII("app"), INSTALL_NEW);
736 ASSERT_TRUE(app);
737 ASSERT_TRUE(app->is_app());
738
treib9afc6212015-10-30 18:49:58739 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36740 syncer::APPS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22741 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
742 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58743
744 syncer::StringOrdinal initial_ordinal =
745 syncer::StringOrdinal::CreateInitialOrdinal();
746 {
747 syncer::SyncDataList list =
748 extension_sync_service()->GetAllSyncData(syncer::APPS);
749 ASSERT_EQ(list.size(), 1U);
750
dchengc963c7142016-04-08 03:55:22751 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58752 ExtensionSyncData::CreateFromSyncData(list[0]);
753 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->app_launch_ordinal()));
754 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
755 }
756
deepak.m14ba69e62015-11-17 05:42:12757 AppSorting* sorting = ExtensionSystem::Get(profile())->app_sorting();
treib9afc6212015-10-30 18:49:58758 sorting->SetAppLaunchOrdinal(app->id(), initial_ordinal.CreateAfter());
759 {
760 syncer::SyncDataList list =
761 extension_sync_service()->GetAllSyncData(syncer::APPS);
762 ASSERT_EQ(list.size(), 1U);
763
dchengc963c7142016-04-08 03:55:22764 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58765 ExtensionSyncData::CreateFromSyncData(list[0]);
766 ASSERT_TRUE(app_sync_data.get());
767 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
768 EXPECT_TRUE(initial_ordinal.Equals(app_sync_data->page_ordinal()));
769 }
770
771 sorting->SetPageOrdinal(app->id(), initial_ordinal.CreateAfter());
772 {
773 syncer::SyncDataList list =
774 extension_sync_service()->GetAllSyncData(syncer::APPS);
775 ASSERT_EQ(list.size(), 1U);
776
dchengc963c7142016-04-08 03:55:22777 std::unique_ptr<ExtensionSyncData> app_sync_data =
treib9afc6212015-10-30 18:49:58778 ExtensionSyncData::CreateFromSyncData(list[0]);
779 ASSERT_TRUE(app_sync_data.get());
780 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->app_launch_ordinal()));
781 EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data->page_ordinal()));
782 }
783}
784
785// TODO (rdevlin.cronin): The OnExtensionMoved() method has been removed from
786// ExtensionService, so this test probably needs a new home. Unfortunately, it
787// relies pretty heavily on things like InitializeExtension[Sync]Service() and
788// PackAndInstallCRX(). When we clean up a bit more, this should move out.
789TEST_F(ExtensionServiceSyncTest, GetSyncAppDataUserSettingsOnExtensionMoved) {
790 InitializeEmptyExtensionService();
791 const size_t kAppCount = 3;
792 const Extension* apps[kAppCount];
793 apps[0] = PackAndInstallCRX(data_dir().AppendASCII("app1"), INSTALL_NEW);
794 apps[1] = PackAndInstallCRX(data_dir().AppendASCII("app2"), INSTALL_NEW);
795 apps[2] = PackAndInstallCRX(data_dir().AppendASCII("app4"), INSTALL_NEW);
796 for (size_t i = 0; i < kAppCount; ++i) {
797 ASSERT_TRUE(apps[i]);
798 ASSERT_TRUE(apps[i]->is_app());
799 }
800
treib9afc6212015-10-30 18:49:58801 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36802 syncer::APPS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22803 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
804 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58805
deepak.m14ba69e62015-11-17 05:42:12806 ExtensionSystem::Get(service()->GetBrowserContext())
treib9afc6212015-10-30 18:49:58807 ->app_sorting()
808 ->OnExtensionMoved(apps[0]->id(), apps[1]->id(), apps[2]->id());
809 {
810 syncer::SyncDataList list =
811 extension_sync_service()->GetAllSyncData(syncer::APPS);
812 ASSERT_EQ(list.size(), 3U);
813
dchengc963c7142016-04-08 03:55:22814 std::unique_ptr<ExtensionSyncData> data[kAppCount];
treib9afc6212015-10-30 18:49:58815 for (size_t i = 0; i < kAppCount; ++i) {
816 data[i] = ExtensionSyncData::CreateFromSyncData(list[i]);
817 ASSERT_TRUE(data[i].get());
818 }
819
820 // The sync data is not always in the same order our apps were installed in,
821 // so we do that sorting here so we can make sure the values are changed as
822 // expected.
823 syncer::StringOrdinal app_launch_ordinals[kAppCount];
824 for (size_t i = 0; i < kAppCount; ++i) {
825 for (size_t j = 0; j < kAppCount; ++j) {
826 if (apps[i]->id() == data[j]->id())
827 app_launch_ordinals[i] = data[j]->app_launch_ordinal();
828 }
829 }
830
831 EXPECT_TRUE(app_launch_ordinals[1].LessThan(app_launch_ordinals[0]));
832 EXPECT_TRUE(app_launch_ordinals[0].LessThan(app_launch_ordinals[2]));
833 }
834}
835
836TEST_F(ExtensionServiceSyncTest, GetSyncDataList) {
837 InitializeEmptyExtensionService();
838 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
839 InstallCRX(data_dir().AppendASCII("page_action.crx"), INSTALL_NEW);
840 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
841 InstallCRX(data_dir().AppendASCII("theme2.crx"), INSTALL_NEW);
842
treib9afc6212015-10-30 18:49:58843 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36844 syncer::APPS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22845 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
846 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58847 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36848 syncer::EXTENSIONS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22849 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
850 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58851
852 service()->DisableExtension(page_action, Extension::DISABLE_USER_ACTION);
853 TerminateExtension(theme2_crx);
854
855 EXPECT_EQ(0u, extension_sync_service()->GetAllSyncData(syncer::APPS).size());
856 EXPECT_EQ(
857 2u, extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS).size());
858}
859
860TEST_F(ExtensionServiceSyncTest, ProcessSyncDataUninstall) {
861 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:58862 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36863 syncer::EXTENSIONS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22864 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
865 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58866
867 sync_pb::EntitySpecifics specifics;
868 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
869 ext_specifics->set_id(good_crx);
870 ext_specifics->set_version("1.0");
treib65f103042015-12-03 10:21:36871
872 SyncChangeList list =
873 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:58874
875 // Should do nothing.
876 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
877 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
878
879 // Install the extension.
880 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
881 InstallCRX(extension_path, INSTALL_NEW);
882 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
883
884 // Should uninstall the extension.
885 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
886 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
887
888 // Should again do nothing.
889 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
890 EXPECT_FALSE(service()->GetExtensionById(good_crx, true));
891}
892
893TEST_F(ExtensionServiceSyncTest, ProcessSyncDataWrongType) {
894 InitializeEmptyExtensionService();
asargente48ab752016-03-12 00:59:20895 StartSyncing(syncer::EXTENSIONS);
896 StartSyncing(syncer::APPS);
treib9afc6212015-10-30 18:49:58897
898 // Install the extension.
899 base::FilePath extension_path = data_dir().AppendASCII("good.crx");
900 InstallCRX(extension_path, INSTALL_NEW);
901 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
902
903 sync_pb::EntitySpecifics specifics;
904 sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
905 sync_pb::ExtensionSpecifics* extension_specifics =
906 app_specifics->mutable_extension();
907 extension_specifics->set_id(good_crx);
908 extension_specifics->set_version(
909 service()->GetInstalledExtension(good_crx)->version()->GetString());
910
911 {
912 extension_specifics->set_enabled(true);
treib65f103042015-12-03 10:21:36913
914 SyncChangeList list =
915 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_DELETE);
treib9afc6212015-10-30 18:49:58916
917 // Should do nothing
918 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
919 EXPECT_TRUE(service()->GetExtensionById(good_crx, true));
920 }
921
922 {
923 extension_specifics->set_enabled(false);
treib65f103042015-12-03 10:21:36924
925 SyncChangeList list =
926 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:58927
928 // Should again do nothing.
929 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
930 EXPECT_TRUE(service()->GetExtensionById(good_crx, false));
931 }
932}
933
934TEST_F(ExtensionServiceSyncTest, ProcessSyncDataSettings) {
935 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:58936 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:36937 syncer::EXTENSIONS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:22938 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
939 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:58940
941 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
942 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
943 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
944 EXPECT_FALSE(extensions::util::HasSetAllowedScriptingOnAllUrls(
945 good_crx, profile()));
946 const bool kDefaultAllowedScripting =
947 extensions::util::DefaultAllowedScriptingOnAllUrls();
948 EXPECT_EQ(kDefaultAllowedScripting,
949 extensions::util::AllowedScriptingOnAllUrls(good_crx, profile()));
950
951 sync_pb::EntitySpecifics specifics;
952 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
953 ext_specifics->set_id(good_crx);
954 ext_specifics->set_version(
955 service()->GetInstalledExtension(good_crx)->version()->GetString());
956 ext_specifics->set_enabled(false);
957
958 {
treib65f103042015-12-03 10:21:36959 SyncChangeList list =
960 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
961
treib9afc6212015-10-30 18:49:58962 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
963 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
964 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
965 EXPECT_FALSE(extensions::util::HasSetAllowedScriptingOnAllUrls(
966 good_crx, profile()));
967 EXPECT_EQ(kDefaultAllowedScripting,
968 extensions::util::AllowedScriptingOnAllUrls(good_crx, profile()));
969 }
970
971 {
972 ext_specifics->set_enabled(true);
973 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:36974
975 SyncChangeList list =
976 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
977
treib9afc6212015-10-30 18:49:58978 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
979 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
980 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
981 }
982
983 {
984 ext_specifics->set_enabled(false);
985 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:36986
987 SyncChangeList list =
988 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
989
treib9afc6212015-10-30 18:49:58990 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
991 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
992 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
993 }
994
995 {
996 ext_specifics->set_enabled(true);
997 ext_specifics->set_all_urls_enabled(!kDefaultAllowedScripting);
treib65f103042015-12-03 10:21:36998
999 SyncChangeList list =
1000 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1001
treib9afc6212015-10-30 18:49:581002 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1003 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1004 EXPECT_TRUE(extensions::util::HasSetAllowedScriptingOnAllUrls(
1005 good_crx, profile()));
1006 EXPECT_EQ(!kDefaultAllowedScripting,
1007 extensions::util::AllowedScriptingOnAllUrls(good_crx, profile()));
1008 }
1009
1010 {
1011 ext_specifics->set_all_urls_enabled(kDefaultAllowedScripting);
treib65f103042015-12-03 10:21:361012
1013 SyncChangeList list =
1014 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1015
treib9afc6212015-10-30 18:49:581016 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1017 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1018 EXPECT_TRUE(extensions::util::HasSetAllowedScriptingOnAllUrls(
1019 good_crx, profile()));
1020 EXPECT_EQ(kDefaultAllowedScripting,
1021 extensions::util::AllowedScriptingOnAllUrls(good_crx, profile()));
1022 }
1023
1024 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1025}
1026
1027TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNewExtension) {
1028 InitializeEmptyExtensionService();
treib9afc6212015-10-30 18:49:581029 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361030 syncer::EXTENSIONS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:221031 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
1032 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:581033
1034 const base::FilePath path = data_dir().AppendASCII("good.crx");
1035 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1036
1037 struct TestCase {
1038 const char* name; // For failure output only.
1039 bool sync_enabled; // The "enabled" flag coming in from Sync.
1040 // The disable reason(s) coming in from Sync, or -1 for "not set".
1041 int sync_disable_reasons;
1042 // The disable reason(s) that should be set on the installed extension.
1043 // This will usually be the same as |sync_disable_reasons|, but see the
1044 // "Legacy" case.
1045 int expect_disable_reasons;
1046 // Whether the extension's permissions should be auto-granted during
1047 // installation.
1048 bool expect_permissions_granted;
1049 } test_cases[] = {
1050 // Standard case: Extension comes in enabled; permissions should be granted
1051 // during installation.
1052 { "Standard", true, 0, 0, true },
1053 // If the extension comes in disabled, its permissions should still be
1054 // granted (the user already approved them on another machine).
1055 { "Disabled", false, Extension::DISABLE_USER_ACTION,
1056 Extension::DISABLE_USER_ACTION, true },
1057 // Legacy case (<M45): No disable reasons come in from Sync (see
1058 // crbug.com/484214). After installation, the reason should be set to
treib3b91e9f2015-11-04 11:29:411059 // DISABLE_USER_ACTION (default assumption).
1060 { "Legacy", false, -1, Extension::DISABLE_USER_ACTION, true },
treib9afc6212015-10-30 18:49:581061 // If the extension came in disabled due to a permissions increase, then the
1062 // user has *not* approved the permissions, and they shouldn't be granted.
1063 // crbug.com/484214
1064 { "PermissionsIncrease", false, Extension::DISABLE_PERMISSIONS_INCREASE,
1065 Extension::DISABLE_PERMISSIONS_INCREASE, false },
1066 };
1067
1068 for (const TestCase& test_case : test_cases) {
1069 SCOPED_TRACE(test_case.name);
1070
1071 sync_pb::EntitySpecifics specifics;
1072 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1073 ext_specifics->set_id(good_crx);
1074 ext_specifics->set_version(base::Version("1").GetString());
1075 ext_specifics->set_enabled(test_case.sync_enabled);
1076 if (test_case.sync_disable_reasons != -1)
1077 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1078
treib65f103042015-12-03 10:21:361079 SyncChangeList list =
1080 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1081
treib9afc6212015-10-30 18:49:581082 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1083
1084 ASSERT_TRUE(service()->pending_extension_manager()->IsIdPending(good_crx));
1085 UpdateExtension(good_crx, path, test_case.sync_enabled ? ENABLED
1086 : DISABLED);
1087 EXPECT_EQ(test_case.expect_disable_reasons,
1088 prefs->GetDisableReasons(good_crx));
dchengc963c7142016-04-08 03:55:221089 std::unique_ptr<const PermissionSet> permissions =
treib9afc6212015-10-30 18:49:581090 prefs->GetGrantedPermissions(good_crx);
1091 EXPECT_EQ(test_case.expect_permissions_granted, !permissions->IsEmpty());
1092 ASSERT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1093
1094 // Remove the extension again, so we can install it again for the next case.
1095 UninstallExtension(good_crx, false,
1096 test_case.sync_enabled ? Extension::ENABLED
1097 : Extension::DISABLED);
1098 }
1099}
1100
1101TEST_F(ExtensionServiceSyncTest, ProcessSyncDataTerminatedExtension) {
1102 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581103 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361104 syncer::EXTENSIONS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:221105 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
1106 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:581107
1108 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1109 TerminateExtension(good_crx);
1110 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1111 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1112
1113 sync_pb::EntitySpecifics specifics;
1114 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1115 ext_specifics->set_id(good_crx);
1116 ext_specifics->set_version(
1117 service()->GetInstalledExtension(good_crx)->version()->GetString());
1118 ext_specifics->set_enabled(false);
1119 ext_specifics->set_incognito_enabled(true);
treib65f103042015-12-03 10:21:361120
1121 SyncChangeList list =
1122 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581123
1124 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1125 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1126 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1127
1128 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1129}
1130
1131TEST_F(ExtensionServiceSyncTest, ProcessSyncDataVersionCheck) {
1132 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581133 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361134 syncer::EXTENSIONS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:221135 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
1136 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:581137
1138 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1139 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1140 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1141
1142 sync_pb::EntitySpecifics specifics;
1143 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1144 ext_specifics->set_id(good_crx);
1145 ext_specifics->set_enabled(true);
1146
1147 const base::Version installed_version =
1148 *service()->GetInstalledExtension(good_crx)->version();
1149
1150 {
1151 ext_specifics->set_version(installed_version.GetString());
treib65f103042015-12-03 10:21:361152
1153 SyncChangeList list =
1154 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581155
1156 // Should do nothing if extension version == sync version.
1157 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1158 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1159 // Make sure the version we'll send back to sync didn't change.
1160 syncer::SyncDataList data =
1161 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1162 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221163 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581164 ExtensionSyncData::CreateFromSyncData(data[0]);
1165 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001166 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581167 }
1168
1169 // Should do nothing if extension version > sync version.
1170 {
1171 ext_specifics->set_version("0.0.0.0");
treib65f103042015-12-03 10:21:361172
1173 SyncChangeList list =
1174 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581175
1176 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1177 EXPECT_FALSE(service()->updater()->WillCheckSoon());
1178 // Make sure the version we'll send back to sync didn't change.
1179 syncer::SyncDataList data =
1180 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1181 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221182 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581183 ExtensionSyncData::CreateFromSyncData(data[0]);
1184 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001185 EXPECT_EQ(installed_version, extension_data->version());
treib9afc6212015-10-30 18:49:581186 }
1187
1188 // Should kick off an update if extension version < sync version.
1189 {
1190 const base::Version new_version("9.9.9.9");
1191 ext_specifics->set_version(new_version.GetString());
treib65f103042015-12-03 10:21:361192
1193 SyncChangeList list =
1194 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581195
1196 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1197 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1198 // Make sure that we'll send the NEW version back to sync, even though we
1199 // haven't actually updated yet. This is to prevent the data in sync from
1200 // flip-flopping back and forth until all clients are up to date.
1201 syncer::SyncDataList data =
1202 extension_sync_service()->GetAllSyncData(syncer::EXTENSIONS);
1203 ASSERT_EQ(1u, data.size());
dchengc963c7142016-04-08 03:55:221204 std::unique_ptr<ExtensionSyncData> extension_data =
treib9afc6212015-10-30 18:49:581205 ExtensionSyncData::CreateFromSyncData(data[0]);
1206 ASSERT_TRUE(extension_data);
robpercivaldcd8b102016-01-25 19:39:001207 EXPECT_EQ(new_version, extension_data->version());
treib9afc6212015-10-30 18:49:581208 }
1209
1210 EXPECT_FALSE(service()->pending_extension_manager()->IsIdPending(good_crx));
1211}
1212
1213TEST_F(ExtensionServiceSyncTest, ProcessSyncDataNotInstalled) {
1214 InitializeExtensionServiceWithUpdater();
treib9afc6212015-10-30 18:49:581215 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361216 syncer::EXTENSIONS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:221217 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
1218 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:581219
1220 sync_pb::EntitySpecifics specifics;
1221 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1222 ext_specifics->set_id(good_crx);
1223 ext_specifics->set_enabled(false);
1224 ext_specifics->set_incognito_enabled(true);
1225 ext_specifics->set_update_url("http://www.google.com/");
1226 ext_specifics->set_version("1.2.3.4");
treib65f103042015-12-03 10:21:361227
1228 SyncChangeList list =
1229 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
treib9afc6212015-10-30 18:49:581230
1231 EXPECT_TRUE(service()->IsExtensionEnabled(good_crx));
1232 EXPECT_FALSE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1233 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1234 EXPECT_TRUE(service()->updater()->WillCheckSoon());
1235 EXPECT_FALSE(service()->IsExtensionEnabled(good_crx));
1236 EXPECT_TRUE(extensions::util::IsIncognitoEnabled(good_crx, profile()));
1237
1238 const extensions::PendingExtensionInfo* info;
1239 EXPECT_TRUE(
1240 (info = service()->pending_extension_manager()->GetById(good_crx)));
1241 EXPECT_EQ(ext_specifics->update_url(), info->update_url().spec());
1242 EXPECT_TRUE(info->is_from_sync());
1243 EXPECT_EQ(Manifest::INTERNAL, info->install_source());
1244 // TODO(akalin): Figure out a way to test |info.ShouldAllowInstall()|.
1245}
1246
1247TEST_F(ExtensionServiceSyncTest, ProcessSyncDataEnableDisable) {
1248 InitializeEmptyExtensionService();
1249 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361250 syncer::EXTENSIONS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:221251 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
1252 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:581253
1254 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1255
1256 struct TestCase {
1257 const char* name; // For failure output only.
1258 // Set of disable reasons before any Sync data comes in. If this is != 0,
1259 // the extension is disabled.
1260 int previous_disable_reasons;
1261 bool sync_enable; // The enabled flag coming in from Sync.
1262 // The disable reason(s) coming in from Sync, or -1 for "not set".
1263 int sync_disable_reasons;
1264 // The expected set of disable reasons after processing the Sync update. The
1265 // extension should be disabled iff this is != 0.
1266 int expect_disable_reasons;
1267 } test_cases[] = {
1268 { "NopEnable", 0, true, 0, 0 },
1269 { "NopDisable", Extension::DISABLE_USER_ACTION, false,
1270 Extension::DISABLE_USER_ACTION, Extension::DISABLE_USER_ACTION },
treib29e1b9b12015-11-11 08:50:561271 { "Enable", Extension::DISABLE_USER_ACTION, true, 0, 0 },
treib9afc6212015-10-30 18:49:581272 { "Disable", 0, false, Extension::DISABLE_USER_ACTION,
1273 Extension::DISABLE_USER_ACTION },
treib9afc6212015-10-30 18:49:581274 { "AddDisableReason", Extension::DISABLE_REMOTE_INSTALL, false,
1275 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION,
1276 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION },
treib9afc6212015-10-30 18:49:581277 { "RemoveDisableReason",
1278 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION, false,
1279 Extension::DISABLE_USER_ACTION, Extension::DISABLE_USER_ACTION },
treib29e1b9b12015-11-11 08:50:561280 { "PreserveLocalDisableReason", Extension::DISABLE_RELOAD, true, 0,
1281 Extension::DISABLE_RELOAD },
1282 { "PreserveOnlyLocalDisableReason",
1283 Extension::DISABLE_USER_ACTION | Extension::DISABLE_RELOAD, true, 0,
1284 Extension::DISABLE_RELOAD },
1285
1286 // Interaction with Chrome clients <=M44, which don't sync disable_reasons
1287 // at all (any existing reasons are preserved).
1288 { "M44Enable", Extension::DISABLE_USER_ACTION, true, -1, 0 },
1289 // An M44 client enables an extension that had been disabled on a new
1290 // client. The disable reasons are still be there, but should be ignored.
1291 { "M44ReEnable", Extension::DISABLE_USER_ACTION, true,
1292 Extension::DISABLE_USER_ACTION, 0 },
1293 { "M44Disable", 0, false, -1, Extension::DISABLE_USER_ACTION },
1294 { "M44ReDisable", 0, false, 0, Extension::DISABLE_USER_ACTION },
1295 { "M44AlreadyDisabledByUser", Extension::DISABLE_USER_ACTION, false, -1,
1296 Extension::DISABLE_USER_ACTION},
1297 { "M44AlreadyDisabledWithOtherReason", Extension::DISABLE_REMOTE_INSTALL,
1298 false, -1,
1299 Extension::DISABLE_REMOTE_INSTALL | Extension::DISABLE_USER_ACTION },
treib9afc6212015-10-30 18:49:581300 };
1301
1302 for (const TestCase& test_case : test_cases) {
1303 SCOPED_TRACE(test_case.name);
1304
1305 std::string id;
1306 std::string version;
1307 // Don't keep |extension| around longer than necessary.
1308 {
1309 const Extension* extension =
1310 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1311 // The extension should now be installed and enabled.
1312 ASSERT_TRUE(extension);
1313 id = extension->id();
1314 version = extension->VersionString();
1315 }
1316 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1317
1318 // Disable it if the test case says so.
1319 if (test_case.previous_disable_reasons) {
1320 service()->DisableExtension(id, test_case.previous_disable_reasons);
1321 ASSERT_TRUE(registry()->disabled_extensions().Contains(id));
1322 }
1323
1324 // Now a sync update comes in.
1325 sync_pb::EntitySpecifics specifics;
1326 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1327 ext_specifics->set_id(id);
1328 ext_specifics->set_enabled(test_case.sync_enable);
1329 ext_specifics->set_version(version);
1330 if (test_case.sync_disable_reasons != -1)
1331 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1332
treib65f103042015-12-03 10:21:361333 SyncChangeList list =
1334 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1335
treib9afc6212015-10-30 18:49:581336 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1337
1338 // Check expectations.
1339 const bool expect_enabled = !test_case.expect_disable_reasons;
1340 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1341 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
1342
1343 // Remove the extension again, so we can install it again for the next case.
1344 UninstallExtension(id, false, expect_enabled ? Extension::ENABLED
1345 : Extension::DISABLED);
1346 }
1347}
1348
1349TEST_F(ExtensionServiceSyncTest, ProcessSyncDataDeferredEnable) {
1350 InitializeEmptyExtensionService();
1351 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361352 syncer::EXTENSIONS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:221353 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
1354 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:581355
1356 base::FilePath base_path = data_dir().AppendASCII("permissions_increase");
1357 base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1358
1359 base::FilePath path = base_path.AppendASCII("v1");
1360 const Extension* extension = PackAndInstallCRX(path, pem_path, INSTALL_NEW);
1361 // The extension must now be installed and enabled.
1362 ASSERT_TRUE(extension);
1363 ASSERT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
1364
1365 // Save the id, as the extension object will be destroyed during updating.
1366 std::string id = extension->id();
1367
1368 // Update to a new version with increased permissions.
1369 path = base_path.AppendASCII("v2");
1370 PackCRXAndUpdateExtension(id, path, pem_path, DISABLED);
1371
1372 // Now a sync update comes in, telling us to re-enable a *newer* version.
1373 sync_pb::EntitySpecifics specifics;
1374 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1375 ext_specifics->set_id(id);
1376 ext_specifics->set_version("3");
1377 ext_specifics->set_enabled(true);
1378 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
1379
treib65f103042015-12-03 10:21:361380 SyncChangeList list =
1381 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1382
treib9afc6212015-10-30 18:49:581383 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1384
1385 // Since the version didn't match, the extension should still be disabled.
1386 EXPECT_TRUE(registry()->disabled_extensions().Contains(id));
1387
1388 // After we update to the matching version, the extension should get enabled.
1389 path = base_path.AppendASCII("v3");
1390 PackCRXAndUpdateExtension(id, path, pem_path, ENABLED);
1391}
1392
1393TEST_F(ExtensionServiceSyncTest, ProcessSyncDataPermissionApproval) {
1394 // This is the update URL specified in the test extension. Setting it here is
1395 // necessary to make it considered syncable.
1396 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1397 switches::kAppsGalleryUpdateURL,
1398 "http://localhost/autoupdate/updates.xml");
1399
1400 InitializeEmptyExtensionService();
1401 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:361402 syncer::EXTENSIONS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:221403 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
1404 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:581405
1406 const base::FilePath base_path =
1407 data_dir().AppendASCII("permissions_increase");
1408 const base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
1409 const base::FilePath path_v1 = base_path.AppendASCII("v1");
1410 const base::FilePath path_v2 = base_path.AppendASCII("v2");
1411
1412 base::ScopedTempDir crx_dir;
1413 ASSERT_TRUE(crx_dir.CreateUniqueTempDir());
1414 const base::FilePath crx_path_v1 = crx_dir.path().AppendASCII("temp1.crx");
1415 PackCRX(path_v1, pem_path, crx_path_v1);
1416 const base::FilePath crx_path_v2 = crx_dir.path().AppendASCII("temp2.crx");
1417 PackCRX(path_v2, pem_path, crx_path_v2);
1418
1419 const std::string v1("1");
1420 const std::string v2("2");
1421
1422 const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
1423
1424 struct TestCase {
1425 const char* name; // For failure output only.
1426 const std::string& sync_version; // The version coming in from Sync.
1427 // The disable reason(s) coming in from Sync, or -1 for "not set".
1428 int sync_disable_reasons;
1429 // The expected set of disable reasons after processing the Sync update. The
1430 // extension should be enabled iff this is 0.
1431 int expect_disable_reasons;
1432 // Whether the extension's permissions should be auto-granted.
1433 bool expect_permissions_granted;
1434 } test_cases[] = {
1435 // Sync tells us to re-enable an older version. No permissions should be
1436 // granted, since we can't be sure if the user actually approved the right
1437 // set of permissions.
1438 { "OldVersion", v1, 0, Extension::DISABLE_PERMISSIONS_INCREASE, false },
1439 // Legacy case: Sync tells us to re-enable the extension, but doesn't
1440 // specify disable reasons. No permissions should be granted.
1441 { "Legacy", v2, -1, Extension::DISABLE_PERMISSIONS_INCREASE, false },
1442 // Sync tells us to re-enable the extension and explicitly removes the
1443 // disable reasons. Now the extension should have its permissions granted.
1444 { "GrantPermissions", v2, 0, Extension::DISABLE_NONE, true },
1445 };
1446
1447 for (const TestCase& test_case : test_cases) {
1448 SCOPED_TRACE(test_case.name);
1449
1450 std::string id;
1451 // Don't keep |extension| around longer than necessary (it'll be destroyed
1452 // during updating).
1453 {
1454 const Extension* extension = InstallCRX(crx_path_v1, INSTALL_NEW);
1455 // The extension should now be installed and enabled.
1456 ASSERT_TRUE(extension);
1457 ASSERT_EQ(v1, extension->VersionString());
1458 id = extension->id();
1459 }
1460 ASSERT_TRUE(registry()->enabled_extensions().Contains(id));
1461
dchengc963c7142016-04-08 03:55:221462 std::unique_ptr<const PermissionSet> granted_permissions_v1 =
treib9afc6212015-10-30 18:49:581463 prefs->GetGrantedPermissions(id);
1464
1465 // Update to a new version with increased permissions.
1466 UpdateExtension(id, crx_path_v2, DISABLED);
1467
1468 // Now the extension should be disabled due to a permissions increase.
1469 {
1470 const Extension* extension =
1471 registry()->disabled_extensions().GetByID(id);
1472 ASSERT_TRUE(extension);
1473 ASSERT_EQ(v2, extension->VersionString());
1474 }
1475 ASSERT_TRUE(prefs->HasDisableReason(
1476 id, Extension::DISABLE_PERMISSIONS_INCREASE));
1477
1478 // No new permissions should have been granted.
dchengc963c7142016-04-08 03:55:221479 std::unique_ptr<const PermissionSet> granted_permissions_v2 =
treib9afc6212015-10-30 18:49:581480 prefs->GetGrantedPermissions(id);
1481 ASSERT_EQ(*granted_permissions_v1, *granted_permissions_v2);
1482
1483 // Now a sync update comes in.
1484 sync_pb::EntitySpecifics specifics;
1485 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1486 ext_specifics->set_id(id);
1487 ext_specifics->set_enabled(true);
1488 ext_specifics->set_version(test_case.sync_version);
1489 if (test_case.sync_disable_reasons != -1)
1490 ext_specifics->set_disable_reasons(test_case.sync_disable_reasons);
1491
treib65f103042015-12-03 10:21:361492 SyncChangeList list =
1493 MakeSyncChangeList(good_crx, specifics, SyncChange::ACTION_UPDATE);
1494
treib9afc6212015-10-30 18:49:581495 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1496
1497 // Check expectations.
1498 const bool expect_enabled = !test_case.expect_disable_reasons;
1499 EXPECT_EQ(expect_enabled, service()->IsExtensionEnabled(id));
1500 EXPECT_EQ(test_case.expect_disable_reasons, prefs->GetDisableReasons(id));
dchengc963c7142016-04-08 03:55:221501 std::unique_ptr<const PermissionSet> granted_permissions =
treib9afc6212015-10-30 18:49:581502 prefs->GetGrantedPermissions(id);
1503 if (test_case.expect_permissions_granted) {
dchengc963c7142016-04-08 03:55:221504 std::unique_ptr<const PermissionSet> active_permissions =
treib9afc6212015-10-30 18:49:581505 prefs->GetActivePermissions(id);
1506 EXPECT_EQ(*granted_permissions, *active_permissions);
1507 } else {
1508 EXPECT_EQ(*granted_permissions, *granted_permissions_v1);
1509 }
1510
1511 // Remove the extension again, so we can install it again for the next case.
1512 UninstallExtension(id, false, expect_enabled ? Extension::ENABLED
1513 : Extension::DISABLED);
1514 }
1515}
1516
treib227b2582015-12-09 09:28:261517// Regression test for crbug.com/558299
1518TEST_F(ExtensionServiceSyncTest, DontSyncThemes) {
1519 InitializeEmptyExtensionService();
1520
1521 // The user has enabled sync.
maxboguefe00952a2016-01-19 19:02:011522 ProfileSyncServiceFactory::GetForProfile(profile())->SetFirstSetupComplete();
treib227b2582015-12-09 09:28:261523 // Make sure ExtensionSyncService is created, so it'll be notified of changes.
1524 extension_sync_service();
1525
1526 service()->Init();
1527 ASSERT_TRUE(service()->is_ready());
1528
1529 syncer::FakeSyncChangeProcessor* processor =
1530 new syncer::FakeSyncChangeProcessor;
1531 extension_sync_service()->MergeDataAndStartSyncing(
dchengc963c7142016-04-08 03:55:221532 syncer::EXTENSIONS, syncer::SyncDataList(), base::WrapUnique(processor),
1533 base::WrapUnique(new syncer::SyncErrorFactoryMock));
treib227b2582015-12-09 09:28:261534
1535 processor->changes().clear();
1536
1537 // Sanity check: Installing an extension should result in a sync change.
1538 InstallCRX(data_dir().AppendASCII("good.crx"), INSTALL_NEW);
1539 EXPECT_EQ(1u, processor->changes().size());
1540
1541 processor->changes().clear();
1542
1543 // Installing a theme should not result in a sync change (themes are handled
1544 // separately by ThemeSyncableService).
1545 InstallCRX(data_dir().AppendASCII("theme.crx"), INSTALL_NEW);
1546 EXPECT_TRUE(processor->changes().empty());
1547}
1548
treib9afc6212015-10-30 18:49:581549#if defined(ENABLE_SUPERVISED_USERS)
1550
1551class ExtensionServiceTestSupervised : public ExtensionServiceSyncTest,
1552 public SupervisedUserService::Delegate {
1553 public:
treibb6af28cd2015-12-01 11:19:461554 ExtensionServiceTestSupervised()
1555 : field_trial_list_(new base::MockEntropyProvider()) {}
1556
treib9afc6212015-10-30 18:49:581557 void SetUp() override {
1558 ExtensionServiceSyncTest::SetUp();
1559
1560 // This is the update URL specified in the permissions test extension.
1561 // Setting it here is necessary to make the extension considered syncable.
1562 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1563 switches::kAppsGalleryUpdateURL,
1564 "http://localhost/autoupdate/updates.xml");
1565 }
1566
1567 void TearDown() override {
1568 supervised_user_service()->SetDelegate(nullptr);
1569
1570 ExtensionServiceSyncTest::TearDown();
1571 }
1572
1573 protected:
treibb6af28cd2015-12-01 11:19:461574 void InitNeedCustodianApprovalFieldTrial(bool enabled) {
1575 // Group name doesn't matter.
1576 base::FieldTrialList::CreateFieldTrial(
1577 "SupervisedUserExtensionPermissionIncrease", "group");
1578 std::map<std::string, std::string> params;
1579 params["legacy_supervised_user"] = enabled ? "true" : "false";
1580 params["child_account"] = enabled ? "true" : "false";
1581 variations::AssociateVariationParams(
1582 "SupervisedUserExtensionPermissionIncrease", "group", params);
1583 }
1584
mamire9609642016-06-28 22:17:541585 void InitSupervisedUserInitiatedExtensionInstallFeature(bool enabled) {
1586 base::FeatureList::ClearInstanceForTesting();
1587 std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
1588 if (enabled) {
1589 feature_list->InitializeFromCommandLine(
1590 "SupervisedUserInitiatedExtensionInstall", std::string());
1591 }
1592 base::FeatureList::SetInstance(std::move(feature_list));
1593 }
1594
treib9afc6212015-10-30 18:49:581595 void InitServices(bool profile_is_supervised) {
1596 ExtensionServiceInitParams params = CreateDefaultInitParams();
1597 params.profile_is_supervised = profile_is_supervised;
mamire9609642016-06-28 22:17:541598 // If profile is supervised, don't pass a pref file such that the testing
1599 // profile creates a pref service that uses SupervisedUserPrefStore.
1600 if (profile_is_supervised) {
1601 params.pref_file = base::FilePath();
1602 }
treib9afc6212015-10-30 18:49:581603 InitializeExtensionService(params);
asargente48ab752016-03-12 00:59:201604 StartSyncing(syncer::EXTENSIONS);
treib9afc6212015-10-30 18:49:581605
1606 supervised_user_service()->SetDelegate(this);
1607 supervised_user_service()->Init();
1608 }
1609
mamire9609642016-06-28 22:17:541610 std::string InstallPermissionsTestExtension(bool by_custodian) {
1611 return InstallTestExtension(permissions_increase, dir_path("1"), pem_path(),
1612 by_custodian);
treib9afc6212015-10-30 18:49:581613 }
1614
1615 void UpdatePermissionsTestExtension(const std::string& id,
1616 const std::string& version,
1617 UpdateState expected_state) {
mamire9609642016-06-28 22:17:541618 UpdateTestExtension(dir_path(version), pem_path(), id, version,
1619 expected_state);
1620 }
1621
1622 std::string InstallNoPermissionsTestExtension(bool by_custodian) {
1623 base::FilePath base_path = data_dir().AppendASCII("autoupdate");
1624 base::FilePath pem_path = base_path.AppendASCII("key.pem");
1625 base::FilePath dir_path = base_path.AppendASCII("v1");
1626
1627 return InstallTestExtension(autoupdate, dir_path, pem_path, by_custodian);
1628 }
1629
1630 void UpdateNoPermissionsTestExtension(const std::string& id,
1631 const std::string& version,
1632 UpdateState expected_state) {
1633 base::FilePath base_path = data_dir().AppendASCII("autoupdate");
1634 base::FilePath pem_path = base_path.AppendASCII("key.pem");
1635 base::FilePath dir_path = base_path.AppendASCII("v" + version);
1636
1637 UpdateTestExtension(dir_path, pem_path, id, version, expected_state);
1638 }
1639
1640 std::string InstallTestExtension(const std::string& id,
1641 const base::FilePath& dir_path,
1642 const base::FilePath& pem_path,
1643 bool by_custodian) {
1644 InstallState expected_state = INSTALL_WITHOUT_LOAD;
1645 if (by_custodian) {
1646 extensions::util::SetWasInstalledByCustodian(id, profile(), true);
1647 expected_state = INSTALL_NEW;
1648 }
1649 const Extension* extension =
1650 PackAndInstallCRX(dir_path, pem_path, expected_state);
1651 // The extension must now be installed.
1652 EXPECT_TRUE(extension);
1653 EXPECT_EQ(extension->id(), id);
1654 if (by_custodian) {
1655 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1656 } else {
1657 CheckDisabledForCustodianApproval(id);
1658 }
1659
1660 EXPECT_EQ(*extension->version(), base::Version("1"));
1661
1662 return id;
1663 }
1664
1665 void UpdateTestExtension(const base::FilePath& dir_path,
1666 const base::FilePath& pem_path,
1667 const std::string& id,
1668 const std::string& version,
1669 const UpdateState& expected_state) {
1670 PackCRXAndUpdateExtension(id, dir_path, pem_path, expected_state);
treib9afc6212015-10-30 18:49:581671 const Extension* extension = registry()->GetInstalledExtension(id);
1672 ASSERT_TRUE(extension);
1673 // The version should have been updated.
mamire9609642016-06-28 22:17:541674 EXPECT_EQ(*extension->version(), base::Version(version));
1675 }
1676
1677 // Simulate a custodian approval for enabling the extension coming in
1678 // through Sync by adding the approved version to the map of approved
1679 // extensions. It doesn't simulate a change in the disable reasons.
1680 void SimulateCustodianApprovalChangeViaSync(const std::string& extension_id,
1681 const std::string& version,
1682 SyncChange::SyncChangeType type) {
1683 std::string key = SupervisedUserSettingsService::MakeSplitSettingKey(
1684 supervised_users::kApprovedExtensions, extension_id);
1685 syncer::SyncData sync_data =
1686 SupervisedUserSettingsService::CreateSyncDataForSetting(
1687 key, base::StringValue(version));
1688
1689 SyncChangeList list(1, SyncChange(FROM_HERE, type, sync_data));
1690
1691 SupervisedUserSettingsService* supervised_user_settings_service =
1692 SupervisedUserSettingsServiceFactory::GetForProfile(profile());
1693 supervised_user_settings_service->ProcessSyncChanges(FROM_HERE, list);
1694 }
1695
1696 void CheckDisabledForCustodianApproval(const std::string& extension_id) {
1697 EXPECT_TRUE(registry()->disabled_extensions().Contains(extension_id));
1698 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile());
1699 EXPECT_TRUE(extension_prefs->HasDisableReason(
1700 extension_id,
1701 extensions::Extension::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
treib9afc6212015-10-30 18:49:581702 }
1703
1704 SupervisedUserService* supervised_user_service() {
1705 return SupervisedUserServiceFactory::GetForProfile(profile());
1706 }
1707
mamire9609642016-06-28 22:17:541708 static std::string RequestId(const std::string& extension_id,
1709 const std::string& version) {
1710 return SupervisedUserService::GetExtensionRequestId(
treib9afc6212015-10-30 18:49:581711 extension_id, base::Version(version));
1712 }
1713
1714 private:
1715 // This prevents the legacy supervised user init code from running.
1716 bool SetActive(bool active) override { return true; }
1717
1718 base::FilePath base_path() const {
1719 return data_dir().AppendASCII("permissions_increase");
1720 }
1721 base::FilePath dir_path(const std::string& version) const {
1722 return base_path().AppendASCII("v" + version);
1723 }
1724 base::FilePath pem_path() const {
1725 return base_path().AppendASCII("permissions.pem");
1726 }
treibb6af28cd2015-12-01 11:19:461727
1728 base::FieldTrialList field_trial_list_;
treib9afc6212015-10-30 18:49:581729};
1730
1731class MockPermissionRequestCreator : public PermissionRequestCreator {
1732 public:
1733 MockPermissionRequestCreator() {}
1734 ~MockPermissionRequestCreator() override {}
1735
1736 bool IsEnabled() const override { return true; }
1737
1738 void CreateURLAccessRequest(const GURL& url_requested,
1739 const SuccessCallback& callback) override {
1740 FAIL();
1741 }
1742
mamire9609642016-06-28 22:17:541743 MOCK_METHOD2(CreateExtensionInstallRequest,
1744 void(const std::string& id,
1745 const SupervisedUserService::SuccessCallback& callback));
1746
treib9afc6212015-10-30 18:49:581747 MOCK_METHOD2(CreateExtensionUpdateRequest,
1748 void(const std::string& id,
1749 const SupervisedUserService::SuccessCallback& callback));
1750
1751 private:
1752 DISALLOW_COPY_AND_ASSIGN(MockPermissionRequestCreator);
1753};
1754
1755TEST_F(ExtensionServiceTestSupervised, InstallOnlyAllowedByCustodian) {
1756 InitServices(true /* profile_is_supervised */);
mamire9609642016-06-28 22:17:541757 InitSupervisedUserInitiatedExtensionInstallFeature(false);
treib9afc6212015-10-30 18:49:581758
mamir192d7882016-06-22 17:10:161759 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
1760
treib9afc6212015-10-30 18:49:581761 base::FilePath path1 = data_dir().AppendASCII("good.crx");
1762 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
1763 const Extension* extensions[] = {
1764 InstallCRX(path1, INSTALL_FAILED),
mamir192d7882016-06-22 17:10:161765 InstallCRX(path2, INSTALL_NEW)
treib9afc6212015-10-30 18:49:581766 };
1767
1768 // Only the extension with the "installed by custodian" flag should have been
1769 // installed and enabled.
1770 EXPECT_FALSE(extensions[0]);
1771 ASSERT_TRUE(extensions[1]);
1772 EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id()));
1773}
1774
mamir192d7882016-06-22 17:10:161775TEST_F(ExtensionServiceTestSupervised,
1776 DelegatedAndPreinstalledExtensionIsSUFirst) {
1777 InitServices(false /* profile_is_supervised */);
mamire9609642016-06-28 22:17:541778 InitSupervisedUserInitiatedExtensionInstallFeature(false);
mamir192d7882016-06-22 17:10:161779
1780 // Install an extension.
1781 base::FilePath path = data_dir().AppendASCII("good.crx");
1782 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1783 std::string id = extension->id();
1784 const std::string version("1.0.0.0");
1785 // It should be enabled.
1786 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1787
1788 // Now make the profile supervised.
1789 profile()->AsTestingProfile()->SetSupervisedUserId(
1790 supervised_users::kChildAccountSUID);
1791
1792 // It should not be enabled now (it is not loaded at all actually).
1793 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
1794
1795 // Simulate data sync with the "was_installed_by_custodian" flag set to 1.
1796 sync_pb::EntitySpecifics specifics;
1797 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1798 ext_specifics->set_id(id);
1799 ext_specifics->set_enabled(true);
1800 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
1801 ext_specifics->set_installed_by_custodian(true);
1802 ext_specifics->set_version(version);
1803
1804 SyncChangeList list =
1805 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
1806
1807 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
1808
1809 // The extension should be enabled again.
1810 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1811 EXPECT_TRUE(extensions::util::WasInstalledByCustodian(id, profile()));
1812}
1813
1814TEST_F(ExtensionServiceTestSupervised,
1815 DelegatedAndPreinstalledExtensionSyncFirst) {
1816 InitServices(false /* profile_is_supervised */);
mamire9609642016-06-28 22:17:541817 InitSupervisedUserInitiatedExtensionInstallFeature(false);
mamir192d7882016-06-22 17:10:161818
1819 // Install an extension.
1820 base::FilePath path = data_dir().AppendASCII("good.crx");
1821 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1822 std::string id = extension->id();
1823 const std::string version("1.0.0.0");
1824
1825 // It should be enabled.
1826 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1827
1828 // Simulate data sync with the "was_installed_by_custodian" flag set to 1.
1829 sync_pb::EntitySpecifics specifics;
1830 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
1831 ext_specifics->set_id(id);
1832 ext_specifics->set_enabled(true);
1833 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
1834 ext_specifics->set_installed_by_custodian(true);
1835 ext_specifics->set_version(version);
1836
1837 SyncChangeList list =
1838 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
1839
1840 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
mamir192d7882016-06-22 17:10:161841 // The extension should be enabled.
1842 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1843 EXPECT_TRUE(extensions::util::WasInstalledByCustodian(id, profile()));
1844}
1845
mamire9609642016-06-28 22:17:541846TEST_F(ExtensionServiceTestSupervised,
1847 InstallAllowedByCustodianAndSupervisedUser) {
1848 InitServices(true /* profile_is_supervised */);
1849 InitSupervisedUserInitiatedExtensionInstallFeature(true);
1850
1851 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
1852
1853 base::FilePath path1 = data_dir().AppendASCII("good.crx");
1854 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
1855 const Extension* extensions[] = {
1856 InstallCRX(path1, INSTALL_WITHOUT_LOAD),
1857 InstallCRX(path2, INSTALL_NEW)
1858 };
1859
1860 // Only the extension with the "installed by custodian" flag should have been
1861 // installed and enabled.
1862 // The extension missing the "installed by custodian" flag is a
1863 // supervised user initiated install and hence not enabled.
1864 ASSERT_TRUE(extensions[0]);
1865 ASSERT_TRUE(extensions[1]);
1866 EXPECT_TRUE(registry()->disabled_extensions().Contains(extensions[0]->id()));
1867 EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id()));
1868}
1869
1870TEST_F(ExtensionServiceTestSupervised,
1871 PreinstalledExtensionWithSUInitiatedInstalls) {
1872 InitServices(false /* profile_is_supervised */);
1873 InitSupervisedUserInitiatedExtensionInstallFeature(true);
1874
1875 // Install an extension.
1876 base::FilePath path = data_dir().AppendASCII("good.crx");
1877 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1878 std::string id = extension->id();
1879 // Make sure it's enabled.
1880 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1881
1882 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1883 supervised_user_service()->AddPermissionRequestCreator(
1884 base::WrapUnique(creator));
1885 const std::string version("1.0.0.0");
1886
1887 EXPECT_CALL(*creator, CreateExtensionInstallRequest(
1888 RequestId(good_crx, version), testing::_));
1889
1890 // Now make the profile supervised.
1891 profile()->AsTestingProfile()->SetSupervisedUserId(
1892 supervised_users::kChildAccountSUID);
1893
1894 Mock::VerifyAndClearExpectations(creator);
1895
1896 // The extension should not be enabled anymore.
1897 CheckDisabledForCustodianApproval(id);
1898}
1899
1900TEST_F(ExtensionServiceTestSupervised,
1901 PreinstalledExtensionWithoutSUInitiatedInstalls) {
1902 InitServices(false /* profile_is_supervised */);
1903 InitSupervisedUserInitiatedExtensionInstallFeature(false);
1904
1905 // Install an extension.
1906 base::FilePath path = data_dir().AppendASCII("good.crx");
1907 const Extension* extension = InstallCRX(path, INSTALL_NEW);
1908 std::string id = extension->id();
1909
1910 // Make sure it's enabled.
1911 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1912
1913 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1914 supervised_user_service()->AddPermissionRequestCreator(
1915 base::WrapUnique(creator));
1916 const std::string version("1.0.0.0");
1917
1918 // No request should be sent because supervised user initiated installs
1919 // are disabled.
1920 EXPECT_CALL(*creator, CreateExtensionInstallRequest(testing::_, testing::_))
1921 .Times(0);
1922
1923 // Now make the profile supervised.
1924 profile()->AsTestingProfile()->SetSupervisedUserId(
1925 supervised_users::kChildAccountSUID);
1926
1927 // The extension should not be loaded anymore.
1928 EXPECT_FALSE(registry()->GetInstalledExtension(id));
1929}
1930
1931TEST_F(ExtensionServiceTestSupervised, ExtensionApprovalBeforeInstallation) {
1932 // This tests the case when the sync entity flagging the extension as approved
1933 // arrives before the extension itself is installed.
1934 InitServices(true /* profile_is_supervised */);
1935 InitSupervisedUserInitiatedExtensionInstallFeature(true);
1936
1937 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1938 supervised_user_service()->AddPermissionRequestCreator(
1939 base::WrapUnique(creator));
1940
1941 std::string id = good_crx;
1942 std::string version("1.0.0.0");
1943
1944 SimulateCustodianApprovalChangeViaSync(id, version, SyncChange::ACTION_ADD);
1945
1946 // Now install an extension.
1947 base::FilePath path = data_dir().AppendASCII("good.crx");
1948 InstallCRX(path, INSTALL_NEW);
1949
1950 // No approval request should be sent.
1951 EXPECT_CALL(*creator, CreateExtensionInstallRequest(testing::_, testing::_))
1952 .Times(0);
1953
1954 // Make sure it's enabled.
1955 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
1956}
1957
treib9afc6212015-10-30 18:49:581958TEST_F(ExtensionServiceTestSupervised, UpdateWithoutPermissionIncrease) {
1959 InitServices(true /* profile_is_supervised */);
1960
treib9afc6212015-10-30 18:49:581961 // Save the id, as the extension object will be destroyed during updating.
mamire9609642016-06-28 22:17:541962 std::string id = InstallNoPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:581963
1964 // Update to a new version.
mamire9609642016-06-28 22:17:541965 std::string version2("2");
1966 UpdateNoPermissionsTestExtension(id, version2, ENABLED);
treib9afc6212015-10-30 18:49:581967
1968 // The extension should still be there and enabled.
mamire9609642016-06-28 22:17:541969 const Extension* extension = registry()->enabled_extensions().GetByID(id);
treib9afc6212015-10-30 18:49:581970 ASSERT_TRUE(extension);
1971 // The version should have changed.
mamire9609642016-06-28 22:17:541972 EXPECT_EQ(*extension->version(), base::Version(version2));
treib9afc6212015-10-30 18:49:581973}
1974
1975TEST_F(ExtensionServiceTestSupervised, UpdateWithPermissionIncreaseNoApproval) {
treibb6af28cd2015-12-01 11:19:461976 InitNeedCustodianApprovalFieldTrial(false);
treib9afc6212015-10-30 18:49:581977
1978 InitServices(true /* profile_is_supervised */);
1979
1980 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
1981 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:221982 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:581983
mamire9609642016-06-28 22:17:541984 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:581985
1986 // Update to a new version with increased permissions.
1987 // Since we don't require the custodian's approval, no permission request
1988 // should be created.
1989 const std::string version2("2");
1990 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:541991 RequestId(id, version2), testing::_))
treib9afc6212015-10-30 18:49:581992 .Times(0);
1993 UpdatePermissionsTestExtension(id, version2, DISABLED);
1994}
1995
1996TEST_F(ExtensionServiceTestSupervised,
1997 UpdateWithPermissionIncreaseApprovalOldVersion) {
treibb6af28cd2015-12-01 11:19:461998 InitNeedCustodianApprovalFieldTrial(true);
treib9afc6212015-10-30 18:49:581999
2000 InitServices(true /* profile_is_supervised */);
2001
2002 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2003 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222004 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582005
2006 const std::string version1("1");
2007 const std::string version2("2");
2008
mamire9609642016-06-28 22:17:542009 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582010
2011 // Update to a new version with increased permissions.
2012 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542013 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582014 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542015 Mock::VerifyAndClearExpectations(creator);
treib9afc6212015-10-30 18:49:582016
2017 // Simulate a custodian approval for re-enabling the extension coming in
2018 // through Sync, but set the old version. This can happen when there already
2019 // was a pending request for an earlier version of the extension.
2020 sync_pb::EntitySpecifics specifics;
2021 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2022 ext_specifics->set_id(id);
2023 ext_specifics->set_enabled(true);
2024 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
2025 ext_specifics->set_installed_by_custodian(true);
2026 ext_specifics->set_version(version1);
2027
2028 // Attempting to re-enable an old version should result in a permission
2029 // request for the current version.
2030 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542031 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582032
treib65f103042015-12-03 10:21:362033 SyncChangeList list =
2034 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2035
2036 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582037 // The re-enable should be ignored, since the version doesn't match.
2038 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2039 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
2040 id, base::Version(version1)));
2041 EXPECT_FALSE(extension_sync_service()->HasPendingReenable(
2042 id, base::Version(version2)));
mamire9609642016-06-28 22:17:542043 Mock::VerifyAndClearExpectations(creator);
treib9afc6212015-10-30 18:49:582044}
2045
2046TEST_F(ExtensionServiceTestSupervised,
2047 UpdateWithPermissionIncreaseApprovalMatchingVersion) {
treibb6af28cd2015-12-01 11:19:462048 InitNeedCustodianApprovalFieldTrial(true);
treib9afc6212015-10-30 18:49:582049
2050 InitServices(true /* profile_is_supervised */);
2051
2052 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2053 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222054 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582055
mamire9609642016-06-28 22:17:542056 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582057
2058 // Update to a new version with increased permissions.
2059 const std::string version2("2");
2060 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542061 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582062 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542063 Mock::VerifyAndClearExpectations(creator);
treib9afc6212015-10-30 18:49:582064
2065 // Simulate a custodian approval for re-enabling the extension coming in
2066 // through Sync.
2067 sync_pb::EntitySpecifics specifics;
2068 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2069 ext_specifics->set_id(id);
2070 ext_specifics->set_enabled(true);
2071 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
2072 ext_specifics->set_installed_by_custodian(true);
2073 ext_specifics->set_version(version2);
2074
treib65f103042015-12-03 10:21:362075 SyncChangeList list =
2076 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2077
2078 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582079 // The extension should have gotten re-enabled.
2080 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2081}
2082
2083TEST_F(ExtensionServiceTestSupervised,
2084 UpdateWithPermissionIncreaseApprovalNewVersion) {
treibb6af28cd2015-12-01 11:19:462085 InitNeedCustodianApprovalFieldTrial(true);
treib9afc6212015-10-30 18:49:582086
2087 InitServices(true /* profile_is_supervised */);
2088
2089 MockPermissionRequestCreator* creator = new MockPermissionRequestCreator;
2090 supervised_user_service()->AddPermissionRequestCreator(
dchengc963c7142016-04-08 03:55:222091 base::WrapUnique(creator));
treib9afc6212015-10-30 18:49:582092
mamire9609642016-06-28 22:17:542093 std::string id = InstallPermissionsTestExtension(true /* by_custodian */);
treib9afc6212015-10-30 18:49:582094
2095 // Update to a new version with increased permissions.
2096 const std::string version2("2");
2097 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542098 RequestId(id, version2), testing::_));
treib9afc6212015-10-30 18:49:582099 UpdatePermissionsTestExtension(id, version2, DISABLED);
mamire9609642016-06-28 22:17:542100 Mock::VerifyAndClearExpectations(creator);
treib9afc6212015-10-30 18:49:582101
2102 // Simulate a custodian approval for re-enabling the extension coming in
2103 // through Sync. Set a newer version than we have installed.
2104 const std::string version3("3");
2105 sync_pb::EntitySpecifics specifics;
2106 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2107 ext_specifics->set_id(id);
2108 ext_specifics->set_enabled(true);
2109 ext_specifics->set_disable_reasons(Extension::DISABLE_NONE);
2110 ext_specifics->set_installed_by_custodian(true);
2111 ext_specifics->set_version(version3);
2112
2113 // This should *not* result in a new permission request.
2114 EXPECT_CALL(*creator, CreateExtensionUpdateRequest(
mamire9609642016-06-28 22:17:542115 RequestId(id, version3), testing::_))
treib9afc6212015-10-30 18:49:582116 .Times(0);
2117
treib65f103042015-12-03 10:21:362118 SyncChangeList list =
2119 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2120
2121 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582122 // The re-enable should be delayed until the extension is updated to the
2123 // matching version.
2124 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2125 EXPECT_TRUE(extension_sync_service()->HasPendingReenable(
2126 id, base::Version(version3)));
2127
2128 // Update to the matching version. Now the extension should get enabled.
2129 UpdatePermissionsTestExtension(id, version3, ENABLED);
2130}
2131
mamire9609642016-06-28 22:17:542132TEST_F(ExtensionServiceTestSupervised, SupervisedUserInitiatedInstalls) {
2133 InitNeedCustodianApprovalFieldTrial(true);
2134 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);
2154
2155 SimulateCustodianApprovalChangeViaSync(good_crx, version,
2156 SyncChange::ACTION_ADD);
2157
2158 // The extension should be enabled now.
2159 EXPECT_TRUE(registry()->enabled_extensions().Contains(good_crx));
2160
2161 // Simulate approval removal coming via Sync.
2162 SimulateCustodianApprovalChangeViaSync(good_crx, version,
2163 SyncChange::ACTION_DELETE);
2164
2165 // The extension should be disabled now.
2166 EXPECT_TRUE(registry()->disabled_extensions().Contains(good_crx));
2167}
2168
2169TEST_F(ExtensionServiceTestSupervised,
2170 UpdateSUInitiatedInstallWithoutPermissionIncrease) {
2171 InitNeedCustodianApprovalFieldTrial(true);
2172 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2173
2174 InitServices(true /* profile_is_supervised */);
2175
2176 std::string id = InstallNoPermissionsTestExtension(false /* by_custodian */);
2177 std::string version1("1");
2178
2179 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2180
2181 // The extension should be enabled now.
2182 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2183
2184 std::string version2("2");
2185
2186 // Update to a new version.
2187 UpdateNoPermissionsTestExtension(id, version2, ENABLED);
2188
2189 // The extension should still be there and enabled.
2190 const Extension* extension = registry()->enabled_extensions().GetByID(id);
2191 ASSERT_TRUE(extension);
2192 // The version should have increased.
2193 EXPECT_EQ(1, extension->version()->CompareTo(base::Version(version1)));
2194
2195 // Check that the approved version has been updated in the prefs as well.
2196 // Prefs are updated via Sync. If the prefs are updated, then the new
2197 // approved version has been pushed to Sync as well.
2198 std::string approved_version;
2199 PrefService* pref_service = profile()->GetPrefs();
2200 const base::DictionaryValue* approved_extensions =
2201 pref_service->GetDictionary(prefs::kSupervisedUserApprovedExtensions);
2202 approved_extensions->GetStringWithoutPathExpansion(id, &approved_version);
2203
2204 EXPECT_EQ(base::Version(approved_version), *extension->version());
2205}
2206
2207TEST_F(ExtensionServiceTestSupervised,
2208 UpdateSUInitiatedInstallWithPermissionIncrease) {
2209 InitNeedCustodianApprovalFieldTrial(true);
2210 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2211
2212 InitServices(true /* profile_is_supervised */);
2213
2214 std::string id = InstallPermissionsTestExtension(false /* by_custodian */);
2215 std::string version1("1");
2216
2217 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2218
2219 // The extension should be enabled now.
2220 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2221
2222 std::string version3("3");
2223
2224 UpdatePermissionsTestExtension(id, version3, DISABLED);
2225
2226 // The extension should be disabled.
2227 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2228 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
2229 id, Extension::DISABLE_PERMISSIONS_INCREASE));
2230
2231 std::string version2("2");
2232 // Approve an older version
2233 SimulateCustodianApprovalChangeViaSync(id, version2,
2234 SyncChange::ACTION_UPDATE);
2235
2236 // The extension should remain disabled.
2237 EXPECT_FALSE(registry()->enabled_extensions().Contains(id));
2238 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
2239 id, Extension::DISABLE_PERMISSIONS_INCREASE));
2240 EXPECT_TRUE(ExtensionPrefs::Get(profile())->HasDisableReason(
2241 id, Extension::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
2242
2243 // Approve the latest version
2244 SimulateCustodianApprovalChangeViaSync(id, version3,
2245 SyncChange::ACTION_UPDATE);
2246
2247 // The extension should be enabled again.
2248 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2249}
2250
2251TEST_F(ExtensionServiceTestSupervised,
2252 UpdateSUInitiatedInstallWithPermissionIncreaseApprovalArrivesFirst) {
2253 InitNeedCustodianApprovalFieldTrial(true);
2254 InitSupervisedUserInitiatedExtensionInstallFeature(true);
2255
2256 InitServices(true /* profile_is_supervised */);
2257
2258 std::string id = InstallPermissionsTestExtension(false /* by_custodian */);
2259
2260 std::string version1("1");
2261 SimulateCustodianApprovalChangeViaSync(id, version1, SyncChange::ACTION_ADD);
2262
2263 // The extension should be enabled now.
2264 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2265
2266 std::string version2("2");
2267 // Approve a newer version
2268 SimulateCustodianApprovalChangeViaSync(id, version2,
2269 SyncChange::ACTION_UPDATE);
2270
2271 // The extension should be disabled.
2272 CheckDisabledForCustodianApproval(id);
2273
2274 // Now update the extension to the same version that was approved.
2275 UpdatePermissionsTestExtension(id, version2, ENABLED);
2276 // The extension should be enabled again.
2277 EXPECT_TRUE(registry()->enabled_extensions().Contains(id));
2278}
2279
treib9afc6212015-10-30 18:49:582280TEST_F(ExtensionServiceSyncTest, SyncUninstallByCustodianSkipsPolicy) {
2281 InitializeEmptyExtensionService();
2282 extension_sync_service()->MergeDataAndStartSyncing(
treib65f103042015-12-03 10:21:362283 syncer::EXTENSIONS, syncer::SyncDataList(),
dchengc963c7142016-04-08 03:55:222284 base::WrapUnique(new syncer::FakeSyncChangeProcessor()),
2285 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
treib9afc6212015-10-30 18:49:582286
mamir192d7882016-06-22 17:10:162287 extensions::util::SetWasInstalledByCustodian(good2048, profile(), true);
treib9afc6212015-10-30 18:49:582288 // Install two extensions.
2289 base::FilePath path1 = data_dir().AppendASCII("good.crx");
2290 base::FilePath path2 = data_dir().AppendASCII("good2048.crx");
2291 const Extension* extensions[] = {
2292 InstallCRX(path1, INSTALL_NEW),
mamir192d7882016-06-22 17:10:162293 InstallCRX(path2, INSTALL_NEW)
treib9afc6212015-10-30 18:49:582294 };
2295
2296 // Add a policy provider that will disallow any changes.
2297 extensions::TestManagementPolicyProvider provider(
2298 extensions::TestManagementPolicyProvider::PROHIBIT_MODIFY_STATUS);
2299 ExtensionSystem::Get(
2300 browser_context())->management_policy()->RegisterProvider(&provider);
2301
2302 // Create a sync deletion for each extension.
treib65f103042015-12-03 10:21:362303 SyncChangeList list;
treib9afc6212015-10-30 18:49:582304 for (size_t i = 0; i < arraysize(extensions); i++) {
2305 const std::string& id = extensions[i]->id();
2306 sync_pb::EntitySpecifics specifics;
2307 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2308 ext_specifics->set_id(id);
2309 ext_specifics->set_version("1.0");
2310 ext_specifics->set_installed_by_custodian(
mamir192d7882016-06-22 17:10:162311 extensions::util::WasInstalledByCustodian(id, profile()));
2312
treib9afc6212015-10-30 18:49:582313 syncer::SyncData sync_data =
2314 syncer::SyncData::CreateLocalData(id, "Name", specifics);
treib65f103042015-12-03 10:21:362315 list.push_back(SyncChange(FROM_HERE, SyncChange::ACTION_DELETE, sync_data));
treib9afc6212015-10-30 18:49:582316 }
2317
2318 // Save the extension ids, as uninstalling destroys the Extension instance.
2319 std::string extension_ids[] = {
2320 extensions[0]->id(),
2321 extensions[1]->id()
2322 };
2323
2324 // Now apply the uninstallations.
treib65f103042015-12-03 10:21:362325 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
treib9afc6212015-10-30 18:49:582326
2327 // Uninstalling the extension without installed_by_custodian should have been
2328 // blocked by policy, so it should still be there.
2329 EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_ids[0]));
2330
2331 // But installed_by_custodian should result in bypassing the policy check.
2332 EXPECT_FALSE(
2333 registry()->GenerateInstalledExtensionsSet()->Contains(extension_ids[1]));
2334}
2335
rdevlin.cronin738501d2015-11-05 21:51:362336TEST_F(ExtensionServiceSyncTest, SyncExtensionHasAllhostsWithheld) {
2337 InitializeEmptyExtensionService();
asargente48ab752016-03-12 00:59:202338 StartSyncing(syncer::EXTENSIONS);
rdevlin.cronin738501d2015-11-05 21:51:362339
2340 // Create an extension that needs all-hosts.
2341 const std::string kName("extension");
2342 scoped_refptr<const Extension> extension =
2343 extensions::ExtensionBuilder()
limasdf3d102542015-12-09 03:58:452344 .SetLocation(Manifest::INTERNAL)
dcheng794d2bd2016-02-27 03:51:322345 .SetManifest(
limasdf3d102542015-12-09 03:58:452346 extensions::DictionaryBuilder()
2347 .Set("name", kName)
2348 .Set("description", "foo")
2349 .Set("manifest_version", 2)
2350 .Set("version", "1.0")
2351 .Set("permissions",
dcheng794d2bd2016-02-27 03:51:322352 extensions::ListBuilder().Append("*://*/*").Build())
2353 .Build())
limasdf3d102542015-12-09 03:58:452354 .SetID(crx_file::id_util::GenerateId(kName))
2355 .Build();
rdevlin.cronin738501d2015-11-05 21:51:362356
2357 // Install and enable it.
2358 service()->AddExtension(extension.get());
2359 service()->GrantPermissionsAndEnableExtension(extension.get());
2360 const std::string id = extension->id();
2361 EXPECT_TRUE(registry()->enabled_extensions().GetByID(id));
2362
2363 // Simulate a sync node coming in where the extension had all-hosts withheld.
2364 // This means that it should have all-hosts withheld on this machine, too.
rdevlin.cronin738501d2015-11-05 21:51:362365 sync_pb::EntitySpecifics specifics;
2366 sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension();
2367 ext_specifics->set_id(id);
2368 ext_specifics->set_name(kName);
2369 ext_specifics->set_version("1.0");
2370 ext_specifics->set_all_urls_enabled(false);
2371 ext_specifics->set_enabled(true);
rdevlin.cronin738501d2015-11-05 21:51:362372
treib65f103042015-12-03 10:21:362373 SyncChangeList list =
2374 MakeSyncChangeList(id, specifics, SyncChange::ACTION_UPDATE);
2375
2376 extension_sync_service()->ProcessSyncChanges(FROM_HERE, list);
rdevlin.cronin738501d2015-11-05 21:51:362377
2378 EXPECT_TRUE(registry()->enabled_extensions().GetByID(id));
2379 EXPECT_FALSE(extensions::util::AllowedScriptingOnAllUrls(id, profile()));
2380 EXPECT_TRUE(extensions::util::HasSetAllowedScriptingOnAllUrls(id, profile()));
2381 EXPECT_FALSE(extensions::util::AllowedScriptingOnAllUrls(id, profile()));
2382}
2383
treib9afc6212015-10-30 18:49:582384#endif // defined(ENABLE_SUPERVISED_USERS)
asargente48ab752016-03-12 00:59:202385
2386// Tests sync behavior in the case of an item that starts out as an app and
2387// gets updated to become an extension.
2388TEST_F(ExtensionServiceSyncTest, AppToExtension) {
2389 InitializeEmptyExtensionService();
2390 service()->Init();
2391 ASSERT_TRUE(service()->is_ready());
2392
2393 // Install v1, which is an app.
2394 const Extension* v1 =
2395 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v1.crx"),
2396 INSTALL_NEW);
2397 EXPECT_TRUE(v1->is_app());
2398 EXPECT_FALSE(v1->is_extension());
2399 std::string id = v1->id();
2400
2401 StatefulChangeProcessor extensions_processor(syncer::ModelType::EXTENSIONS);
2402 StatefulChangeProcessor apps_processor(syncer::ModelType::APPS);
2403 extension_sync_service()->MergeDataAndStartSyncing(
2404 syncer::EXTENSIONS, syncer::SyncDataList(),
2405 extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222406 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202407 extension_sync_service()->MergeDataAndStartSyncing(
2408 syncer::APPS, syncer::SyncDataList(), apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222409 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202410
2411 // Check the app/extension change processors to be sure the right data was
2412 // added.
2413 EXPECT_TRUE(extensions_processor.changes().empty());
2414 EXPECT_TRUE(extensions_processor.data().empty());
2415 EXPECT_EQ(1u, apps_processor.data().size());
2416 ASSERT_EQ(1u, apps_processor.changes().size());
2417 const SyncChange& app_change = apps_processor.changes()[0];
2418 EXPECT_EQ(SyncChange::ACTION_ADD, app_change.change_type());
dchengc963c7142016-04-08 03:55:222419 std::unique_ptr<ExtensionSyncData> app_data =
asargente48ab752016-03-12 00:59:202420 ExtensionSyncData::CreateFromSyncData(app_change.sync_data());
2421 EXPECT_TRUE(app_data->is_app());
2422 EXPECT_EQ(id, app_data->id());
2423 EXPECT_EQ(*v1->version(), app_data->version());
2424
2425 // Update the app to v2, which is an extension.
2426 const Extension* v2 =
2427 InstallCRX(data_dir().AppendASCII("sync_datatypes").AppendASCII("v2.crx"),
2428 INSTALL_UPDATED);
2429 EXPECT_FALSE(v2->is_app());
2430 EXPECT_TRUE(v2->is_extension());
2431 EXPECT_EQ(id, v2->id());
2432
2433 // Make sure we saw an extension item added.
2434 ASSERT_EQ(1u, extensions_processor.changes().size());
2435 const SyncChange& extension_change = extensions_processor.changes()[0];
2436 EXPECT_EQ(SyncChange::ACTION_ADD, extension_change.change_type());
dchengc963c7142016-04-08 03:55:222437 std::unique_ptr<ExtensionSyncData> extension_data =
asargente48ab752016-03-12 00:59:202438 ExtensionSyncData::CreateFromSyncData(extension_change.sync_data());
2439 EXPECT_FALSE(extension_data->is_app());
2440 EXPECT_EQ(id, extension_data->id());
2441 EXPECT_EQ(*v2->version(), extension_data->version());
2442
2443 // Get the current data from the change processors to use as the input to
2444 // the following call to MergeDataAndStartSyncing. This simulates what should
2445 // happen with sync.
2446 syncer::SyncDataList extensions_data =
2447 extensions_processor.GetAllSyncData(syncer::EXTENSIONS);
2448 syncer::SyncDataList apps_data = apps_processor.GetAllSyncData(syncer::APPS);
2449
2450 // Stop syncing, then start again.
2451 extension_sync_service()->StopSyncing(syncer::EXTENSIONS);
2452 extension_sync_service()->StopSyncing(syncer::APPS);
2453 extension_sync_service()->MergeDataAndStartSyncing(
2454 syncer::EXTENSIONS, extensions_data, extensions_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222455 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202456 extension_sync_service()->MergeDataAndStartSyncing(
2457 syncer::APPS, apps_data, apps_processor.GetWrapped(),
dchengc963c7142016-04-08 03:55:222458 base::WrapUnique(new syncer::SyncErrorFactoryMock()));
asargente48ab752016-03-12 00:59:202459
2460 // Make sure we saw an app item deleted.
2461 bool found_delete = false;
2462 for (const auto& change : apps_processor.changes()) {
2463 if (change.change_type() == SyncChange::ACTION_DELETE) {
dchengc963c7142016-04-08 03:55:222464 std::unique_ptr<ExtensionSyncData> data =
asargente48ab752016-03-12 00:59:202465 ExtensionSyncData::CreateFromSyncChange(change);
2466 if (data->id() == id) {
2467 found_delete = true;
2468 break;
2469 }
2470 }
2471 }
2472 EXPECT_TRUE(found_delete);
2473
2474 // Make sure there is one extension, and there are no more apps.
2475 EXPECT_EQ(1u, extensions_processor.data().size());
2476 EXPECT_TRUE(apps_processor.data().empty());
2477}