Extensions cleanup: Merge IsSyncableApp+Extension, ShouldSyncApp+Extension
[chromium-blink-merge.git] / chrome / browser / extensions / extension_reenabler_unittest.cc
blob3c6f7c1819929120051bfaef79fd0d396c07af9c
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.
5 #include "base/run_loop.h"
6 #include "chrome/browser/extensions/extension_install_prompt.h"
7 #include "chrome/browser/extensions/extension_reenabler.h"
8 #include "chrome/browser/extensions/extension_service.h"
9 #include "chrome/browser/extensions/extension_service_test_base.h"
10 #include "chrome/browser/extensions/extension_system_factory.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/test/base/testing_profile.h"
13 #include "components/crx_file/id_util.h"
14 #include "extensions/browser/extension_dialog_auto_confirm.h"
15 #include "extensions/browser/extension_registry.h"
16 #include "extensions/browser/management_policy.h"
17 #include "extensions/browser/test_extensions_browser_client.h"
18 #include "extensions/common/extension.h"
19 #include "extensions/common/extension_builder.h"
20 #include "extensions/common/value_builder.h"
22 namespace extensions {
24 namespace {
26 // A simple provider that says all extensions must remain disabled.
27 class TestManagementProvider : public ManagementPolicy::Provider {
28 public:
29 TestManagementProvider() {}
30 ~TestManagementProvider() override {}
32 private:
33 // MananagementPolicy::Provider:
34 std::string GetDebugPolicyProviderName() const override { return "test"; }
35 bool MustRemainDisabled(const Extension* extension,
36 Extension::DisableReason* reason,
37 base::string16* error) const override {
38 return true;
41 DISALLOW_COPY_AND_ASSIGN(TestManagementProvider);
44 // A helper class for all the various callbacks associated with reenabling an
45 // extension. This class also helps store the results of the run.
46 class CallbackHelper {
47 public:
48 CallbackHelper() {}
49 ~CallbackHelper() {}
51 // Get a callback to run on the completion of the reenable process and reset
52 // |result_|.
53 ExtensionReenabler::Callback GetCallback() {
54 result_.reset();
55 return base::Bind(&CallbackHelper::OnComplete,
56 base::Unretained(this));
59 // Check if we have receved any result, and if it matches the expected one.
60 bool has_result() const { return result_.get() != nullptr; }
61 bool result_matches(ExtensionReenabler::ReenableResult expected) const {
62 return result_.get() && *result_ == expected;
65 // Create a test ExtensionInstallPrompt that will not display any UI (which
66 // causes unit tests to crash), but rather runs the given |quit_closure| (with
67 // the prompt still active|.
68 scoped_ptr<ExtensionInstallPrompt> CreateTestPrompt(
69 content::WebContents* web_contents,
70 const base::Closure& quit_closure) {
71 quit_closure_ = quit_closure;
72 scoped_ptr<ExtensionInstallPrompt> prompt(
73 new ExtensionInstallPrompt(web_contents));
74 prompt->set_callback_for_test(base::Bind(&CallbackHelper::OnShow,
75 base::Unretained(this)));
76 return prompt.Pass();
79 private:
80 // The callback to run once the reenable process finishes.
81 void OnComplete(ExtensionReenabler::ReenableResult result) {
82 result_.reset(new ExtensionReenabler::ReenableResult(result));
85 // The callback to run when a test ExtensionInstallPrompt is ready to show.
86 void OnShow(ExtensionInstallPromptShowParams* show_params,
87 ExtensionInstallPrompt::Delegate* delegate,
88 scoped_refptr<ExtensionInstallPrompt::Prompt> prompt) {
89 DCHECK(!quit_closure_.is_null());
90 quit_closure_.Run();
91 quit_closure_ = base::Closure();
94 // The closure to quit the currently-running loop; used with test
95 // ExtensionInstallPrompts.
96 base::Closure quit_closure_;
98 // The result of the reenable process, or null if the process hasn't finished.
99 scoped_ptr<ExtensionReenabler::ReenableResult> result_;
101 DISALLOW_COPY_AND_ASSIGN(CallbackHelper);
104 } // namespace
106 class ExtensionReenablerUnitTest : public ExtensionServiceTestBase {
107 public:
108 ExtensionReenablerUnitTest() {}
109 ~ExtensionReenablerUnitTest() override {}
111 private:
112 void SetUp() override;
113 void TearDown() override;
115 scoped_ptr<TestExtensionsBrowserClient> test_browser_client_;
117 DISALLOW_COPY_AND_ASSIGN(ExtensionReenablerUnitTest);
120 void ExtensionReenablerUnitTest::SetUp() {
121 ExtensionServiceTestBase::SetUp();
122 InitializeEmptyExtensionService();
123 // We need a TestExtensionsBrowserClient because the real one tries to
124 // implicitly convert any browser context to a (non-Testing)Profile.
125 test_browser_client_.reset(new TestExtensionsBrowserClient(profile()));
126 test_browser_client_->set_extension_system_factory(
127 ExtensionSystemFactory::GetInstance());
128 ExtensionsBrowserClient::Set(test_browser_client_.get());
131 void ExtensionReenablerUnitTest::TearDown() {
132 profile_.reset();
133 ExtensionsBrowserClient::Set(nullptr);
134 test_browser_client_.reset();
135 ExtensionServiceTestBase::TearDown();
138 // Test that the ExtensionReenabler reenables disabled extensions.
139 TEST_F(ExtensionReenablerUnitTest, TestReenablingDisabledExtension) {
140 // Create a simple extension and add it to the service.
141 scoped_refptr<const Extension> extension =
142 ExtensionBuilder().
143 SetManifest(DictionaryBuilder().Set("name", "test ext").
144 Set("version", "1.0").
145 Set("manifest_version", 2).
146 Set("description", "a test ext")).
147 SetID(crx_file::id_util::GenerateId("test ext")).
148 Build();
149 service()->AddExtension(extension.get());
150 EXPECT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
152 CallbackHelper callback_helper;
154 // Check that the ExtensionReenabler can re-enable disabled extensions.
156 // Disable the extension due to a permissions increase (the only type of
157 // disablement we handle with the ExtensionReenabler so far).
158 service()->DisableExtension(extension->id(),
159 Extension::DISABLE_PERMISSIONS_INCREASE);
160 // Sanity check that it's disabled.
161 EXPECT_TRUE(registry()->disabled_extensions().Contains(extension->id()));
163 // Automatically confirm install prompts.
164 ScopedTestDialogAutoConfirm auto_confirm(
165 ScopedTestDialogAutoConfirm::ACCEPT);
167 // Run the ExtensionReenabler.
168 scoped_ptr<ExtensionReenabler> extension_reenabler =
169 ExtensionReenabler::PromptForReenable(extension,
170 profile(),
171 nullptr, // No web contents.
172 GURL(), // No referrer.
173 callback_helper.GetCallback());
174 base::RunLoop().RunUntilIdle();
176 // The extension should be enabled.
177 EXPECT_TRUE(registry()->enabled_extensions().Contains(extension->id()));
178 EXPECT_TRUE(
179 callback_helper.result_matches(ExtensionReenabler::REENABLE_SUCCESS));
182 // Check that we don't re-enable extensions that must remain disabled, and
183 // that the re-enabler reports failure correctly.
185 ScopedTestDialogAutoConfirm auto_confirm(
186 ScopedTestDialogAutoConfirm::ACCEPT);
188 ManagementPolicy* management_policy =
189 ExtensionSystem::Get(browser_context())->management_policy();
190 ASSERT_TRUE(management_policy);
191 TestManagementProvider test_provider;
192 management_policy->RegisterProvider(&test_provider);
193 service()->DisableExtension(extension->id(),
194 Extension::DISABLE_PERMISSIONS_INCREASE);
196 scoped_ptr<ExtensionReenabler> extension_reenabler =
197 ExtensionReenabler::PromptForReenable(extension,
198 profile(),
199 nullptr, // No web contents.
200 GURL(), // No referrer.
201 callback_helper.GetCallback());
202 base::RunLoop().RunUntilIdle();
204 // The extension should be enabled.
205 EXPECT_TRUE(registry()->disabled_extensions().Contains(extension->id()));
206 EXPECT_TRUE(
207 callback_helper.result_matches(ExtensionReenabler::NOT_ALLOWED));
209 management_policy->UnregisterProvider(&test_provider);
212 // Check that canceling the re-enable prompt doesn't re-enable the extension.
214 // Disable it again, and try canceling the prompt.
215 service()->DisableExtension(extension->id(),
216 Extension::DISABLE_PERMISSIONS_INCREASE);
217 ScopedTestDialogAutoConfirm auto_confirm(
218 ScopedTestDialogAutoConfirm::CANCEL);
219 scoped_ptr<ExtensionReenabler> extension_reenabler =
220 ExtensionReenabler::PromptForReenable(extension,
221 profile(),
222 nullptr, // No web contents.
223 GURL(), // No referrer.
224 callback_helper.GetCallback());
225 base::RunLoop().RunUntilIdle();
227 // The extension should remain disabled.
228 EXPECT_TRUE(registry()->disabled_extensions().Contains(extension->id()));
229 EXPECT_TRUE(
230 callback_helper.result_matches(ExtensionReenabler::USER_CANCELED));
233 // Test that if the extension is re-enabled while the prompt is active, the
234 // prompt exits and reports success.
236 base::RunLoop run_loop;
237 scoped_ptr<ExtensionReenabler> extension_reenabler =
238 ExtensionReenabler::PromptForReenableWithPromptForTest(
239 extension,
240 profile(),
241 callback_helper.GetCallback(),
242 callback_helper.CreateTestPrompt(nullptr, run_loop.QuitClosure()));
243 run_loop.Run();
245 // We shouldn't have any result yet (the user hasn't confirmed or canceled).
246 EXPECT_FALSE(callback_helper.has_result());
248 // Reenable the extension. This should count as a success for reenabling.
249 service()->GrantPermissionsAndEnableExtension(extension.get());
250 EXPECT_TRUE(
251 callback_helper.result_matches(ExtensionReenabler::REENABLE_SUCCESS));
254 // Test that prematurely destroying the re-enable prompt doesn't crash and
255 // reports an "aborted" result.
257 // Disable again, and create another prompt.
258 service()->DisableExtension(extension->id(),
259 Extension::DISABLE_PERMISSIONS_INCREASE);
260 base::RunLoop run_loop;
261 scoped_ptr<ExtensionReenabler> extension_reenabler =
262 ExtensionReenabler::PromptForReenableWithPromptForTest(
263 extension,
264 profile(),
265 callback_helper.GetCallback(),
266 callback_helper.CreateTestPrompt(nullptr, run_loop.QuitClosure()));
267 run_loop.Run();
268 EXPECT_FALSE(callback_helper.has_result());
269 // Destroy the reenabler to simulate the owning context being shut down
270 // (e.g., the tab closing).
271 extension_reenabler.reset();
272 EXPECT_TRUE(
273 callback_helper.result_matches(ExtensionReenabler::ABORTED));
277 } // namespace extensions