• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
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_service.h"
16 #include "chrome/browser/extensions/extension_test_message_listener.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/common/chrome_switches.h"
20 #include "content/public/browser/notification_service.h"
21 #include "content/public/common/url_constants.h"
22 #include "content/public/test/browser_test_utils.h"
23 #include "content/public/test/test_utils.h"
24 #include "extensions/browser/extension_host.h"
25 #include "extensions/browser/extension_prefs.h"
26 #include "extensions/browser/extension_system.h"
27 
28 namespace keys = extension_management_api_constants;
29 namespace util = extension_function_test_utils;
30 
31 namespace extensions {
32 
33 class ExtensionManagementApiBrowserTest : public ExtensionBrowserTest {
34  protected:
CrashEnabledExtension(const std::string & extension_id)35   bool CrashEnabledExtension(const std::string& extension_id) {
36     ExtensionHost* background_host =
37         ExtensionSystem::Get(browser()->profile())->
38             process_manager()->GetBackgroundHostForExtension(extension_id);
39     if (!background_host)
40       return false;
41     content::CrashTab(background_host->host_contents());
42     return true;
43   }
44 };
45 
46 // We test this here instead of in an ExtensionApiTest because normal extensions
47 // are not allowed to call the install function.
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,InstallEvent)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());
53 
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());
58 }
59 
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,LaunchApp)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());
71 }
72 
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,LaunchAppFromBackground)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());
81 }
82 
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,SelfUninstall)83 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,
84                        SelfUninstall) {
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());
91 }
92 
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,SelfUninstallNoPermissions)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());
101 }
102 
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,UninstallWithConfirmDialog)103 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,
104                        UninstallWithConfirmDialog) {
105   ExtensionService* service = ExtensionSystem::Get(browser()->profile())->
106       extension_service();
107 
108   // Install an extension.
109   const Extension* extension = InstallExtension(
110       test_data_dir_.AppendASCII("api_test/management/enabled_extension"), 1);
111   ASSERT_TRUE(extension);
112 
113   const std::string id = extension->id();
114 
115   scoped_refptr<Extension> empty_extension(
116       extension_function_test_utils::CreateEmptyExtension());
117   // Uninstall, then cancel via the confirm dialog.
118   scoped_refptr<ManagementUninstallFunction> uninstall_function(
119       new ManagementUninstallFunction());
120   uninstall_function->set_extension(empty_extension);
121   uninstall_function->set_user_gesture(true);
122   ManagementUninstallFunction::SetAutoConfirmForTest(false);
123 
124   EXPECT_TRUE(MatchPattern(
125       util::RunFunctionAndReturnError(
126           uninstall_function.get(),
127           base::StringPrintf("[\"%s\", {\"showConfirmDialog\": true}]",
128                              id.c_str()),
129           browser()),
130       keys::kUninstallCanceledError));
131 
132   // Make sure the extension wasn't uninstalled.
133   EXPECT_TRUE(service->GetExtensionById(id, false) != NULL);
134 
135   // Uninstall, then accept via the confirm dialog.
136   uninstall_function = new ManagementUninstallFunction();
137   uninstall_function->set_extension(empty_extension);
138   ManagementUninstallFunction::SetAutoConfirmForTest(true);
139   uninstall_function->set_user_gesture(true);
140   util::RunFunctionAndReturnSingleResult(
141       uninstall_function.get(),
142       base::StringPrintf("[\"%s\", {\"showConfirmDialog\": true}]", id.c_str()),
143       browser());
144 
145   // Make sure the extension was uninstalled.
146   EXPECT_TRUE(service->GetExtensionById(id, false) == NULL);
147 }
148 
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,CreateAppShortcutConfirmDialog)149 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,
150                        CreateAppShortcutConfirmDialog) {
151   const Extension* app = InstallExtension(
152       test_data_dir_.AppendASCII("api_test/management/packaged_app"), 1);
153   ASSERT_TRUE(app);
154 
155   const std::string app_id = app->id();
156 
157   scoped_refptr<ManagementCreateAppShortcutFunction> create_shortcut_function(
158       new ManagementCreateAppShortcutFunction());
159   create_shortcut_function->set_user_gesture(true);
160   ManagementCreateAppShortcutFunction::SetAutoConfirmForTest(true);
161   util::RunFunctionAndReturnSingleResult(
162       create_shortcut_function.get(),
163       base::StringPrintf("[\"%s\"]", app_id.c_str()),
164       browser());
165 
166   create_shortcut_function = new ManagementCreateAppShortcutFunction();
167   create_shortcut_function->set_user_gesture(true);
168   ManagementCreateAppShortcutFunction::SetAutoConfirmForTest(false);
169   EXPECT_TRUE(MatchPattern(
170       util::RunFunctionAndReturnError(
171           create_shortcut_function.get(),
172           base::StringPrintf("[\"%s\"]", app_id.c_str()),
173           browser()),
174       keys::kCreateShortcutCanceledError));
175 }
176 
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,GetAllIncludesTerminated)177 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,
178                        GetAllIncludesTerminated) {
179   // Load an extension with a background page, so that we know it has a process
180   // running.
181   ExtensionTestMessageListener listener("ready", false);
182   const Extension* extension = LoadExtension(
183       test_data_dir_.AppendASCII("management/install_event"));
184   ASSERT_TRUE(extension);
185   ASSERT_TRUE(listener.WaitUntilSatisfied());
186 
187   // The management API should list this extension.
188   scoped_refptr<ManagementGetAllFunction> function =
189       new ManagementGetAllFunction();
190   scoped_ptr<base::Value> result(util::RunFunctionAndReturnSingleResult(
191       function.get(), "[]", browser()));
192   base::ListValue* list;
193   ASSERT_TRUE(result->GetAsList(&list));
194   EXPECT_EQ(1U, list->GetSize());
195 
196   // And it should continue to do so even after it crashes.
197   ASSERT_TRUE(CrashEnabledExtension(extension->id()));
198 
199   function = new ManagementGetAllFunction();
200   result.reset(util::RunFunctionAndReturnSingleResult(
201       function.get(), "[]", browser()));
202   ASSERT_TRUE(result->GetAsList(&list));
203   EXPECT_EQ(1U, list->GetSize());
204 }
205 
206 class ExtensionManagementApiEscalationTest :
207     public ExtensionManagementApiBrowserTest {
208  protected:
209   // The id of the permissions escalation test extension we use.
210   static const char kId[];
211 
SetUpOnMainThread()212   virtual void SetUpOnMainThread() OVERRIDE {
213     EXPECT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
214     base::FilePath pem_path = test_data_dir_.
215         AppendASCII("permissions_increase").AppendASCII("permissions.pem");
216     base::FilePath path_v1 = PackExtensionWithOptions(
217         test_data_dir_.AppendASCII("permissions_increase").AppendASCII("v1"),
218         scoped_temp_dir_.path().AppendASCII("permissions1.crx"),
219         pem_path,
220         base::FilePath());
221     base::FilePath path_v2 = PackExtensionWithOptions(
222         test_data_dir_.AppendASCII("permissions_increase").AppendASCII("v2"),
223         scoped_temp_dir_.path().AppendASCII("permissions2.crx"),
224         pem_path,
225         base::FilePath());
226 
227     ExtensionService* service = ExtensionSystem::Get(browser()->profile())->
228         extension_service();
229 
230     // Install low-permission version of the extension.
231     ASSERT_TRUE(InstallExtension(path_v1, 1));
232     EXPECT_TRUE(service->GetExtensionById(kId, false) != NULL);
233 
234     // Update to a high-permission version - it should get disabled.
235     EXPECT_FALSE(UpdateExtension(kId, path_v2, -1));
236     EXPECT_TRUE(service->GetExtensionById(kId, false) == NULL);
237     EXPECT_TRUE(service->GetExtensionById(kId, true) != NULL);
238     EXPECT_TRUE(ExtensionPrefs::Get(browser()->profile())
239                     ->DidExtensionEscalatePermissions(kId));
240   }
241 
SetEnabled(bool enabled,bool user_gesture,const std::string & expected_error)242   void SetEnabled(bool enabled, bool user_gesture,
243                   const std::string& expected_error) {
244     scoped_refptr<ManagementSetEnabledFunction> function(
245         new ManagementSetEnabledFunction);
246     const char* enabled_string = enabled ? "true" : "false";
247     if (user_gesture)
248       function->set_user_gesture(true);
249     bool response = util::RunFunction(
250         function.get(),
251         base::StringPrintf("[\"%s\", %s]", kId, enabled_string),
252         browser(),
253         util::NONE);
254     if (expected_error.empty()) {
255       EXPECT_EQ(true, response);
256     } else {
257       EXPECT_TRUE(response == false);
258       EXPECT_EQ(expected_error, function->GetError());
259     }
260   }
261 
262 
263  private:
264   base::ScopedTempDir scoped_temp_dir_;
265 };
266 
267 const char ExtensionManagementApiEscalationTest::kId[] =
268     "pgdpcfcocojkjfbgpiianjngphoopgmo";
269 
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiEscalationTest,DisabledReason)270 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiEscalationTest,
271                        DisabledReason) {
272   scoped_refptr<ManagementGetFunction> function =
273       new ManagementGetFunction();
274   scoped_ptr<base::Value> result(util::RunFunctionAndReturnSingleResult(
275       function.get(),
276       base::StringPrintf("[\"%s\"]", kId),
277       browser()));
278   ASSERT_TRUE(result.get() != NULL);
279   ASSERT_TRUE(result->IsType(base::Value::TYPE_DICTIONARY));
280   base::DictionaryValue* dict =
281       static_cast<base::DictionaryValue*>(result.get());
282   std::string reason;
283   EXPECT_TRUE(dict->GetStringASCII(keys::kDisabledReasonKey, &reason));
284   EXPECT_EQ(reason, std::string(keys::kDisabledReasonPermissionsIncrease));
285 }
286 
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiEscalationTest,SetEnabled)287 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiEscalationTest,
288                        SetEnabled) {
289   // Expect an error about no gesture.
290   SetEnabled(true, false, keys::kGestureNeededForEscalationError);
291 
292   // Expect an error that user cancelled the dialog.
293   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
294       switches::kAppsGalleryInstallAutoConfirmForTests, "cancel");
295   SetEnabled(true, true, keys::kUserDidNotReEnableError);
296 
297   // This should succeed when user accepts dialog.  We must wait for the process
298   // to connect *and* for the channel to finish initializing before trying to
299   // crash it.  (NOTIFICATION_RENDERER_PROCESS_CREATED does not wait for the
300   // latter and can cause KillProcess to fail on Windows.)
301   content::WindowedNotificationObserver observer(
302       chrome::NOTIFICATION_EXTENSION_HOST_CREATED,
303       content::NotificationService::AllSources());
304   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
305       switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
306   SetEnabled(true, true, std::string());
307   observer.Wait();
308 
309   // Crash the extension. Mock a reload by disabling and then enabling. The
310   // extension should be reloaded and enabled.
311   ASSERT_TRUE(CrashEnabledExtension(kId));
312   SetEnabled(false, true, std::string());
313   SetEnabled(true, true, std::string());
314   const Extension* extension = ExtensionSystem::Get(browser()->profile())
315       ->extension_service()->GetExtensionById(kId, false);
316   EXPECT_TRUE(extension);
317 }
318 
319 }  // namespace extensions
320