blob: 3007a43813082845e491a86d0cea5d871e356fa2 [file] [log] [blame]
// Copyright 2014 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 "base/memory/ref_counted.h"
#include "chrome/browser/extensions/extension_error_controller.h"
#include "chrome/browser/extensions/extension_error_ui.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/test/base/testing_profile.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_builder.h"
#include "extensions/common/value_builder.h"
namespace extensions {
namespace {
// Create a mock for the UI component of the error alert that is shown for
// blacklisted extensions. This allows us to test which extensions the alert
// is showing, and also eliminates the UI component (since this is a unit
// test).
class MockExtensionErrorUI : public ExtensionErrorUI {
public:
explicit MockExtensionErrorUI(ExtensionErrorUI::Delegate* delegate);
~MockExtensionErrorUI() override;
// Wrappers around the similar methods in ExtensionErrorUI.
void CloseUI();
void Accept();
void Details();
ExtensionErrorUI::Delegate* delegate() { return delegate_; }
private:
// ExtensionErrorUI implementation.
bool ShowErrorInBubbleView() override;
void ShowExtensions() override;
void Close() override;
// Keep a copy of the delegate around for ourselves.
ExtensionErrorUI::Delegate* delegate_;
};
// We use this as a slight hack to get the created Error UI, if any. We should
// only ever have one (since this is a single-profile test), and this avoids
// the need for any kind of accessor to the ErrorController from
// ExtensionService.
MockExtensionErrorUI* g_error_ui = NULL;
MockExtensionErrorUI::MockExtensionErrorUI(
ExtensionErrorUI::Delegate* delegate)
: ExtensionErrorUI(delegate),
delegate_(delegate) {
// We should never make more than one of these in a test.
DCHECK(!g_error_ui);
g_error_ui = this;
}
MockExtensionErrorUI::~MockExtensionErrorUI() {
g_error_ui = NULL;
}
void MockExtensionErrorUI::CloseUI() {
BubbleViewDidClose();
}
void MockExtensionErrorUI::Accept() {
BubbleViewAcceptButtonPressed();
}
void MockExtensionErrorUI::Details() {
BubbleViewCancelButtonPressed();
}
bool MockExtensionErrorUI::ShowErrorInBubbleView() {
return true;
}
void MockExtensionErrorUI::ShowExtensions() {}
void MockExtensionErrorUI::Close() {
CloseUI();
}
ExtensionErrorUI* CreateMockUI(ExtensionErrorUI::Delegate* delegate) {
return new MockExtensionErrorUI(delegate);
}
// Builds and returns a simple extension.
scoped_refptr<const Extension> BuildExtension() {
return ExtensionBuilder()
.SetManifest(DictionaryBuilder().Set("name", "My Wonderful Extension")
.Set("version", "0.1.1.0")
.Set("manifest_version", 2)
.Build())
.Build();
}
} // namespace
class ExtensionErrorControllerUnitTest : public ExtensionServiceTestBase {
protected:
void SetUp() override;
// Add an extension to chrome, and mark it as blacklisted in the prefs.
testing::AssertionResult AddBlacklistedExtension(const Extension* extension);
// Return the ExtensionPrefs associated with the test.
ExtensionPrefs* GetPrefs();
Profile* profile() { return profile_.get(); }
};
void ExtensionErrorControllerUnitTest::SetUp() {
ExtensionServiceTestBase::SetUp();
// Make sure we use the mock UI instead of the real UI.
ExtensionErrorController::SetUICreateMethodForTesting(CreateMockUI);
// We don't want a first-run ExtensionService, since we ignore warnings
// for new profiles.
ExtensionServiceInitParams params = CreateDefaultInitParams();
params.is_first_run = false;
InitializeExtensionService(params);
}
testing::AssertionResult
ExtensionErrorControllerUnitTest::AddBlacklistedExtension(
const Extension* extension) {
GetPrefs()->SetExtensionBlacklisted(extension->id(), true);
service_->AddExtension(extension);
// Make sure the extension is added to the blacklisted set.
if (!ExtensionRegistry::Get(profile())->blacklisted_extensions()
.Contains(extension->id())) {
return testing::AssertionFailure()
<< "Failed to add blacklisted extension.";
}
return testing::AssertionSuccess();
}
ExtensionPrefs* ExtensionErrorControllerUnitTest::GetPrefs() {
return ExtensionPrefs::Get(profile());
}
// Test that closing the extension alert for blacklisted extensions counts
// as acknowledging them in the prefs.
TEST_F(ExtensionErrorControllerUnitTest, ClosingAcknowledgesBlacklisted) {
// Add a blacklisted extension.
scoped_refptr<const Extension> extension = BuildExtension();
ASSERT_TRUE(AddBlacklistedExtension(extension.get()));
service_->Init();
// Make sure that we created an error "ui" to warn about the blacklisted
// extension.
ASSERT_TRUE(g_error_ui);
ExtensionErrorUI::Delegate* delegate = g_error_ui->delegate();
ASSERT_TRUE(delegate);
// Make sure that the blacklisted extension is reported (and that no other
// extensions are).
const ExtensionSet& delegate_blacklisted_extensions =
delegate->GetBlacklistedExtensions();
EXPECT_EQ(1u, delegate_blacklisted_extensions.size());
EXPECT_TRUE(delegate_blacklisted_extensions.Contains(extension->id()));
// Close, and verify that the extension ids now acknowledged.
g_error_ui->CloseUI();
EXPECT_TRUE(GetPrefs()->IsBlacklistedExtensionAcknowledged(extension->id()));
// Verify we cleaned up after ourselves.
EXPECT_FALSE(g_error_ui);
}
// Test that clicking "accept" on the extension alert counts as acknowledging
// blacklisted extensions.
TEST_F(ExtensionErrorControllerUnitTest, AcceptingAcknowledgesBlacklisted) {
// Add a blacklisted extension.
scoped_refptr<const Extension> extension = BuildExtension();
ASSERT_TRUE(AddBlacklistedExtension(extension.get()));
service_->Init();
// Make sure that we created an error "ui" to warn about the blacklisted
// extension.
ASSERT_TRUE(g_error_ui);
// Accept, and verify that the extension ids now acknowledged.
g_error_ui->Accept();
EXPECT_TRUE(GetPrefs()->IsBlacklistedExtensionAcknowledged(extension->id()));
// Verify we cleaned up after ourselves.
EXPECT_FALSE(g_error_ui);
}
// Test that we don't warn for extensions which are blacklisted, but have
// already been acknowledged.
TEST_F(ExtensionErrorControllerUnitTest, DontWarnForAcknowledgedBlacklisted) {
scoped_refptr<const Extension> extension = BuildExtension();
ASSERT_TRUE(AddBlacklistedExtension(extension.get()));
GetPrefs()->AcknowledgeBlacklistedExtension(extension->id());
service_->Init();
// We should never have made an alert, because the extension should already
// be acknowledged.
ASSERT_FALSE(g_error_ui);
}
} // namespace extensions