- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / management / management_api_browsertest.cc
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_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"
25
26 namespace keys = extension_management_api_constants;
27 namespace util = extension_function_test_utils;
28
29 namespace extensions {
30
31 class ExtensionManagementApiBrowserTest : public ExtensionBrowserTest {
32  protected:
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);
40     if (!background_host)
41       return false;
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();
46     return true;
47   }
48 };
49
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());
57
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());
62 }
63
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());
75 }
76
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());
85 }
86
87 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,
88                        SelfUninstall) {
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());
95 }
96
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());
105 }
106
107 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiBrowserTest,
108                        UninstallWithConfirmDialog) {
109   ExtensionService* service = ExtensionSystem::Get(browser()->profile())->
110       extension_service();
111
112   // Install an extension.
113   const Extension* extension = InstallExtension(
114       test_data_dir_.AppendASCII("api_test/management/enabled_extension"), 1);
115   ASSERT_TRUE(extension);
116
117   const std::string id = extension->id();
118
119   // Uninstall, then cancel via the confirm dialog.
120   scoped_refptr<ManagementUninstallFunction> uninstall_function(
121       new ManagementUninstallFunction());
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   ManagementUninstallFunction::SetAutoConfirmForTest(true);
138
139   util::RunFunctionAndReturnSingleResult(
140       uninstall_function.get(),
141       base::StringPrintf("[\"%s\", {\"showConfirmDialog\": true}]", id.c_str()),
142       browser());
143
144   // Make sure the extension was uninstalled.
145   EXPECT_TRUE(service->GetExtensionById(id, false) == NULL);
146 }
147
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
151   // running.
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());
157
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());
166
167   // And it should continue to do so even after it crashes.
168   ASSERT_TRUE(CrashEnabledExtension(extension->id()));
169
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());
175 }
176
177 class ExtensionManagementApiEscalationTest :
178     public ExtensionManagementApiBrowserTest {
179  protected:
180   // The id of the permissions escalation test extension we use.
181   static const char kId[];
182
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"),
190         pem_path,
191         base::FilePath());
192     base::FilePath path_v2 = PackExtensionWithOptions(
193         test_data_dir_.AppendASCII("permissions_increase").AppendASCII("v2"),
194         scoped_temp_dir_.path().AppendASCII("permissions2.crx"),
195         pem_path,
196         base::FilePath());
197
198     ExtensionService* service = ExtensionSystem::Get(browser()->profile())->
199         extension_service();
200
201     // Install low-permission version of the extension.
202     ASSERT_TRUE(InstallExtension(path_v1, 1));
203     EXPECT_TRUE(service->GetExtensionById(kId, false) != NULL);
204
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);
209     EXPECT_TRUE(
210         service->extension_prefs()->DidExtensionEscalatePermissions(kId));
211   }
212
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";
218     if (user_gesture)
219       function->set_user_gesture(true);
220     bool response = util::RunFunction(
221         function.get(),
222         base::StringPrintf("[\"%s\", %s]", kId, enabled_string),
223         browser(),
224         util::NONE);
225     if (expected_error.empty()) {
226       EXPECT_EQ(true, response);
227     } else {
228       EXPECT_TRUE(response == false);
229       EXPECT_EQ(expected_error, function->GetError());
230     }
231   }
232
233
234  private:
235   base::ScopedTempDir scoped_temp_dir_;
236 };
237
238 const char ExtensionManagementApiEscalationTest::kId[] =
239     "pgdpcfcocojkjfbgpiianjngphoopgmo";
240
241 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiEscalationTest,
242                        DisabledReason) {
243   scoped_refptr<ManagementGetFunction> function =
244       new ManagementGetFunction();
245   scoped_ptr<base::Value> result(util::RunFunctionAndReturnSingleResult(
246       function.get(),
247       base::StringPrintf("[\"%s\"]", kId),
248       browser()));
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());
253   std::string reason;
254   EXPECT_TRUE(dict->GetStringASCII(keys::kDisabledReasonKey, &reason));
255   EXPECT_EQ(reason, std::string(keys::kDisabledReasonPermissionsIncrease));
256 }
257
258 IN_PROC_BROWSER_TEST_F(ExtensionManagementApiEscalationTest,
259                        SetEnabled) {
260   // Expect an error about no gesture.
261   SetEnabled(true, false, keys::kGestureNeededForEscalationError);
262
263   // Expect an error that user cancelled the dialog.
264   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
265       switches::kAppsGalleryInstallAutoConfirmForTests, "cancel");
266   SetEnabled(true, true, keys::kUserDidNotReEnableError);
267
268   // This should succeed when user accepts dialog.
269   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
270       switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
271   SetEnabled(true, true, std::string());
272
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);
281 }
282
283 }  // namespace extensions