1 // Copyright (c) 2012 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/files/file_path.h"
6 #include "base/files/scoped_temp_dir.h"
7 #include "base/strings/string_util.h"
8 #include "base/strings/stringprintf.h"
9 #include "chrome/browser/extensions/extension_browsertest.h"
10 #include "chrome/browser/extensions/extension_function_test_utils.h"
11 #include "chrome/browser/extensions/extension_install_prompt.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "content/public/browser/notification_service.h"
16 #include "content/public/common/url_constants.h"
17 #include "content/public/test/browser_test_utils.h"
18 #include "content/public/test/test_utils.h"
19 #include "extensions/browser/api/management/management_api.h"
20 #include "extensions/browser/api/management/management_api_constants.h"
21 #include "extensions/browser/extension_host.h"
22 #include "extensions/browser/extension_prefs.h"
23 #include "extensions/browser/extension_system.h"
24 #include "extensions/browser/notification_types.h"
25 #include "extensions/common/test_util.h"
26 #include "extensions/test/extension_test_message_listener.h"
28 namespace keys = extension_management_api_constants;
29 namespace util = extension_function_test_utils;
31 namespace extensions {
33 class ExtensionManagementApiBrowserTest : public ExtensionBrowserTest {
35 bool CrashEnabledExtension(const std::string& extension_id) {
36 ExtensionHost* background_host =
37 ProcessManager::Get(browser()->profile())
38 ->GetBackgroundHostForExtension(extension_id);
41 content::CrashTab(background_host->host_contents());
46 // We test this here instead of in an ExtensionApiTest because normal extensions
47 // are not allowed to call the install function.
48 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest, InstallEvent) {
49 ExtensionTestMessageListener listener1("ready", false);
50 ASSERT_TRUE(LoadExtension(
51 test_data_dir_.AppendASCII("management/install_event")));
52 ASSERT_TRUE(listener1.WaitUntilSatisfied());
54 ExtensionTestMessageListener listener2("got_event", false);
55 ASSERT_TRUE(LoadExtension(
56 test_data_dir_.AppendASCII("api_test/management/enabled_extension")));
57 ASSERT_TRUE(listener2.WaitUntilSatisfied());
60 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest, LaunchApp) {
61 ExtensionTestMessageListener listener1("app_launched", false);
62 ExtensionTestMessageListener listener2("got_expected_error", false);
63 ASSERT_TRUE(LoadExtension(
64 test_data_dir_.AppendASCII("management/simple_extension")));
65 ASSERT_TRUE(LoadExtension(
66 test_data_dir_.AppendASCII("management/packaged_app")));
67 ASSERT_TRUE(LoadExtension(
68 test_data_dir_.AppendASCII("management/launch_app")));
69 ASSERT_TRUE(listener1.WaitUntilSatisfied());
70 ASSERT_TRUE(listener2.WaitUntilSatisfied());
73 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,
74 LaunchAppFromBackground) {
75 ExtensionTestMessageListener listener1("success", false);
76 ASSERT_TRUE(LoadExtension(
77 test_data_dir_.AppendASCII("management/packaged_app")));
78 ASSERT_TRUE(LoadExtension(
79 test_data_dir_.AppendASCII("management/launch_app_from_background")));
80 ASSERT_TRUE(listener1.WaitUntilSatisfied());
83 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,
85 ExtensionTestMessageListener listener1("success", false);
86 ASSERT_TRUE(LoadExtension(
87 test_data_dir_.AppendASCII("management/self_uninstall_helper")));
88 ASSERT_TRUE(LoadExtension(
89 test_data_dir_.AppendASCII("management/self_uninstall")));
90 ASSERT_TRUE(listener1.WaitUntilSatisfied());
93 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,
94 SelfUninstallNoPermissions) {
95 ExtensionTestMessageListener listener1("success", false);
96 ASSERT_TRUE(LoadExtension(
97 test_data_dir_.AppendASCII("management/self_uninstall_helper")));
98 ASSERT_TRUE(LoadExtension(
99 test_data_dir_.AppendASCII("management/self_uninstall_noperm")));
100 ASSERT_TRUE(listener1.WaitUntilSatisfied());
103 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,
104 GetSelfNoPermissions) {
105 ExtensionTestMessageListener listener1("success", false);
106 ASSERT_TRUE(LoadExtension(
107 test_data_dir_.AppendASCII("management/get_self")));
108 ASSERT_TRUE(listener1.WaitUntilSatisfied());
111 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,
112 UninstallWithConfirmDialog) {
113 ExtensionService* service = ExtensionSystem::Get(browser()->profile())->
116 // Install an extension.
117 const Extension* extension = InstallExtension(
118 test_data_dir_.AppendASCII("api_test/management/enabled_extension"), 1);
119 ASSERT_TRUE(extension);
121 const std::string id = extension->id();
123 scoped_refptr<Extension> empty_extension(test_util::CreateEmptyExtension());
124 // Uninstall, then cancel via the confirm dialog.
125 scoped_refptr<ManagementUninstallFunction> uninstall_function(
126 new ManagementUninstallFunction());
127 uninstall_function->set_extension(empty_extension.get());
128 uninstall_function->set_user_gesture(true);
129 ManagementUninstallFunction::SetAutoConfirmForTest(false);
131 EXPECT_TRUE(MatchPattern(
132 util::RunFunctionAndReturnError(
133 uninstall_function.get(),
134 base::StringPrintf("[\"%s\", {\"showConfirmDialog\": true}]",
137 keys::kUninstallCanceledError));
139 // Make sure the extension wasn't uninstalled.
140 EXPECT_TRUE(service->GetExtensionById(id, false) != NULL);
142 // Uninstall, then accept via the confirm dialog.
143 uninstall_function = new ManagementUninstallFunction();
144 uninstall_function->set_extension(empty_extension.get());
145 ManagementUninstallFunction::SetAutoConfirmForTest(true);
146 uninstall_function->set_user_gesture(true);
147 util::RunFunctionAndReturnSingleResult(
148 uninstall_function.get(),
149 base::StringPrintf("[\"%s\", {\"showConfirmDialog\": true}]", id.c_str()),
152 // Make sure the extension was uninstalled.
153 EXPECT_TRUE(service->GetExtensionById(id, false) == NULL);
156 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,
157 CreateAppShortcutConfirmDialog) {
158 const Extension* app = InstallExtension(
159 test_data_dir_.AppendASCII("api_test/management/packaged_app"), 1);
162 const std::string app_id = app->id();
164 scoped_refptr<ManagementCreateAppShortcutFunction> create_shortcut_function(
165 new ManagementCreateAppShortcutFunction());
166 create_shortcut_function->set_user_gesture(true);
167 ManagementCreateAppShortcutFunction::SetAutoConfirmForTest(true);
168 util::RunFunctionAndReturnSingleResult(
169 create_shortcut_function.get(),
170 base::StringPrintf("[\"%s\"]", app_id.c_str()),
173 create_shortcut_function = new ManagementCreateAppShortcutFunction();
174 create_shortcut_function->set_user_gesture(true);
175 ManagementCreateAppShortcutFunction::SetAutoConfirmForTest(false);
176 EXPECT_TRUE(MatchPattern(
177 util::RunFunctionAndReturnError(
178 create_shortcut_function.get(),
179 base::StringPrintf("[\"%s\"]", app_id.c_str()),
181 keys::kCreateShortcutCanceledError));
184 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,
185 GetAllIncludesTerminated) {
186 // Load an extension with a background page, so that we know it has a process
188 ExtensionTestMessageListener listener("ready", false);
189 const Extension* extension = LoadExtension(
190 test_data_dir_.AppendASCII("management/install_event"));
191 ASSERT_TRUE(extension);
192 ASSERT_TRUE(listener.WaitUntilSatisfied());
194 // The management API should list this extension.
195 scoped_refptr<ManagementGetAllFunction> function =
196 new ManagementGetAllFunction();
197 scoped_ptr<base::Value> result(util::RunFunctionAndReturnSingleResult(
198 function.get(), "[]", browser()));
199 base::ListValue* list;
200 ASSERT_TRUE(result->GetAsList(&list));
201 EXPECT_EQ(1U, list->GetSize());
203 // And it should continue to do so even after it crashes.
204 ASSERT_TRUE(CrashEnabledExtension(extension->id()));
206 function = new ManagementGetAllFunction();
207 result.reset(util::RunFunctionAndReturnSingleResult(
208 function.get(), "[]", browser()));
209 ASSERT_TRUE(result->GetAsList(&list));
210 EXPECT_EQ(1U, list->GetSize());
213 class ExtensionManagementApiEscalationTest :
214 public ExtensionManagementApiBrowserTest {
216 // The id of the permissions escalation test extension we use.
217 static const char kId[];
219 void SetUpOnMainThread() override {
220 EXPECT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
221 base::FilePath pem_path = test_data_dir_.
222 AppendASCII("permissions_increase").AppendASCII("permissions.pem");
223 base::FilePath path_v1 = PackExtensionWithOptions(
224 test_data_dir_.AppendASCII("permissions_increase").AppendASCII("v1"),
225 scoped_temp_dir_.path().AppendASCII("permissions1.crx"),
228 base::FilePath path_v2 = PackExtensionWithOptions(
229 test_data_dir_.AppendASCII("permissions_increase").AppendASCII("v2"),
230 scoped_temp_dir_.path().AppendASCII("permissions2.crx"),
234 ExtensionService* service = ExtensionSystem::Get(browser()->profile())->
237 // Install low-permission version of the extension.
238 ASSERT_TRUE(InstallExtension(path_v1, 1));
239 EXPECT_TRUE(service->GetExtensionById(kId, false) != NULL);
241 // Update to a high-permission version - it should get disabled.
242 EXPECT_FALSE(UpdateExtension(kId, path_v2, -1));
243 EXPECT_TRUE(service->GetExtensionById(kId, false) == NULL);
244 EXPECT_TRUE(service->GetExtensionById(kId, true) != NULL);
245 EXPECT_TRUE(ExtensionPrefs::Get(browser()->profile())
246 ->DidExtensionEscalatePermissions(kId));
249 void SetEnabled(bool enabled, bool user_gesture,
250 const std::string& expected_error) {
251 scoped_refptr<ManagementSetEnabledFunction> function(
252 new ManagementSetEnabledFunction);
253 const char* const enabled_string = enabled ? "true" : "false";
255 function->set_user_gesture(true);
256 bool response = util::RunFunction(
258 base::StringPrintf("[\"%s\", %s]", kId, enabled_string),
261 if (expected_error.empty()) {
262 EXPECT_EQ(true, response);
264 EXPECT_TRUE(response == false);
265 EXPECT_EQ(expected_error, function->GetError());
271 base::ScopedTempDir scoped_temp_dir_;
274 const char ExtensionManagementApiEscalationTest::kId[] =
275 "pgdpcfcocojkjfbgpiianjngphoopgmo";
277 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiEscalationTest,
279 scoped_refptr<ManagementGetFunction> function =
280 new ManagementGetFunction();
281 scoped_ptr<base::Value> result(util::RunFunctionAndReturnSingleResult(
283 base::StringPrintf("[\"%s\"]", kId),
285 ASSERT_TRUE(result.get() != NULL);
286 ASSERT_TRUE(result->IsType(base::Value::TYPE_DICTIONARY));
287 base::DictionaryValue* dict =
288 static_cast<base::DictionaryValue*>(result.get());
290 EXPECT_TRUE(dict->GetStringASCII(keys::kDisabledReasonKey, &reason));
291 EXPECT_EQ(reason, std::string(keys::kDisabledReasonPermissionsIncrease));
294 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiEscalationTest,
296 // Expect an error about no gesture.
297 SetEnabled(true, false, keys::kGestureNeededForEscalationError);
299 // Expect an error that user cancelled the dialog.
300 ExtensionInstallPrompt::g_auto_confirm_for_tests =
301 ExtensionInstallPrompt::CANCEL;
302 SetEnabled(true, true, keys::kUserDidNotReEnableError);
304 // This should succeed when user accepts dialog. We must wait for the process
305 // to connect *and* for the channel to finish initializing before trying to
306 // crash it. (NOTIFICATION_RENDERER_PROCESS_CREATED does not wait for the
307 // latter and can cause KillProcess to fail on Windows.)
308 content::WindowedNotificationObserver observer(
309 extensions::NOTIFICATION_EXTENSION_HOST_CREATED,
310 content::NotificationService::AllSources());
311 ExtensionInstallPrompt::g_auto_confirm_for_tests =
312 ExtensionInstallPrompt::ACCEPT;
313 SetEnabled(true, true, std::string());
316 // Crash the extension. Mock a reload by disabling and then enabling. The
317 // extension should be reloaded and enabled.
318 ASSERT_TRUE(CrashEnabledExtension(kId));
319 SetEnabled(false, true, std::string());
320 SetEnabled(true, true, std::string());
321 const Extension* extension = ExtensionSystem::Get(browser()->profile())
322 ->extension_service()->GetExtensionById(kId, false);
323 EXPECT_TRUE(extension);
326 } // namespace extensions