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/command_line.h"
6 #include "base/files/file_path.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/stringprintf.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/extensions/api/management/management_api.h"
12 #include "chrome/browser/extensions/api/management/management_api_constants.h"
13 #include "chrome/browser/extensions/extension_browsertest.h"
14 #include "chrome/browser/extensions/extension_function_test_utils.h"
15 #include "chrome/browser/extensions/extension_host.h"
16 #include "chrome/browser/extensions/extension_service.h"
17 #include "chrome/browser/extensions/extension_system.h"
18 #include "chrome/browser/extensions/extension_test_message_listener.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/ui/browser.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "content/public/browser/notification_service.h"
23 #include "content/public/common/url_constants.h"
24 #include "content/public/test/test_utils.h"
26 namespace keys = extension_management_api_constants;
27 namespace util = extension_function_test_utils;
29 namespace extensions {
31 class ExtensionManagementApiBrowserTest : public ExtensionBrowserTest {
33 bool CrashEnabledExtension(const std::string& extension_id) {
34 content::WindowedNotificationObserver extension_crash_observer(
35 chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED,
36 content::NotificationService::AllSources());
37 ExtensionHost* background_host =
38 ExtensionSystem::Get(browser()->profile())->
39 process_manager()->GetBackgroundHostForExtension(extension_id);
42 background_host->host_contents()->GetController().LoadURL(
43 GURL(content::kChromeUICrashURL), content::Referrer(),
44 content::PAGE_TRANSITION_LINK, std::string());
45 extension_crash_observer.Wait();
50 // We test this here instead of in an ExtensionApiTest because normal extensions
51 // are not allowed to call the install function.
52 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest, InstallEvent) {
53 ExtensionTestMessageListener listener1("ready", false);
54 ASSERT_TRUE(LoadExtension(
55 test_data_dir_.AppendASCII("management/install_event")));
56 ASSERT_TRUE(listener1.WaitUntilSatisfied());
58 ExtensionTestMessageListener listener2("got_event", false);
59 ASSERT_TRUE(LoadExtension(
60 test_data_dir_.AppendASCII("api_test/management/enabled_extension")));
61 ASSERT_TRUE(listener2.WaitUntilSatisfied());
64 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest, LaunchApp) {
65 ExtensionTestMessageListener listener1("app_launched", false);
66 ExtensionTestMessageListener listener2("got_expected_error", false);
67 ASSERT_TRUE(LoadExtension(
68 test_data_dir_.AppendASCII("management/simple_extension")));
69 ASSERT_TRUE(LoadExtension(
70 test_data_dir_.AppendASCII("management/packaged_app")));
71 ASSERT_TRUE(LoadExtension(
72 test_data_dir_.AppendASCII("management/launch_app")));
73 ASSERT_TRUE(listener1.WaitUntilSatisfied());
74 ASSERT_TRUE(listener2.WaitUntilSatisfied());
77 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,
78 LaunchAppFromBackground) {
79 ExtensionTestMessageListener listener1("success", false);
80 ASSERT_TRUE(LoadExtension(
81 test_data_dir_.AppendASCII("management/packaged_app")));
82 ASSERT_TRUE(LoadExtension(
83 test_data_dir_.AppendASCII("management/launch_app_from_background")));
84 ASSERT_TRUE(listener1.WaitUntilSatisfied());
87 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,
89 ExtensionTestMessageListener listener1("success", false);
90 ASSERT_TRUE(LoadExtension(
91 test_data_dir_.AppendASCII("management/self_uninstall_helper")));
92 ASSERT_TRUE(LoadExtension(
93 test_data_dir_.AppendASCII("management/self_uninstall")));
94 ASSERT_TRUE(listener1.WaitUntilSatisfied());
97 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,
98 SelfUninstallNoPermissions) {
99 ExtensionTestMessageListener listener1("success", false);
100 ASSERT_TRUE(LoadExtension(
101 test_data_dir_.AppendASCII("management/self_uninstall_helper")));
102 ASSERT_TRUE(LoadExtension(
103 test_data_dir_.AppendASCII("management/self_uninstall_noperm")));
104 ASSERT_TRUE(listener1.WaitUntilSatisfied());
107 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,
108 UninstallWithConfirmDialog) {
109 ExtensionService* service = ExtensionSystem::Get(browser()->profile())->
112 // Install an extension.
113 const Extension* extension = InstallExtension(
114 test_data_dir_.AppendASCII("api_test/management/enabled_extension"), 1);
115 ASSERT_TRUE(extension);
117 const std::string id = extension->id();
119 // Uninstall, then cancel via the confirm dialog.
120 scoped_refptr<ManagementUninstallFunction> uninstall_function(
121 new ManagementUninstallFunction());
122 ManagementUninstallFunction::SetAutoConfirmForTest(false);
124 EXPECT_TRUE(MatchPattern(
125 util::RunFunctionAndReturnError(
126 uninstall_function.get(),
127 base::StringPrintf("[\"%s\", {\"showConfirmDialog\": true}]",
130 keys::kUninstallCanceledError));
132 // Make sure the extension wasn't uninstalled.
133 EXPECT_TRUE(service->GetExtensionById(id, false) != NULL);
135 // Uninstall, then accept via the confirm dialog.
136 uninstall_function = new ManagementUninstallFunction();
137 ManagementUninstallFunction::SetAutoConfirmForTest(true);
139 util::RunFunctionAndReturnSingleResult(
140 uninstall_function.get(),
141 base::StringPrintf("[\"%s\", {\"showConfirmDialog\": true}]", id.c_str()),
144 // Make sure the extension was uninstalled.
145 EXPECT_TRUE(service->GetExtensionById(id, false) == NULL);
148 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,
149 GetAllIncludesTerminated) {
150 // Load an extension with a background page, so that we know it has a process
152 ExtensionTestMessageListener listener("ready", false);
153 const Extension* extension = LoadExtension(
154 test_data_dir_.AppendASCII("management/install_event"));
155 ASSERT_TRUE(extension);
156 ASSERT_TRUE(listener.WaitUntilSatisfied());
158 // The management API should list this extension.
159 scoped_refptr<ManagementGetAllFunction> function =
160 new ManagementGetAllFunction();
161 scoped_ptr<base::Value> result(util::RunFunctionAndReturnSingleResult(
162 function.get(), "[]", browser()));
163 base::ListValue* list;
164 ASSERT_TRUE(result->GetAsList(&list));
165 EXPECT_EQ(1U, list->GetSize());
167 // And it should continue to do so even after it crashes.
168 ASSERT_TRUE(CrashEnabledExtension(extension->id()));
170 function = new ManagementGetAllFunction();
171 result.reset(util::RunFunctionAndReturnSingleResult(
172 function.get(), "[]", browser()));
173 ASSERT_TRUE(result->GetAsList(&list));
174 EXPECT_EQ(1U, list->GetSize());
177 class ExtensionManagementApiEscalationTest :
178 public ExtensionManagementApiBrowserTest {
180 // The id of the permissions escalation test extension we use.
181 static const char kId[];
183 virtual void SetUpOnMainThread() OVERRIDE {
184 EXPECT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
185 base::FilePath pem_path = test_data_dir_.
186 AppendASCII("permissions_increase").AppendASCII("permissions.pem");
187 base::FilePath path_v1 = PackExtensionWithOptions(
188 test_data_dir_.AppendASCII("permissions_increase").AppendASCII("v1"),
189 scoped_temp_dir_.path().AppendASCII("permissions1.crx"),
192 base::FilePath path_v2 = PackExtensionWithOptions(
193 test_data_dir_.AppendASCII("permissions_increase").AppendASCII("v2"),
194 scoped_temp_dir_.path().AppendASCII("permissions2.crx"),
198 ExtensionService* service = ExtensionSystem::Get(browser()->profile())->
201 // Install low-permission version of the extension.
202 ASSERT_TRUE(InstallExtension(path_v1, 1));
203 EXPECT_TRUE(service->GetExtensionById(kId, false) != NULL);
205 // Update to a high-permission version - it should get disabled.
206 EXPECT_FALSE(UpdateExtension(kId, path_v2, -1));
207 EXPECT_TRUE(service->GetExtensionById(kId, false) == NULL);
208 EXPECT_TRUE(service->GetExtensionById(kId, true) != NULL);
210 service->extension_prefs()->DidExtensionEscalatePermissions(kId));
213 void SetEnabled(bool enabled, bool user_gesture,
214 const std::string& expected_error) {
215 scoped_refptr<ManagementSetEnabledFunction> function(
216 new ManagementSetEnabledFunction);
217 const char* enabled_string = enabled ? "true" : "false";
219 function->set_user_gesture(true);
220 bool response = util::RunFunction(
222 base::StringPrintf("[\"%s\", %s]", kId, enabled_string),
225 if (expected_error.empty()) {
226 EXPECT_EQ(true, response);
228 EXPECT_TRUE(response == false);
229 EXPECT_EQ(expected_error, function->GetError());
235 base::ScopedTempDir scoped_temp_dir_;
238 const char ExtensionManagementApiEscalationTest::kId[] =
239 "pgdpcfcocojkjfbgpiianjngphoopgmo";
241 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiEscalationTest,
243 scoped_refptr<ManagementGetFunction> function =
244 new ManagementGetFunction();
245 scoped_ptr<base::Value> result(util::RunFunctionAndReturnSingleResult(
247 base::StringPrintf("[\"%s\"]", kId),
249 ASSERT_TRUE(result.get() != NULL);
250 ASSERT_TRUE(result->IsType(base::Value::TYPE_DICTIONARY));
251 base::DictionaryValue* dict =
252 static_cast<base::DictionaryValue*>(result.get());
254 EXPECT_TRUE(dict->GetStringASCII(keys::kDisabledReasonKey, &reason));
255 EXPECT_EQ(reason, std::string(keys::kDisabledReasonPermissionsIncrease));
258 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiEscalationTest,
260 // Expect an error about no gesture.
261 SetEnabled(true, false, keys::kGestureNeededForEscalationError);
263 // Expect an error that user cancelled the dialog.
264 CommandLine::ForCurrentProcess()->AppendSwitchASCII(
265 switches::kAppsGalleryInstallAutoConfirmForTests, "cancel");
266 SetEnabled(true, true, keys::kUserDidNotReEnableError);
268 // This should succeed when user accepts dialog.
269 CommandLine::ForCurrentProcess()->AppendSwitchASCII(
270 switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
271 SetEnabled(true, true, std::string());
273 // Crash the extension. Mock a reload by disabling and then enabling. The
274 // extension should be reloaded and enabled.
275 ASSERT_TRUE(CrashEnabledExtension(kId));
276 SetEnabled(false, true, std::string());
277 SetEnabled(true, true, std::string());
278 const Extension* extension = ExtensionSystem::Get(browser()->profile())
279 ->extension_service()->GetExtensionById(kId, false);
280 EXPECT_TRUE(extension);
283 } // namespace extensions