1// Copyright 2014 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 5#include "base/memory/ref_counted.h" 6#include "chrome/browser/extensions/extension_error_controller.h" 7#include "chrome/browser/extensions/extension_error_ui.h" 8#include "chrome/browser/extensions/extension_service.h" 9#include "chrome/browser/extensions/extension_service_test_base.h" 10#include "chrome/browser/profiles/profile.h" 11#include "chrome/test/base/testing_profile.h" 12#include "extensions/browser/extension_prefs.h" 13#include "extensions/browser/extension_registry.h" 14#include "extensions/common/extension.h" 15#include "extensions/common/extension_builder.h" 16#include "extensions/common/value_builder.h" 17 18namespace extensions { 19 20namespace { 21 22// Create a mock for the UI component of the error alert that is shown for 23// blacklisted extensions. This allows us to test which extensions the alert 24// is showing, and also eliminates the UI component (since this is a unit 25// test). 26class MockExtensionErrorUI : public ExtensionErrorUI { 27 public: 28 explicit MockExtensionErrorUI(ExtensionErrorUI::Delegate* delegate); 29 virtual ~MockExtensionErrorUI(); 30 31 // Wrappers around the similar methods in ExtensionErrorUI. 32 void CloseUI(); 33 void Accept(); 34 void Details(); 35 36 ExtensionErrorUI::Delegate* delegate() { return delegate_; } 37 38 private: 39 // ExtensionErrorUI implementation. 40 virtual bool ShowErrorInBubbleView() OVERRIDE; 41 virtual void ShowExtensions() OVERRIDE; 42 virtual void Close() OVERRIDE; 43 44 // Keep a copy of the delegate around for ourselves. 45 ExtensionErrorUI::Delegate* delegate_; 46}; 47 48// We use this as a slight hack to get the created Error UI, if any. We should 49// only ever have one (since this is a single-profile test), and this avoids 50// the need for any kind of accessor to the ErrorController from 51// ExtensionService. 52MockExtensionErrorUI* g_error_ui = NULL; 53 54MockExtensionErrorUI::MockExtensionErrorUI( 55 ExtensionErrorUI::Delegate* delegate) 56 : ExtensionErrorUI(delegate), 57 delegate_(delegate) { 58 // We should never make more than one of these in a test. 59 DCHECK(!g_error_ui); 60 g_error_ui = this; 61} 62 63MockExtensionErrorUI::~MockExtensionErrorUI() { 64 g_error_ui = NULL; 65} 66 67void MockExtensionErrorUI::CloseUI() { 68 BubbleViewDidClose(); 69} 70 71void MockExtensionErrorUI::Accept() { 72 BubbleViewAcceptButtonPressed(); 73} 74 75void MockExtensionErrorUI::Details() { 76 BubbleViewCancelButtonPressed(); 77} 78 79bool MockExtensionErrorUI::ShowErrorInBubbleView() { 80 return true; 81} 82 83void MockExtensionErrorUI::ShowExtensions() {} 84 85void MockExtensionErrorUI::Close() { 86 CloseUI(); 87} 88 89ExtensionErrorUI* CreateMockUI(ExtensionErrorUI::Delegate* delegate) { 90 return new MockExtensionErrorUI(delegate); 91} 92 93// Builds and returns a simple extension. 94scoped_refptr<const Extension> BuildExtension() { 95 return ExtensionBuilder() 96 .SetManifest(DictionaryBuilder().Set("name", "My Wonderful Extension") 97 .Set("version", "0.1.1.0") 98 .Set("manifest_version", 2) 99 .Build()) 100 .Build(); 101} 102 103} // namespace 104 105class ExtensionErrorControllerUnitTest : public ExtensionServiceTestBase { 106 protected: 107 virtual void SetUp() OVERRIDE; 108 109 // Add an extension to chrome, and mark it as blacklisted in the prefs. 110 testing::AssertionResult AddBlacklistedExtension(const Extension* extension); 111 112 // Return the ExtensionPrefs associated with the test. 113 ExtensionPrefs* GetPrefs(); 114 115 Profile* profile() { return profile_.get(); } 116}; 117 118void ExtensionErrorControllerUnitTest::SetUp() { 119 ExtensionServiceTestBase::SetUp(); 120 // Make sure we use the mock UI instead of the real UI. 121 ExtensionErrorController::SetUICreateMethodForTesting(CreateMockUI); 122 123 // We don't want a first-run ExtensionService, since we ignore warnings 124 // for new profiles. 125 ExtensionServiceInitParams params = CreateDefaultInitParams(); 126 params.is_first_run = false; 127 InitializeExtensionService(params); 128} 129 130testing::AssertionResult 131ExtensionErrorControllerUnitTest::AddBlacklistedExtension( 132 const Extension* extension) { 133 GetPrefs()->SetExtensionBlacklisted(extension->id(), true); 134 service_->AddExtension(extension); 135 136 // Make sure the extension is added to the blacklisted set. 137 if (!ExtensionRegistry::Get(profile())->blacklisted_extensions() 138 .Contains(extension->id())) { 139 return testing::AssertionFailure() 140 << "Failed to add blacklisted extension."; 141 } 142 143 return testing::AssertionSuccess(); 144} 145 146ExtensionPrefs* ExtensionErrorControllerUnitTest::GetPrefs() { 147 return ExtensionPrefs::Get(profile()); 148} 149 150// Test that closing the extension alert for blacklisted extensions counts 151// as acknowledging them in the prefs. 152TEST_F(ExtensionErrorControllerUnitTest, ClosingAcknowledgesBlacklisted) { 153 // Add a blacklisted extension. 154 scoped_refptr<const Extension> extension = BuildExtension(); 155 ASSERT_TRUE(AddBlacklistedExtension(extension.get())); 156 157 service_->Init(); 158 159 // Make sure that we created an error "ui" to warn about the blacklisted 160 // extension. 161 ASSERT_TRUE(g_error_ui); 162 ExtensionErrorUI::Delegate* delegate = g_error_ui->delegate(); 163 ASSERT_TRUE(delegate); 164 165 // Make sure that the blacklisted extension is reported (and that no other 166 // extensions are). 167 const ExtensionSet& delegate_blacklisted_extensions = 168 delegate->GetBlacklistedExtensions(); 169 EXPECT_EQ(1u, delegate_blacklisted_extensions.size()); 170 EXPECT_TRUE(delegate_blacklisted_extensions.Contains(extension->id())); 171 172 // Close, and verify that the extension ids now acknowledged. 173 g_error_ui->CloseUI(); 174 EXPECT_TRUE(GetPrefs()->IsBlacklistedExtensionAcknowledged(extension->id())); 175 // Verify we cleaned up after ourselves. 176 EXPECT_FALSE(g_error_ui); 177} 178 179// Test that clicking "accept" on the extension alert counts as acknowledging 180// blacklisted extensions. 181TEST_F(ExtensionErrorControllerUnitTest, AcceptingAcknowledgesBlacklisted) { 182 // Add a blacklisted extension. 183 scoped_refptr<const Extension> extension = BuildExtension(); 184 ASSERT_TRUE(AddBlacklistedExtension(extension.get())); 185 186 service_->Init(); 187 188 // Make sure that we created an error "ui" to warn about the blacklisted 189 // extension. 190 ASSERT_TRUE(g_error_ui); 191 192 // Accept, and verify that the extension ids now acknowledged. 193 g_error_ui->Accept(); 194 EXPECT_TRUE(GetPrefs()->IsBlacklistedExtensionAcknowledged(extension->id())); 195 // Verify we cleaned up after ourselves. 196 EXPECT_FALSE(g_error_ui); 197} 198 199// Test that we don't warn for extensions which are blacklisted, but have 200// already been acknowledged. 201TEST_F(ExtensionErrorControllerUnitTest, DontWarnForAcknowledgedBlacklisted) { 202 scoped_refptr<const Extension> extension = BuildExtension(); 203 ASSERT_TRUE(AddBlacklistedExtension(extension.get())); 204 205 GetPrefs()->AcknowledgeBlacklistedExtension(extension->id()); 206 207 service_->Init(); 208 209 // We should never have made an alert, because the extension should already 210 // be acknowledged. 211 ASSERT_FALSE(g_error_ui); 212} 213 214} // namespace extensions 215