Index: chrome/browser/extensions/extension_service_unittest.cc |
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc |
index e031b50148a763335ecb1ff309d9cfc5515b6eb7..c163aab1b94d0a879f007ec82138c32e46843c8e 100644 |
--- a/chrome/browser/extensions/extension_service_unittest.cc |
+++ b/chrome/browser/extensions/extension_service_unittest.cc |
@@ -7073,22 +7073,83 @@ TEST_F(ExtensionServiceTest, ProcessSyncDataPermissionApproval) { |
} |
#if defined(ENABLE_SUPERVISED_USERS) |
-class ScopedSupervisedUserServiceDelegate |
- : public SupervisedUserService::Delegate { |
+class ExtensionServiceTestSupervised : public ExtensionServiceTest, |
+ public SupervisedUserService::Delegate { |
public: |
- explicit ScopedSupervisedUserServiceDelegate(SupervisedUserService* service) |
- : service_(service) { |
- service_->SetDelegate(this); |
+ void SetUp() override { |
+ ExtensionServiceTest::SetUp(); |
+ |
+ // This is the update URL specified in the permissions test extension. |
+ // Setting it here is necessary to make the extension considered syncable. |
+ base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( |
+ switches::kAppsGalleryUpdateURL, |
+ "http://localhost/autoupdate/updates.xml"); |
} |
- ~ScopedSupervisedUserServiceDelegate() override { |
- service_->SetDelegate(nullptr); |
+ |
+ void TearDown() override { |
+ supervised_user_service()->SetDelegate(nullptr); |
+ |
+ ExtensionServiceTest::TearDown(); |
} |
+ protected: |
+ void InitServices(bool profile_is_supervised) { |
+ ExtensionServiceInitParams params = CreateDefaultInitParams(); |
+ params.profile_is_supervised = profile_is_supervised; |
+ InitializeExtensionService(params); |
+ |
+ supervised_user_service()->SetDelegate(this); |
+ supervised_user_service()->Init(); |
+ } |
+ |
+ std::string InstallPermissionsTestExtension() { |
+ const std::string version("1"); |
+ |
+ const Extension* extension = |
+ PackAndInstallCRX(dir_path(version), pem_path(), INSTALL_NEW, |
+ Extension::WAS_INSTALLED_BY_CUSTODIAN); |
+ // The extension must now be installed and enabled. |
+ EXPECT_TRUE(extension); |
+ EXPECT_TRUE(registry()->enabled_extensions().Contains(extension->id())); |
+ EXPECT_EQ(version, extension->VersionString()); |
+ |
+ return extension->id(); |
+ } |
+ |
+ void UpdatePermissionsTestExtension(const std::string& id, |
+ const std::string& version, |
+ UpdateState expected_state) { |
+ PackCRXAndUpdateExtension(id, dir_path(version), pem_path(), |
+ expected_state); |
+ const Extension* extension = registry()->GetInstalledExtension(id); |
+ ASSERT_TRUE(extension); |
+ // The version should have been updated. |
+ EXPECT_EQ(version, extension->VersionString()); |
+ } |
+ |
+ SupervisedUserService* supervised_user_service() { |
+ return SupervisedUserServiceFactory::GetForProfile(profile()); |
+ } |
+ |
+ static std::string UpdateRequestId(const std::string& extension_id, |
+ const std::string& version) { |
+ return SupervisedUserService::GetExtensionUpdateRequestId( |
+ extension_id, base::Version(version)); |
+ } |
+ |
+ private: |
// This prevents the legacy supervised user init code from running. |
bool SetActive(bool active) override { return true; } |
- private: |
- SupervisedUserService* service_; |
+ base::FilePath base_path() const { |
+ return data_dir().AppendASCII("permissions_increase"); |
+ } |
+ base::FilePath dir_path(const std::string& version) const { |
+ return base_path().AppendASCII("v" + version); |
+ } |
+ base::FilePath pem_path() const { |
+ return base_path().AppendASCII("permissions.pem"); |
+ } |
}; |
class MockPermissionRequestCreator : public PermissionRequestCreator { |
@@ -7111,15 +7172,8 @@ class MockPermissionRequestCreator : public PermissionRequestCreator { |
DISALLOW_COPY_AND_ASSIGN(MockPermissionRequestCreator); |
}; |
-TEST_F(ExtensionServiceTest, SupervisedUserInstallOnlyAllowedByCustodian) { |
- ExtensionServiceInitParams params = CreateDefaultInitParams(); |
- params.profile_is_supervised = true; |
- InitializeExtensionService(params); |
- |
- SupervisedUserService* supervised_user_service = |
- SupervisedUserServiceFactory::GetForProfile(profile()); |
- ScopedSupervisedUserServiceDelegate delegate(supervised_user_service); |
- supervised_user_service->Init(); |
+TEST_F(ExtensionServiceTestSupervised, InstallOnlyAllowedByCustodian) { |
+ InitServices(true /* profile_is_supervised */); |
base::FilePath path1 = data_dir().AppendASCII("good.crx"); |
base::FilePath path2 = data_dir().AppendASCII("good2048.crx"); |
@@ -7135,15 +7189,8 @@ TEST_F(ExtensionServiceTest, SupervisedUserInstallOnlyAllowedByCustodian) { |
EXPECT_TRUE(registry()->enabled_extensions().Contains(extensions[1]->id())); |
} |
-TEST_F(ExtensionServiceTest, SupervisedUserPreinstalledExtension) { |
- ExtensionServiceInitParams params = CreateDefaultInitParams(); |
- // Do *not* set the profile to supervised here! |
- InitializeExtensionService(params); |
- |
- SupervisedUserService* supervised_user_service = |
- SupervisedUserServiceFactory::GetForProfile(profile()); |
- ScopedSupervisedUserServiceDelegate delegate(supervised_user_service); |
- supervised_user_service->Init(); |
+TEST_F(ExtensionServiceTestSupervised, PreinstalledExtension) { |
+ InitServices(false /* profile_is_supervised */); |
// Install an extension. |
base::FilePath path = data_dir().AppendASCII("good.crx"); |
@@ -7158,22 +7205,14 @@ TEST_F(ExtensionServiceTest, SupervisedUserPreinstalledExtension) { |
EXPECT_FALSE(registry()->enabled_extensions().Contains(id)); |
} |
-TEST_F(ExtensionServiceTest, SupervisedUserUpdateWithoutPermissionIncrease) { |
- ExtensionServiceInitParams params = CreateDefaultInitParams(); |
- params.profile_is_supervised = true; |
- InitializeExtensionService(params); |
- |
- SupervisedUserService* supervised_user_service = |
- SupervisedUserServiceFactory::GetForProfile(profile()); |
- ScopedSupervisedUserServiceDelegate delegate(supervised_user_service); |
- supervised_user_service->Init(); |
+TEST_F(ExtensionServiceTestSupervised, UpdateWithoutPermissionIncrease) { |
+ InitServices(true /* profile_is_supervised */); |
base::FilePath base_path = data_dir().AppendASCII("autoupdate"); |
base::FilePath pem_path = base_path.AppendASCII("key.pem"); |
- base::FilePath path = base_path.AppendASCII("v1"); |
const Extension* extension = |
- PackAndInstallCRX(path, pem_path, INSTALL_NEW, |
+ PackAndInstallCRX(base_path.AppendASCII("v1"), pem_path, INSTALL_NEW, |
Extension::WAS_INSTALLED_BY_CUSTODIAN); |
// The extension must now be installed and enabled. |
ASSERT_TRUE(extension); |
@@ -7185,8 +7224,7 @@ TEST_F(ExtensionServiceTest, SupervisedUserUpdateWithoutPermissionIncrease) { |
std::string old_version = extension->VersionString(); |
// Update to a new version. |
- path = base_path.AppendASCII("v2"); |
- PackCRXAndUpdateExtension(id, path, pem_path, ENABLED); |
+ PackCRXAndUpdateExtension(id, base_path.AppendASCII("v2"), pem_path, ENABLED); |
// The extension should still be there and enabled. |
extension = registry()->enabled_extensions().GetByID(id); |
@@ -7195,67 +7233,178 @@ TEST_F(ExtensionServiceTest, SupervisedUserUpdateWithoutPermissionIncrease) { |
EXPECT_NE(extension->VersionString(), old_version); |
} |
-// Helper class that allows us to parameterize the UpdateWithPermissionIncrease |
-// test over |bool need_custodian_approval|. |
-class ExtensionServiceTestSupervisedUserPermissionIncrease : |
- public ExtensionServiceTest, public testing::WithParamInterface<bool> {}; |
+TEST_F(ExtensionServiceTestSupervised, UpdateWithPermissionIncreaseNoApproval) { |
+ // Explicitly disable the "need custodian approval" field trial. |
+ base::FieldTrialList field_trial_list(new base::MockEntropyProvider()); |
+ base::FieldTrialList::CreateFieldTrial( |
+ "SupervisedUserExtensionPermissionIncrease", ""); |
+ |
+ InitServices(true /* profile_is_supervised */); |
+ |
+ MockPermissionRequestCreator* creator = new MockPermissionRequestCreator; |
+ supervised_user_service()->AddPermissionRequestCreator( |
+ make_scoped_ptr(creator)); |
-TEST_P(ExtensionServiceTestSupervisedUserPermissionIncrease, |
- UpdateWithPermissionIncrease) { |
- bool need_custodian_approval = GetParam(); |
+ std::string id = InstallPermissionsTestExtension(); |
+ |
+ // Update to a new version with increased permissions. |
+ // Since we don't require the custodian's approval, no permission request |
+ // should be created. |
+ const std::string version2("2"); |
+ EXPECT_CALL(*creator, CreateExtensionUpdateRequest( |
+ UpdateRequestId(id, version2), testing::_)) |
+ .Times(0); |
+ UpdatePermissionsTestExtension(id, version2, DISABLED); |
+} |
+ |
+TEST_F(ExtensionServiceTestSupervised, |
+ UpdateWithPermissionIncreaseApprovalOldVersion) { |
+ // Explicitly enable the "need custodian approval" field trial. |
base::FieldTrialList field_trial_list(new base::MockEntropyProvider()); |
base::FieldTrialList::CreateFieldTrial( |
- "SupervisedUserExtensionPermissionIncrease", |
- need_custodian_approval ? "NeedCustodianApproval" : ""); |
+ "SupervisedUserExtensionPermissionIncrease", "NeedCustodianApproval"); |
- ExtensionServiceInitParams params = CreateDefaultInitParams(); |
- params.profile_is_supervised = true; |
- InitializeExtensionService(params); |
+ InitServices(true /* profile_is_supervised */); |
- SupervisedUserService* supervised_user_service = |
- SupervisedUserServiceFactory::GetForProfile(profile()); |
- ScopedSupervisedUserServiceDelegate delegate(supervised_user_service); |
- supervised_user_service->Init(); |
MockPermissionRequestCreator* creator = new MockPermissionRequestCreator; |
- supervised_user_service->AddPermissionRequestCreator( |
+ supervised_user_service()->AddPermissionRequestCreator( |
make_scoped_ptr(creator)); |
- base::FilePath base_path = data_dir().AppendASCII("permissions_increase"); |
- base::FilePath pem_path = base_path.AppendASCII("permissions.pem"); |
+ const std::string version1("1"); |
+ const std::string version2("2"); |
- base::FilePath path = base_path.AppendASCII("v1"); |
- const Extension* extension = |
- PackAndInstallCRX(path, pem_path, INSTALL_NEW, |
- Extension::WAS_INSTALLED_BY_CUSTODIAN); |
- // The extension must now be installed and enabled. |
- ASSERT_TRUE(extension); |
- ASSERT_TRUE(registry()->enabled_extensions().Contains(extension->id())); |
+ std::string id = InstallPermissionsTestExtension(); |
- // Save the id, as the extension object will be destroyed during updating. |
- std::string id = extension->id(); |
+ // Update to a new version with increased permissions. |
+ EXPECT_CALL(*creator, CreateExtensionUpdateRequest( |
+ UpdateRequestId(id, version2), testing::_)); |
+ UpdatePermissionsTestExtension(id, version2, DISABLED); |
- std::string old_version = extension->VersionString(); |
+ // Simulate a custodian approval for re-enabling the extension coming in |
+ // through Sync, but set the old version. This can happen when there already |
+ // was a pending request for an earlier version of the extension. |
+ sync_pb::EntitySpecifics specifics; |
+ sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension(); |
+ ext_specifics->set_id(id); |
+ ext_specifics->set_enabled(true); |
+ ext_specifics->set_disable_reasons(Extension::DISABLE_NONE); |
+ ext_specifics->set_installed_by_custodian(true); |
+ ext_specifics->set_version(version1); |
+ |
+ // Attempting to re-enable an old version should result in a permission |
+ // request for the current version. |
+ EXPECT_CALL(*creator, CreateExtensionUpdateRequest( |
+ UpdateRequestId(id, version2), testing::_)); |
+ |
+ syncer::SyncData sync_data = |
+ syncer::SyncData::CreateLocalData(id, "Name", specifics); |
+ syncer::SyncChange sync_change(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, |
+ sync_data); |
+ syncer::SyncChangeList change_list(1, sync_change); |
+ extension_sync_service()->ProcessSyncChanges(FROM_HERE, change_list); |
+ // The re-enable should be ignored, since the version doesn't match. |
+ EXPECT_FALSE(registry()->enabled_extensions().Contains(id)); |
+ EXPECT_FALSE(extension_sync_service()->HasPendingReenable( |
+ id, base::Version(version1))); |
+ EXPECT_FALSE(extension_sync_service()->HasPendingReenable( |
+ id, base::Version(version2))); |
+} |
+ |
+TEST_F(ExtensionServiceTestSupervised, |
+ UpdateWithPermissionIncreaseApprovalMatchingVersion) { |
+ // Explicitly enable the "need custodian approval" field trial. |
+ base::FieldTrialList field_trial_list(new base::MockEntropyProvider()); |
+ base::FieldTrialList::CreateFieldTrial( |
+ "SupervisedUserExtensionPermissionIncrease", "NeedCustodianApproval"); |
+ |
+ InitServices(true /* profile_is_supervised */); |
+ |
+ MockPermissionRequestCreator* creator = new MockPermissionRequestCreator; |
+ supervised_user_service()->AddPermissionRequestCreator( |
+ make_scoped_ptr(creator)); |
+ |
+ std::string id = InstallPermissionsTestExtension(); |
// Update to a new version with increased permissions. |
- EXPECT_CALL(*creator, |
- CreateExtensionUpdateRequest(id + ":2", testing::_)) |
- .Times(need_custodian_approval ? 1 : 0); |
- path = base_path.AppendASCII("v2"); |
- PackCRXAndUpdateExtension(id, path, pem_path, DISABLED); |
+ const std::string version2("2"); |
+ EXPECT_CALL(*creator, CreateExtensionUpdateRequest( |
+ UpdateRequestId(id, version2), testing::_)); |
+ UpdatePermissionsTestExtension(id, version2, DISABLED); |
+ |
+ // Simulate a custodian approval for re-enabling the extension coming in |
+ // through Sync. |
+ sync_pb::EntitySpecifics specifics; |
+ sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension(); |
+ ext_specifics->set_id(id); |
+ ext_specifics->set_enabled(true); |
+ ext_specifics->set_disable_reasons(Extension::DISABLE_NONE); |
+ ext_specifics->set_installed_by_custodian(true); |
+ ext_specifics->set_version(version2); |
+ |
+ syncer::SyncData sync_data = |
+ syncer::SyncData::CreateLocalData(id, "Name", specifics); |
+ syncer::SyncChange sync_change(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, |
+ sync_data); |
+ syncer::SyncChangeList change_list(1, sync_change); |
+ extension_sync_service()->ProcessSyncChanges(FROM_HERE, change_list); |
+ // The extension should have gotten re-enabled. |
+ EXPECT_TRUE(registry()->enabled_extensions().Contains(id)); |
+} |
- // The extension should still be there, but disabled. |
+TEST_F(ExtensionServiceTestSupervised, |
+ UpdateWithPermissionIncreaseApprovalNewVersion) { |
+ // Explicitly enable the "need custodian approval" field trial. |
+ base::FieldTrialList field_trial_list(new base::MockEntropyProvider()); |
+ base::FieldTrialList::CreateFieldTrial( |
+ "SupervisedUserExtensionPermissionIncrease", "NeedCustodianApproval"); |
+ |
+ InitServices(true /* profile_is_supervised */); |
+ |
+ MockPermissionRequestCreator* creator = new MockPermissionRequestCreator; |
+ supervised_user_service()->AddPermissionRequestCreator( |
+ make_scoped_ptr(creator)); |
+ |
+ std::string id = InstallPermissionsTestExtension(); |
+ |
+ // Update to a new version with increased permissions. |
+ const std::string version2("2"); |
+ EXPECT_CALL(*creator, CreateExtensionUpdateRequest( |
+ UpdateRequestId(id, version2), testing::_)); |
+ UpdatePermissionsTestExtension(id, version2, DISABLED); |
+ |
+ // Simulate a custodian approval for re-enabling the extension coming in |
+ // through Sync. Set a newer version than we have installed. |
+ const std::string version3("3"); |
+ sync_pb::EntitySpecifics specifics; |
+ sync_pb::ExtensionSpecifics* ext_specifics = specifics.mutable_extension(); |
+ ext_specifics->set_id(id); |
+ ext_specifics->set_enabled(true); |
+ ext_specifics->set_disable_reasons(Extension::DISABLE_NONE); |
+ ext_specifics->set_installed_by_custodian(true); |
+ ext_specifics->set_version(version3); |
+ |
+ // This should *not* result in a new permission request. |
+ EXPECT_CALL(*creator, CreateExtensionUpdateRequest( |
+ UpdateRequestId(id, version3), testing::_)) |
+ .Times(0); |
+ |
+ syncer::SyncData sync_data = |
+ syncer::SyncData::CreateLocalData(id, "Name", specifics); |
+ syncer::SyncChange sync_change(FROM_HERE, syncer::SyncChange::ACTION_UPDATE, |
+ sync_data); |
+ syncer::SyncChangeList change_list(1, sync_change); |
+ extension_sync_service()->ProcessSyncChanges(FROM_HERE, change_list); |
+ // The re-enable should be delayed until the extension is updated to the |
+ // matching version. |
EXPECT_FALSE(registry()->enabled_extensions().Contains(id)); |
- extension = registry()->disabled_extensions().GetByID(id); |
- ASSERT_TRUE(extension); |
- // The version should have changed. |
- EXPECT_NE(extension->VersionString(), old_version); |
+ EXPECT_TRUE(extension_sync_service()->HasPendingReenable( |
+ id, base::Version(version3))); |
+ |
+ // Update to the matching version. Now the extension should get enabled. |
+ UpdatePermissionsTestExtension(id, version3, ENABLED); |
} |
-INSTANTIATE_TEST_CASE_P(NeedCustodianApproval, |
- ExtensionServiceTestSupervisedUserPermissionIncrease, |
- testing::Bool()); |
-TEST_F(ExtensionServiceTest, |
- SupervisedUserSyncUninstallByCustodianSkipsPolicy) { |
+TEST_F(ExtensionServiceTest, SyncUninstallByCustodianSkipsPolicy) { |
InitializeEmptyExtensionService(); |
extension_sync_service()->MergeDataAndStartSyncing( |
syncer::EXTENSIONS, |