// Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include <string> #include <vector> #include "base/memory/ref_counted.h" #include "base/values.h" #include "chrome/browser/extensions/component_migration_helper.h" #include "chrome/browser/extensions/extension_action_test_util.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_service_test_base.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_registry_simple.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/feature_switch.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using ::testing::Return; using ::testing::StrictMock; namespace extensions { namespace { const char kTestActionId[] = "toolbar-action"; class MockComponentActionDelegate : public ComponentMigrationHelper::ComponentActionDelegate { public: MOCK_METHOD1(AddComponentAction, void(const std::string&)); MOCK_METHOD1(RemoveComponentAction, void(const std::string&)); MOCK_CONST_METHOD1(HasComponentAction, bool(const std::string&)); }; class MockComponentMigrationHelper : public ComponentMigrationHelper { public: MockComponentMigrationHelper(Profile* profile, ComponentActionDelegate* delegate) : ComponentMigrationHelper(profile, delegate) {} ~MockComponentMigrationHelper() override{}; void SetTestComponentActionPref(bool enabled) { SetComponentActionPref(kTestActionId, enabled); } void EnableTestFeature() { enabled_actions_.insert(kTestActionId); } void DisableTestFeature() { enabled_actions_.erase(kTestActionId); } }; } // namespace class ComponentMigrationHelperTest : public ExtensionServiceTestBase { protected: ComponentMigrationHelperTest() {} ~ComponentMigrationHelperTest() override {} void SetUp() override { extension_action_redesign_.reset(new FeatureSwitch::ScopedOverride( FeatureSwitch::extension_action_redesign(), FeatureSwitch::OVERRIDE_ENABLED)); ExtensionServiceTestBase::SetUp(); InitializeEmptyExtensionService(); migrated_extension_a_ = extension_action_test_util::CreateActionExtension( "migrated_browser_action_a", extension_action_test_util::BROWSER_ACTION); migrated_extension_b_ = extension_action_test_util::CreateActionExtension( "migrated_browser_action_b", extension_action_test_util::BROWSER_ACTION); unregistered_extension_ = extension_action_test_util::CreateActionExtension( "unregistered_extension", extension_action_test_util::BROWSER_ACTION); mock_helper_.reset(new StrictMock<MockComponentMigrationHelper>( profile(), &mock_delegate_)); mock_helper_->Register(kTestActionId, migrated_extension_a_->id()); mock_helper_->Register(kTestActionId, migrated_extension_b_->id()); } bool IsTestComponentActionEnabled() { const base::DictionaryValue* migration_pref = profile()->GetPrefs()->GetDictionary( ::prefs::kToolbarMigratedComponentActionStatus); if (!migration_pref->HasKey(kTestActionId)) return false; bool enable_value = false; CHECK(migration_pref->GetBoolean(kTestActionId, &enable_value)); return enable_value; } StrictMock<MockComponentActionDelegate> mock_delegate_; scoped_ptr<StrictMock<MockComponentMigrationHelper>> mock_helper_; scoped_ptr<FeatureSwitch::ScopedOverride> extension_action_redesign_; // Migrated extensions with browser actions. scoped_refptr<const Extension> migrated_extension_a_; scoped_refptr<const Extension> migrated_extension_b_; // An extension that is not migrated. scoped_refptr<const Extension> unregistered_extension_; private: DISALLOW_COPY_AND_ASSIGN(ComponentMigrationHelperTest); }; TEST_F(ComponentMigrationHelperTest, FeatureEnabledWhenExtensionInstalled) { service()->AddExtension(migrated_extension_a_.get()); service()->AddExtension(migrated_extension_b_.get()); EXPECT_CALL(mock_delegate_, HasComponentAction(kTestActionId)) .WillOnce(Return(false)); EXPECT_CALL(mock_delegate_, AddComponentAction(kTestActionId)); mock_helper_->OnFeatureEnabled(kTestActionId); EXPECT_TRUE(IsTestComponentActionEnabled()); EXPECT_FALSE( registry()->enabled_extensions().Contains(migrated_extension_a_->id())); EXPECT_FALSE( registry()->enabled_extensions().Contains(migrated_extension_b_->id())); } TEST_F(ComponentMigrationHelperTest, FeatureEnabledWithNoPref) { mock_helper_->OnFeatureEnabled(kTestActionId); EXPECT_FALSE(IsTestComponentActionEnabled()); } TEST_F(ComponentMigrationHelperTest, FeatureEnabledWithPrefFalse) { mock_helper_->SetTestComponentActionPref(false); mock_helper_->OnFeatureEnabled(kTestActionId); EXPECT_FALSE(IsTestComponentActionEnabled()); } TEST_F(ComponentMigrationHelperTest, FeatureEnabledWithPrefTrue) { mock_helper_->SetTestComponentActionPref(true); EXPECT_CALL(mock_delegate_, HasComponentAction(kTestActionId)) .WillOnce(Return(false)); EXPECT_CALL(mock_delegate_, AddComponentAction(kTestActionId)); mock_helper_->OnFeatureEnabled(kTestActionId); EXPECT_TRUE(IsTestComponentActionEnabled()); } TEST_F(ComponentMigrationHelperTest, FeatureDisabledWithAction) { mock_helper_->EnableTestFeature(); EXPECT_CALL(mock_delegate_, HasComponentAction(kTestActionId)) .WillOnce(Return(true)); EXPECT_CALL(mock_delegate_, RemoveComponentAction(kTestActionId)); mock_helper_->OnFeatureDisabled(kTestActionId); EXPECT_FALSE(IsTestComponentActionEnabled()); } TEST_F(ComponentMigrationHelperTest, InstallWithFeatureEnabled) { mock_helper_->EnableTestFeature(); EXPECT_CALL(mock_delegate_, HasComponentAction(kTestActionId)) .WillOnce(Return(false)); EXPECT_CALL(mock_delegate_, AddComponentAction(kTestActionId)); service()->AddExtension(migrated_extension_a_.get()); // The test framework does not call OnExtensionReady :-/ mock_helper_->OnExtensionReady(browser_context(), migrated_extension_a_.get()); EXPECT_TRUE(IsTestComponentActionEnabled()); EXPECT_FALSE( registry()->enabled_extensions().Contains(migrated_extension_a_->id())); } TEST_F(ComponentMigrationHelperTest, InstallWithFeatureDisabled) { mock_helper_->DisableTestFeature(); service()->AddExtension(migrated_extension_a_.get()); EXPECT_FALSE(IsTestComponentActionEnabled()); EXPECT_TRUE( registry()->enabled_extensions().Contains(migrated_extension_a_->id())); } TEST_F(ComponentMigrationHelperTest, InstallUnregisteredExtension) { service()->AddExtension(unregistered_extension_.get()); EXPECT_FALSE(IsTestComponentActionEnabled()); EXPECT_TRUE( registry()->enabled_extensions().Contains(unregistered_extension_->id())); } TEST_F(ComponentMigrationHelperTest, RemoveComponentAction) { mock_helper_->SetTestComponentActionPref(true); EXPECT_CALL(mock_delegate_, HasComponentAction(kTestActionId)) .WillOnce(Return(false)); EXPECT_CALL(mock_delegate_, AddComponentAction(kTestActionId)); mock_helper_->OnFeatureEnabled(kTestActionId); EXPECT_TRUE(IsTestComponentActionEnabled()); EXPECT_CALL(mock_delegate_, HasComponentAction(kTestActionId)) .WillOnce(Return(true)); EXPECT_CALL(mock_delegate_, RemoveComponentAction(kTestActionId)); mock_helper_->OnActionRemoved(kTestActionId); EXPECT_FALSE(IsTestComponentActionEnabled()); } } // namespace extensions