#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/extensions/extension_message_bubble.h"
#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/settings_api_bubble_controller.h"
#include "chrome/browser/extensions/suspicious_extension_bubble_controller.h"
#include "chrome/browser/extensions/test_extension_system.h"
+#include "chrome/common/chrome_version_info.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "extensions/common/extension.h"
+#include "extensions/common/extension_builder.h"
#include "extensions/common/feature_switch.h"
+namespace {
+
+const char kId1[] = "iccfkkhkfiphcjdakkmcjmkfboccmndk";
+const char kId2[] = "ajjhifimiemdpmophmkkkcijegphclbl";
+const char kId3[] = "ioibbbfddncmmabjmpokikkeiofalaek";
+
+} // namespace
+
namespace extensions {
class TestDelegate {
}
};
+// A test class for the SettingsApiBubbleController.
+class TestSettingsApiBubbleController : public SettingsApiBubbleController,
+ public TestDelegate {
+ public:
+ TestSettingsApiBubbleController(Profile* profile,
+ SettingsApiOverrideType type)
+ : SettingsApiBubbleController(profile, type) {}
+
+ virtual void OnBubbleAction() OVERRIDE {
+ ++action_button_callback_count_;
+ SettingsApiBubbleController::OnBubbleAction();
+ }
+
+ virtual void OnBubbleDismiss() OVERRIDE {
+ ++dismiss_button_callback_count_;
+ SettingsApiBubbleController::OnBubbleDismiss();
+ }
+
+ virtual void OnLinkClicked() OVERRIDE {
+ ++link_click_callback_count_;
+ SettingsApiBubbleController::OnLinkClicked();
+ }
+};
+
// A fake bubble used for testing the controller. Takes an action that specifies
// what should happen when the bubble is "shown" (the bubble is actually not
// shown, the corresponding action is taken immediately).
class ExtensionMessageBubbleTest : public testing::Test {
public:
- ExtensionMessageBubbleTest() {
+ ExtensionMessageBubbleTest() {}
+
+ void LoadGenericExtension(const std::string& index,
+ const std::string& id,
+ Manifest::Location location) {
+ extensions::ExtensionBuilder builder;
+ builder.SetManifest(extensions::DictionaryBuilder()
+ .Set("name", std::string("Extension " + index))
+ .Set("version", "1.0")
+ .Set("manifest_version", 2));
+ builder.SetLocation(location);
+ builder.SetID(id);
+ service_->AddExtension(builder.Build().get());
+ }
+
+ void LoadExtensionWithAction(const std::string& index,
+ const std::string& id,
+ Manifest::Location location) {
+ extensions::ExtensionBuilder builder;
+ builder.SetManifest(extensions::DictionaryBuilder()
+ .Set("name", std::string("Extension " + index))
+ .Set("version", "1.0")
+ .Set("manifest_version", 2)
+ .Set("browser_action",
+ extensions::DictionaryBuilder().Set(
+ "default_title", "Default title")));
+ builder.SetLocation(location);
+ builder.SetID(id);
+ service_->AddExtension(builder.Build().get());
+ }
+
+ void LoadExtensionOverridingHome(const std::string& index,
+ const std::string& id,
+ Manifest::Location location) {
+ extensions::ExtensionBuilder builder;
+ builder.SetManifest(extensions::DictionaryBuilder()
+ .Set("name", std::string("Extension " + index))
+ .Set("version", "1.0")
+ .Set("manifest_version", 2)
+ .Set("chrome_settings_overrides",
+ extensions::DictionaryBuilder().Set(
+ "homepage", "http://www.google.com")));
+ builder.SetLocation(location);
+ builder.SetID(id);
+ service_->AddExtension(builder.Build().get());
+ }
+
+ void LoadExtensionOverridingStart(const std::string& index,
+ const std::string& id,
+ Manifest::Location location) {
+ extensions::ExtensionBuilder builder;
+ builder.SetManifest(extensions::DictionaryBuilder()
+ .Set("name", std::string("Extension " + index))
+ .Set("version", "1.0")
+ .Set("manifest_version", 2)
+ .Set("chrome_settings_overrides",
+ extensions::DictionaryBuilder().Set(
+ "startup_pages",
+ extensions::ListBuilder().Append(
+ "http://www.google.com"))));
+ builder.SetLocation(location);
+ builder.SetID(id);
+ service_->AddExtension(builder.Build().get());
+ }
+
+ void Init() {
// The two lines of magical incantation required to get the extension
// service to work inside a unit test and access the extension prefs.
thread_bundle_.reset(new content::TestBrowserThreadBundle);
profile_.reset(new TestingProfile);
-
static_cast<TestExtensionSystem*>(
ExtensionSystem::Get(profile()))->CreateExtensionService(
CommandLine::ForCurrentProcess(),
false);
service_ = profile_->GetExtensionService();
service_->Init();
-
- std::string basic_extension =
- "{\"name\": \"Extension #\","
- "\"version\": \"1.0\","
- "\"manifest_version\": 2}";
- std::string basic_extension_with_action =
- "{\"name\": \"Extension #\","
- "\"version\": \"1.0\","
- "\"browser_action\": {"
- " \"default_title\": \"Default title\""
- "},"
- "\"manifest_version\": 2}";
-
- std::string extension_data;
- base::ReplaceChars(basic_extension_with_action, "#", "1", &extension_data);
- scoped_refptr<Extension> my_test_extension1(
- CreateExtension(
- Manifest::COMMAND_LINE,
- extension_data,
- "Autogenerated 1"));
-
- base::ReplaceChars(basic_extension, "#", "2", &extension_data);
- scoped_refptr<Extension> my_test_extension2(
- CreateExtension(
- Manifest::UNPACKED,
- extension_data,
- "Autogenerated 2"));
-
- base::ReplaceChars(basic_extension, "#", "3", &extension_data);
- scoped_refptr<Extension> regular_extension(
- CreateExtension(
- Manifest::EXTERNAL_POLICY,
- extension_data,
- "Autogenerated 3"));
-
- extension_id1_ = my_test_extension1->id();
- extension_id2_ = my_test_extension2->id();
- extension_id3_ = regular_extension->id();
-
- service_->AddExtension(regular_extension);
- service_->AddExtension(my_test_extension1);
- service_->AddExtension(my_test_extension2);
}
+
virtual ~ExtensionMessageBubbleTest() {
// Make sure the profile is destroyed before the thread bundle.
profile_.reset(NULL);
}
ExtensionService* service_;
- std::string extension_id1_;
- std::string extension_id2_;
- std::string extension_id3_;
private:
scoped_ptr<CommandLine> command_line_;
#endif
TEST_F(ExtensionMessageBubbleTest, MAYBE_WipeoutControllerTest) {
- // The test base class adds three extensions, and we control two of them in
- // this test (ids are: extension_id1_ and extension_id2_).
+ Init();
+ // Add three extensions, and control two of them in this test (extension 1
+ // and 2).
+ LoadExtensionWithAction("1", kId1, Manifest::COMMAND_LINE);
+ LoadGenericExtension("2", kId2, Manifest::UNPACKED);
+ LoadGenericExtension("3", kId3, Manifest::EXTERNAL_POLICY);
+
scoped_ptr<TestSuspiciousExtensionBubbleController> controller(
new TestSuspiciousExtensionBubbleController(profile()));
FakeExtensionMessageBubble bubble;
// Validate that we don't have a suppress value for the extensions.
ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
- EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(extension_id1_));
- EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(extension_id2_));
+ EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(kId1));
+ EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(kId2));
EXPECT_FALSE(controller->ShouldShow());
std::vector<base::string16> suspicious_extensions =
EXPECT_EQ(0U, controller->dismiss_click_count());
// Now disable an extension, specifying the wipeout flag.
- service_->DisableExtension(extension_id1_,
- Extension::DISABLE_NOT_VERIFIED);
+ service_->DisableExtension(kId1, Extension::DISABLE_NOT_VERIFIED);
- EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(extension_id1_));
- EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(extension_id2_));
+ EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(kId1));
+ EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(kId2));
controller.reset(new TestSuspiciousExtensionBubbleController(
profile()));
SuspiciousExtensionBubbleController::ClearProfileListForTesting();
EXPECT_EQ(0U, controller->link_click_count());
EXPECT_EQ(1U, controller->dismiss_click_count());
// Now the acknowledge flag should be set only for the first extension.
- EXPECT_TRUE(prefs->HasWipeoutBeenAcknowledged(extension_id1_));
- EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(extension_id2_));
+ EXPECT_TRUE(prefs->HasWipeoutBeenAcknowledged(kId1));
+ EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(kId2));
// Clear the flag.
- prefs->SetWipeoutAcknowledged(extension_id1_, false);
- EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(extension_id1_));
+ prefs->SetWipeoutAcknowledged(kId1, false);
+ EXPECT_FALSE(prefs->HasWipeoutBeenAcknowledged(kId1));
// Now disable the other extension and exercise the link click code path.
- service_->DisableExtension(extension_id2_,
- Extension::DISABLE_NOT_VERIFIED);
+ service_->DisableExtension(kId2, Extension::DISABLE_NOT_VERIFIED);
bubble.set_action_on_show(
FakeExtensionMessageBubble::BUBBLE_ACTION_CLICK_LINK);
controller->Show(&bubble); // Simulate showing the bubble.
EXPECT_EQ(1U, controller->link_click_count());
EXPECT_EQ(0U, controller->dismiss_click_count());
- EXPECT_TRUE(prefs->HasWipeoutBeenAcknowledged(extension_id1_));
+ EXPECT_TRUE(prefs->HasWipeoutBeenAcknowledged(kId1));
}
// The feature this is meant to test is only implemented on Windows.
TEST_F(ExtensionMessageBubbleTest, MAYBE_DevModeControllerTest) {
FeatureSwitch::ScopedOverride force_dev_mode_highlighting(
FeatureSwitch::force_dev_mode_highlighting(), true);
- // The test base class adds three extensions, and we control two of them in
- // this test (ids are: extension_id1_ and extension_id2_). Extension 1 is a
- // regular extension, Extension 2 is UNPACKED so it counts as a DevMode
- // extension.
+ Init();
+ // Add three extensions, and control two of them in this test (extension 1
+ // and 2). Extension 1 is a regular extension, Extension 2 is UNPACKED so it
+ // counts as a DevMode extension.
+ LoadExtensionWithAction("1", kId1, Manifest::COMMAND_LINE);
+ LoadGenericExtension("2", kId2, Manifest::UNPACKED);
+ LoadGenericExtension("3", kId3, Manifest::EXTERNAL_POLICY);
+
scoped_ptr<TestDevModeBubbleController> controller(
new TestDevModeBubbleController(profile()));
EXPECT_EQ(0U, controller->link_click_count());
EXPECT_EQ(0U, controller->action_click_count());
EXPECT_EQ(1U, controller->dismiss_click_count());
- EXPECT_TRUE(service_->GetExtensionById(extension_id1_, false) != NULL);
- EXPECT_TRUE(service_->GetExtensionById(extension_id2_, false) != NULL);
+ EXPECT_TRUE(service_->GetExtensionById(kId1, false) != NULL);
+ EXPECT_TRUE(service_->GetExtensionById(kId2, false) != NULL);
// Do it again, but now press different button (Disable).
bubble.set_action_on_show(
EXPECT_EQ(0U, controller->link_click_count());
EXPECT_EQ(1U, controller->action_click_count());
EXPECT_EQ(0U, controller->dismiss_click_count());
- EXPECT_TRUE(service_->GetExtensionById(extension_id1_, false) == NULL);
- EXPECT_TRUE(service_->GetExtensionById(extension_id2_, false) == NULL);
+ EXPECT_TRUE(service_->GetExtensionById(kId1, false) == NULL);
+ EXPECT_TRUE(service_->GetExtensionById(kId2, false) == NULL);
// Re-enable the extensions (disabled by the action button above).
- service_->EnableExtension(extension_id1_);
- service_->EnableExtension(extension_id2_);
+ service_->EnableExtension(kId1);
+ service_->EnableExtension(kId2);
// Show the dialog a third time, but now press the learn more link.
bubble.set_action_on_show(
EXPECT_EQ(1U, controller->link_click_count());
EXPECT_EQ(0U, controller->action_click_count());
EXPECT_EQ(0U, controller->dismiss_click_count());
- EXPECT_TRUE(service_->GetExtensionById(extension_id1_, false) != NULL);
- EXPECT_TRUE(service_->GetExtensionById(extension_id2_, false) != NULL);
+ EXPECT_TRUE(service_->GetExtensionById(kId1, false) != NULL);
+ EXPECT_TRUE(service_->GetExtensionById(kId2, false) != NULL);
// Now disable the unpacked extension.
- service_->DisableExtension(extension_id1_, Extension::DISABLE_USER_ACTION);
- service_->DisableExtension(extension_id2_, Extension::DISABLE_USER_ACTION);
+ service_->DisableExtension(kId1, Extension::DISABLE_USER_ACTION);
+ service_->DisableExtension(kId2, Extension::DISABLE_USER_ACTION);
controller.reset(new TestDevModeBubbleController(
profile()));
EXPECT_EQ(0U, dev_mode_extensions.size());
}
+// The feature this is meant to test is only implemented on Windows.
+#if defined(OS_WIN)
+#define MAYBE_SettingsApiControllerTest SettingsApiControllerTest
+#else
+#define MAYBE_SettingsApiControllerTest DISABLED_SettingsApiControllerTest
+#endif
+
+TEST_F(ExtensionMessageBubbleTest, MAYBE_SettingsApiControllerTest) {
+ Init();
+ extensions::ExtensionPrefs* prefs =
+ extensions::ExtensionPrefs::Get(profile());
+
+ for (int i = 0; i < 3; ++i) {
+ switch (static_cast<SettingsApiOverrideType>(i)) {
+ case BUBBLE_TYPE_HOME_PAGE:
+ // Load two extensions overriding home page and one overriding something
+ // unrelated (to check for interference). Extension 2 should still win
+ // on the home page setting.
+ LoadExtensionOverridingHome("1", kId1, Manifest::UNPACKED);
+ LoadExtensionOverridingHome("2", kId2, Manifest::UNPACKED);
+ LoadExtensionOverridingStart("3", kId3, Manifest::UNPACKED);
+ break;
+ case BUBBLE_TYPE_SEARCH_ENGINE:
+ // We deliberately skip testing the search engine since it relies on
+ // TemplateURLServiceFactory that isn't available while unit testing.
+ // This test is only simulating the bubble interaction with the user and
+ // that is more or less the same for the search engine as it is for the
+ // others.
+ continue;
+ case BUBBLE_TYPE_STARTUP_PAGES:
+ // Load two extensions overriding start page and one overriding
+ // something unrelated (to check for interference). Extension 2 should
+ // still win on the startup page setting.
+ LoadExtensionOverridingStart("1", kId1, Manifest::UNPACKED);
+ LoadExtensionOverridingStart("2", kId2, Manifest::UNPACKED);
+ LoadExtensionOverridingHome("3", kId3, Manifest::UNPACKED);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ scoped_ptr<TestSettingsApiBubbleController> controller(
+ new TestSettingsApiBubbleController(
+ profile(), static_cast<SettingsApiOverrideType>(i)));
+
+ // The list will contain one enabled unpacked extension (ext 2).
+ EXPECT_TRUE(controller->ShouldShow(kId2));
+ std::vector<base::string16> override_extensions =
+ controller->GetExtensionList();
+ ASSERT_EQ(1U, override_extensions.size());
+ EXPECT_TRUE(base::ASCIIToUTF16("Extension 2") ==
+ override_extensions[0].c_str());
+ EXPECT_EQ(0U, controller->link_click_count());
+ EXPECT_EQ(0U, controller->dismiss_click_count());
+ EXPECT_EQ(0U, controller->action_click_count());
+
+ // Simulate showing the bubble and dismissing it.
+ FakeExtensionMessageBubble bubble;
+ bubble.set_action_on_show(
+ FakeExtensionMessageBubble::BUBBLE_ACTION_CLICK_DISMISS_BUTTON);
+ controller->Show(&bubble);
+ EXPECT_EQ(0U, controller->link_click_count());
+ EXPECT_EQ(0U, controller->action_click_count());
+ EXPECT_EQ(1U, controller->dismiss_click_count());
+ // No extension should have become disabled.
+ EXPECT_TRUE(service_->GetExtensionById(kId1, false) != NULL);
+ EXPECT_TRUE(service_->GetExtensionById(kId2, false) != NULL);
+ EXPECT_TRUE(service_->GetExtensionById(kId3, false) != NULL);
+ // Only extension 2 should have been acknowledged.
+ EXPECT_FALSE(prefs->HasSettingsApiBubbleBeenAcknowledged(kId1));
+ EXPECT_TRUE(prefs->HasSettingsApiBubbleBeenAcknowledged(kId2));
+ EXPECT_FALSE(prefs->HasSettingsApiBubbleBeenAcknowledged(kId3));
+ // Clean up after ourselves.
+ prefs->SetSettingsApiBubbleBeenAcknowledged(kId2, false);
+
+ // Simulate clicking the learn more link to dismiss it.
+ bubble.set_action_on_show(
+ FakeExtensionMessageBubble::BUBBLE_ACTION_CLICK_LINK);
+ controller.reset(new TestSettingsApiBubbleController(
+ profile(), static_cast<SettingsApiOverrideType>(i)));
+ controller->Show(&bubble);
+ EXPECT_EQ(1U, controller->link_click_count());
+ EXPECT_EQ(0U, controller->action_click_count());
+ EXPECT_EQ(0U, controller->dismiss_click_count());
+ // No extension should have become disabled.
+ EXPECT_TRUE(service_->GetExtensionById(kId1, false) != NULL);
+ EXPECT_TRUE(service_->GetExtensionById(kId2, false) != NULL);
+ EXPECT_TRUE(service_->GetExtensionById(kId3, false) != NULL);
+ // Only extension 2 should have been acknowledged.
+ EXPECT_FALSE(prefs->HasSettingsApiBubbleBeenAcknowledged(kId1));
+ EXPECT_TRUE(prefs->HasSettingsApiBubbleBeenAcknowledged(kId2));
+ EXPECT_FALSE(prefs->HasSettingsApiBubbleBeenAcknowledged(kId3));
+ // Clean up after ourselves.
+ prefs->SetSettingsApiBubbleBeenAcknowledged(kId2, false);
+
+ // Do it again, but now opt to disable the extension.
+ bubble.set_action_on_show(
+ FakeExtensionMessageBubble::BUBBLE_ACTION_CLICK_ACTION_BUTTON);
+ controller.reset(new TestSettingsApiBubbleController(
+ profile(), static_cast<SettingsApiOverrideType>(i)));
+ EXPECT_TRUE(controller->ShouldShow(kId2));
+ override_extensions = controller->GetExtensionList();
+ EXPECT_EQ(1U, override_extensions.size());
+ controller->Show(&bubble); // Simulate showing the bubble.
+ EXPECT_EQ(0U, controller->link_click_count());
+ EXPECT_EQ(1U, controller->action_click_count());
+ EXPECT_EQ(0U, controller->dismiss_click_count());
+ // Only extension 2 should have become disabled.
+ EXPECT_TRUE(service_->GetExtensionById(kId1, false) != NULL);
+ EXPECT_TRUE(service_->GetExtensionById(kId2, false) == NULL);
+ EXPECT_TRUE(service_->GetExtensionById(kId3, false) != NULL);
+ // No extension should have been acknowledged (it got disabled).
+ EXPECT_FALSE(prefs->HasSettingsApiBubbleBeenAcknowledged(kId1));
+ EXPECT_FALSE(prefs->HasSettingsApiBubbleBeenAcknowledged(kId2));
+ EXPECT_FALSE(prefs->HasSettingsApiBubbleBeenAcknowledged(kId3));
+
+ // Clean up after ourselves.
+ service_->UninstallExtension(kId1, false, NULL);
+ service_->UninstallExtension(kId2, false, NULL);
+ service_->UninstallExtension(kId3, false, NULL);
+ }
+}
+
} // namespace extensions