blob: d2715bdd7ff97a6f76fc29dd19160940b082bbdd [file] [log] [blame]
[email protected]a44657202012-01-09 05:48:311// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]cfc6cca2011-12-01 02:30:062// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]a6db6122012-09-03 06:00:235#include "base/bind.h"
[email protected]939532d02012-08-31 23:37:336#include "base/test/test_timeouts.h"
7#include "base/threading/platform_thread.h"
[email protected]b3c019b2012-08-28 02:43:488#include "base/utf_string_conversions.h"
[email protected]ad687a72012-06-08 06:03:119#include "chrome/app/chrome_command_ids.h"
[email protected]605fb8102012-05-04 01:36:5510#include "chrome/browser/automation/automation_util.h"
[email protected]70019152012-12-19 11:44:1911#include "chrome/browser/devtools/devtools_window.h"
[email protected]ddf42162012-11-06 21:14:5512#include "chrome/browser/extensions/api/permissions/permissions_api.h"
[email protected]78acaf6d2013-01-10 11:14:3713#include "chrome/browser/extensions/app_restore_service_factory.h"
[email protected]758b0b702013-01-10 12:19:3314#include "chrome/browser/extensions/app_restore_service.h"
[email protected]a6db6122012-09-03 06:00:2315#include "chrome/browser/extensions/extension_browsertest.h"
[email protected]28c3eeb2012-10-15 05:47:5316#include "chrome/browser/extensions/extension_prefs.h"
17#include "chrome/browser/extensions/extension_service.h"
18#include "chrome/browser/extensions/extension_system.h"
[email protected]259771102012-05-31 16:52:2019#include "chrome/browser/extensions/extension_test_message_listener.h"
20#include "chrome/browser/extensions/platform_app_browsertest_util.h"
[email protected]a6db6122012-09-03 06:00:2321#include "chrome/browser/extensions/platform_app_launcher.h"
[email protected]259771102012-05-31 16:52:2022#include "chrome/browser/extensions/shell_window_registry.h"
[email protected]8c484b742012-11-29 06:05:3623#include "chrome/browser/prefs/pref_service.h"
[email protected]e85cc642012-10-24 06:14:2324#include "chrome/browser/tab_contents/render_view_context_menu.h"
[email protected]cfc6cca2011-12-01 02:30:0625#include "chrome/browser/ui/browser.h"
[email protected]52877dbc62012-06-29 22:22:0326#include "chrome/browser/ui/browser_tabstrip.h"
[email protected]a5a0be02012-07-18 05:51:5427#include "chrome/browser/ui/extensions/application_launch.h"
[email protected]1b1989f52012-12-03 08:33:5428#include "chrome/browser/ui/extensions/native_app_window.h"
[email protected]d72d3a62012-05-10 03:45:0829#include "chrome/browser/ui/extensions/shell_window.h"
[email protected]d2b16572013-01-03 00:41:5830#include "chrome/browser/ui/web_contents_modal_dialog_manager.h"
[email protected]5b1a04b42012-06-15 00:41:4431#include "chrome/common/chrome_notification_types.h"
[email protected]4d007b312012-10-17 03:00:4832#include "chrome/common/url_constants.h"
[email protected]cfc6cca2011-12-01 02:30:0633#include "chrome/test/base/ui_test_utils.h"
[email protected]98f66112012-12-25 12:59:3634#include "content/public/browser/devtools_agent_host.h"
[email protected]fb29e6cf2012-07-12 21:27:2035#include "content/public/browser/render_process_host.h"
[email protected]a6db6122012-09-03 06:00:2336#include "content/public/browser/web_intents_dispatcher.h"
[email protected]28c3eeb2012-10-15 05:47:5337#include "content/public/test/test_utils.h"
[email protected]a6db6122012-09-03 06:00:2338#include "googleurl/src/gurl.h"
39#include "webkit/glue/web_intent_data.h"
[email protected]cfc6cca2011-12-01 02:30:0640
[email protected]bb81f382012-01-03 22:45:4441using content::WebContents;
[email protected]d9ede582012-08-14 19:21:3842
43namespace extensions {
[email protected]31bdbfef2012-05-22 19:59:1544
[email protected]375003a2011-12-13 02:53:2145namespace {
[email protected]85d3d5e2012-08-31 21:19:1746
[email protected]375003a2011-12-13 02:53:2147// Non-abstract RenderViewContextMenu class.
48class PlatformAppContextMenu : public RenderViewContextMenu {
49 public:
[email protected]bb81f382012-01-03 22:45:4450 PlatformAppContextMenu(WebContents* web_contents,
[email protected]35be7ec2012-02-12 20:42:5151 const content::ContextMenuParams& params)
[email protected]bb81f382012-01-03 22:45:4452 : RenderViewContextMenu(web_contents, params) {}
[email protected]375003a2011-12-13 02:53:2153
[email protected]ad687a72012-06-08 06:03:1154 bool HasCommandWithId(int command_id) {
55 return menu_model_.GetIndexOfCommandId(command_id) != -1;
56 }
57
[email protected]375003a2011-12-13 02:53:2158 protected:
[email protected]85d3d5e2012-08-31 21:19:1759 // RenderViewContextMenu implementation.
60 virtual bool GetAcceleratorForCommandId(
61 int command_id,
62 ui::Accelerator* accelerator) OVERRIDE {
[email protected]375003a2011-12-13 02:53:2163 return false;
64 }
[email protected]85d3d5e2012-08-31 21:19:1765 virtual void PlatformInit() OVERRIDE {}
66 virtual void PlatformCancel() OVERRIDE {}
[email protected]375003a2011-12-13 02:53:2167};
68
[email protected]a6db6122012-09-03 06:00:2369// State holder for the LaunchReply test. This provides an WebIntentsDispatcher
70// that will, when used to launch a Web Intent, will return its reply via this
71// class. The result may then be waited on via WaitUntilReply().
72class LaunchReplyHandler {
73 public:
74 explicit LaunchReplyHandler(webkit_glue::WebIntentData& data)
75 : data_(data),
76 replied_(false),
77 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
78 intents_dispatcher_ = content::WebIntentsDispatcher::Create(data);
79 intents_dispatcher_->RegisterReplyNotification(base::Bind(
80 &LaunchReplyHandler::OnReply, weak_ptr_factory_.GetWeakPtr()));
81 }
82
83 content::WebIntentsDispatcher* intents_dispatcher() {
84 return intents_dispatcher_;
85 }
86
87 // Waits until a reply to this Web Intent is provided via the
88 // WebIntentsDispatcher.
89 bool WaitUntilReply() {
90 if (replied_)
91 return true;
92 waiting_ = true;
93 content::RunMessageLoop();
94 waiting_ = false;
95 return replied_;
96 }
97
98 private:
99 void OnReply(webkit_glue::WebIntentReplyType reply) {
100 // Note that the ReplyNotification registered on WebIntentsDispatcher does
101 // not include the result data: this is reserved for the source page (which
102 // we don't care about).
103 replied_ = true;
104 if (waiting_)
105 MessageLoopForUI::current()->Quit();
106 }
107
108 webkit_glue::WebIntentData data_;
109 bool replied_;
110 bool waiting_;
111 content::WebIntentsDispatcher* intents_dispatcher_;
112 base::WeakPtrFactory<LaunchReplyHandler> weak_ptr_factory_;
113};
114
[email protected]4d007b312012-10-17 03:00:48115// This class keeps track of tabs as they are added to the browser. It will be
116// "done" (i.e. won't block on Wait()) once |observations| tabs have been added.
117class TabsAddedNotificationObserver
118 : public content::WindowedNotificationObserver {
119 public:
120 explicit TabsAddedNotificationObserver(size_t observations)
121 : content::WindowedNotificationObserver(
122 chrome::NOTIFICATION_TAB_ADDED,
123 content::NotificationService::AllSources()),
124 observations_(observations) {
125 }
126
127 virtual void Observe(int type,
128 const content::NotificationSource& source,
129 const content::NotificationDetails& details) OVERRIDE {
130 observed_tabs_.push_back(
131 content::Details<WebContents>(details).ptr());
132 if (observed_tabs_.size() == observations_)
133 content::WindowedNotificationObserver::Observe(type, source, details);
134 }
135
136 const std::vector<content::WebContents*>& tabs() { return observed_tabs_; }
137
138 private:
139 size_t observations_;
140 std::vector<content::WebContents*> observed_tabs_;
141
142 DISALLOW_COPY_AND_ASSIGN(TabsAddedNotificationObserver);
143};
144
[email protected]85d3d5e2012-08-31 21:19:17145const char kTestFilePath[] = "platform_apps/launch_files/test.txt";
146
[email protected]375003a2011-12-13 02:53:21147} // namespace
148
[email protected]eb4bcac2012-06-27 01:32:08149// Tests that CreateShellWindow doesn't crash if you close it straight away.
150// LauncherPlatformAppBrowserTest relies on this behaviour, but is only run for
151// ash, so we test that it works here.
152IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, CreateAndCloseShellWindow) {
153 const Extension* extension = LoadAndLaunchPlatformApp("minimal");
154 ShellWindow* window = CreateShellWindow(extension);
155 CloseShellWindow(window);
156}
157
[email protected]dc37b002012-04-23 23:02:26158// Tests that platform apps received the "launch" event when launched.
159IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, OnLaunchedEvent) {
160 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch")) << message_;
[email protected]cfc6cca2011-12-01 02:30:06161}
[email protected]375003a2011-12-13 02:53:21162
[email protected]a6db6122012-09-03 06:00:23163// Tests that platform apps can reply to "launch" events that contain a Web
164// Intent. This test does not test the mechanics of invoking a Web Intent
165// from a source page, and short-circuits to LaunchPlatformAppWithWebIntent.
166IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchReply) {
167 FilePath path = test_data_dir_.AppendASCII("platform_apps/launch_reply");
168 const extensions::Extension* extension = LoadExtension(path);
169 ASSERT_TRUE(extension) << "Failed to load extension.";
170
171 webkit_glue::WebIntentData data(
172 UTF8ToUTF16("http://webintents.org/view"),
173 UTF8ToUTF16("text/plain"),
174 UTF8ToUTF16("irrelevant unserialized string data"));
175 LaunchReplyHandler handler(data);
176
177 // Navigate to a boring page: we don't care what it is, but we require some
178 // source WebContents to launch the Web Intent "from".
179 ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
180 WebContents* web_contents = chrome::GetActiveWebContents(browser());
181 ASSERT_TRUE(web_contents);
182
183 extensions::LaunchPlatformAppWithWebIntent(
184 browser()->profile(),
185 extension,
186 handler.intents_dispatcher(),
187 web_contents);
188
189 ASSERT_TRUE(handler.WaitUntilReply());
190}
191
[email protected]567230b2012-08-21 21:11:44192// Tests that platform apps cannot use certain disabled window properties, but
193// can override them and then use them.
194IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisabledWindowProperties) {
195 ASSERT_TRUE(RunPlatformAppTest("platform_apps/disabled_window_properties"))
196 << message_;
197}
198
[email protected]edd7ed692012-02-08 02:50:03199IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, EmptyContextMenu) {
[email protected]d9d02762012-12-04 05:18:58200 ExtensionTestMessageListener launched_listener("Launched", false);
[email protected]31bdbfef2012-05-22 19:59:15201 LoadAndLaunchPlatformApp("minimal");
[email protected]dc37b002012-04-23 23:02:26202
[email protected]d9d02762012-12-04 05:18:58203 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
204
[email protected]375003a2011-12-13 02:53:21205 // The empty app doesn't add any context menu items, so its menu should
[email protected]0cfacd82012-02-09 01:55:33206 // only include the developer tools.
[email protected]d72d3a62012-05-10 03:45:08207 WebContents* web_contents = GetFirstShellWindowWebContents();
[email protected]a44657202012-01-09 05:48:31208 ASSERT_TRUE(web_contents);
[email protected]375003a2011-12-13 02:53:21209 WebKit::WebContextMenuData data;
[email protected]35be7ec2012-02-12 20:42:51210 content::ContextMenuParams params(data);
[email protected]85d3d5e2012-08-31 21:19:17211 scoped_ptr<PlatformAppContextMenu> menu;
212 menu.reset(new PlatformAppContextMenu(web_contents, params));
[email protected]375003a2011-12-13 02:53:21213 menu->Init();
[email protected]ad687a72012-06-08 06:03:11214 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
[email protected]65992d52012-09-19 23:05:31215 ASSERT_TRUE(
216 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
[email protected]671c9702012-09-27 07:51:19217 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
[email protected]ad687a72012-06-08 06:03:11218 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
219 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
[email protected]375003a2011-12-13 02:53:21220}
221
[email protected]edd7ed692012-02-08 02:50:03222IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenu) {
[email protected]d9d02762012-12-04 05:18:58223 ExtensionTestMessageListener launched_listener("Launched", false);
[email protected]375003a2011-12-13 02:53:21224 LoadAndLaunchPlatformApp("context_menu");
225
[email protected]d9d02762012-12-04 05:18:58226 // Wait for the extension to tell us it's initialized its context menus and
227 // launched a window.
228 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
229
[email protected]271d01c2012-08-27 23:48:05230 // The context_menu app has two context menu items. These, along with a
[email protected]0cfacd82012-02-09 01:55:33231 // separator and the developer tools, is all that should be in the menu.
[email protected]d72d3a62012-05-10 03:45:08232 WebContents* web_contents = GetFirstShellWindowWebContents();
[email protected]a44657202012-01-09 05:48:31233 ASSERT_TRUE(web_contents);
[email protected]375003a2011-12-13 02:53:21234 WebKit::WebContextMenuData data;
[email protected]35be7ec2012-02-12 20:42:51235 content::ContextMenuParams params(data);
[email protected]85d3d5e2012-08-31 21:19:17236 scoped_ptr<PlatformAppContextMenu> menu;
237 menu.reset(new PlatformAppContextMenu(web_contents, params));
[email protected]375003a2011-12-13 02:53:21238 menu->Init();
[email protected]ad687a72012-06-08 06:03:11239 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
[email protected]271d01c2012-08-27 23:48:05240 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST + 1));
[email protected]ad687a72012-06-08 06:03:11241 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
[email protected]65992d52012-09-19 23:05:31242 ASSERT_TRUE(
243 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
[email protected]671c9702012-09-27 07:51:19244 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
[email protected]ad687a72012-06-08 06:03:11245 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
246 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
[email protected]b3c019b2012-08-28 02:43:48247 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
248}
249
[email protected]65992d52012-09-19 23:05:31250IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, InstalledAppWithContextMenu) {
[email protected]d9d02762012-12-04 05:18:58251 ExtensionTestMessageListener launched_listener("Launched", false);
[email protected]65992d52012-09-19 23:05:31252 InstallAndLaunchPlatformApp("context_menu");
253
[email protected]d9d02762012-12-04 05:18:58254 // Wait for the extension to tell us it's initialized its context menus and
255 // launched a window.
256 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
257
[email protected]65992d52012-09-19 23:05:31258 // The context_menu app has two context menu items. For an installed app
259 // these are all that should be in the menu.
260 WebContents* web_contents = GetFirstShellWindowWebContents();
261 ASSERT_TRUE(web_contents);
262 WebKit::WebContextMenuData data;
263 content::ContextMenuParams params(data);
264 scoped_ptr<PlatformAppContextMenu> menu;
265 menu.reset(new PlatformAppContextMenu(web_contents, params));
266 menu->Init();
267 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
268 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST + 1));
269 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
270 ASSERT_FALSE(
271 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
[email protected]671c9702012-09-27 07:51:19272 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
[email protected]65992d52012-09-19 23:05:31273 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
274 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
275 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
276}
277
[email protected]b3c019b2012-08-28 02:43:48278IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenuTextField) {
[email protected]d9d02762012-12-04 05:18:58279 ExtensionTestMessageListener launched_listener("Launched", false);
[email protected]b3c019b2012-08-28 02:43:48280 LoadAndLaunchPlatformApp("context_menu");
281
[email protected]d9d02762012-12-04 05:18:58282 // Wait for the extension to tell us it's initialized its context menus and
283 // launched a window.
284 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
285
[email protected]b3c019b2012-08-28 02:43:48286 // The context_menu app has one context menu item. This, along with a
287 // separator and the developer tools, is all that should be in the menu.
288 WebContents* web_contents = GetFirstShellWindowWebContents();
289 ASSERT_TRUE(web_contents);
290 WebKit::WebContextMenuData data;
291 content::ContextMenuParams params(data);
292 params.is_editable = true;
[email protected]85d3d5e2012-08-31 21:19:17293 scoped_ptr<PlatformAppContextMenu> menu;
294 menu.reset(new PlatformAppContextMenu(web_contents, params));
[email protected]b3c019b2012-08-28 02:43:48295 menu->Init();
296 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
297 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
[email protected]65992d52012-09-19 23:05:31298 ASSERT_TRUE(
299 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
[email protected]671c9702012-09-27 07:51:19300 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
[email protected]b3c019b2012-08-28 02:43:48301 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
302 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_COPY));
303 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
304 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
305}
306
307IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenuSelection) {
[email protected]d9d02762012-12-04 05:18:58308 ExtensionTestMessageListener launched_listener("Launched", false);
[email protected]b3c019b2012-08-28 02:43:48309 LoadAndLaunchPlatformApp("context_menu");
310
[email protected]d9d02762012-12-04 05:18:58311 // Wait for the extension to tell us it's initialized its context menus and
312 // launched a window.
313 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
314
[email protected]b3c019b2012-08-28 02:43:48315 // The context_menu app has one context menu item. This, along with a
316 // separator and the developer tools, is all that should be in the menu.
317 WebContents* web_contents = GetFirstShellWindowWebContents();
318 ASSERT_TRUE(web_contents);
319 WebKit::WebContextMenuData data;
320 content::ContextMenuParams params(data);
321 params.selection_text = ASCIIToUTF16("Hello World");
[email protected]85d3d5e2012-08-31 21:19:17322 scoped_ptr<PlatformAppContextMenu> menu;
323 menu.reset(new PlatformAppContextMenu(web_contents, params));
[email protected]b3c019b2012-08-28 02:43:48324 menu->Init();
325 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
326 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
[email protected]65992d52012-09-19 23:05:31327 ASSERT_TRUE(
328 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
[email protected]671c9702012-09-27 07:51:19329 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
[email protected]b3c019b2012-08-28 02:43:48330 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
331 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_COPY));
332 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
333 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
[email protected]375003a2011-12-13 02:53:21334}
[email protected]5f000f272012-01-19 05:25:08335
[email protected]dc83c582012-08-17 02:18:14336IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenuClicked) {
[email protected]d9d02762012-12-04 05:18:58337 ExtensionTestMessageListener launched_listener("Launched", false);
[email protected]dc83c582012-08-17 02:18:14338 LoadAndLaunchPlatformApp("context_menu_click");
339
[email protected]d9d02762012-12-04 05:18:58340 // Wait for the extension to tell us it's initialized its context menus and
341 // launched a window.
342 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
343
[email protected]dc83c582012-08-17 02:18:14344 // Test that the menu item shows up
345 WebContents* web_contents = GetFirstShellWindowWebContents();
346 ASSERT_TRUE(web_contents);
347 WebKit::WebContextMenuData data;
348 content::ContextMenuParams params(data);
349 params.page_url = GURL("http://foo.bar");
[email protected]85d3d5e2012-08-31 21:19:17350 scoped_ptr<PlatformAppContextMenu> menu;
351 menu.reset(new PlatformAppContextMenu(web_contents, params));
[email protected]dc83c582012-08-17 02:18:14352 menu->Init();
353 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
354
355 // Execute the menu item
356 ExtensionTestMessageListener onclicked_listener("onClicked fired for id1",
357 false);
358 menu->ExecuteCommand(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST);
359
360 ASSERT_TRUE(onclicked_listener.WaitUntilSatisfied());
361}
362
[email protected]edd7ed692012-02-08 02:50:03363IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisallowNavigation) {
[email protected]4d007b312012-10-17 03:00:48364 TabsAddedNotificationObserver observer(2);
365
[email protected]dc37b002012-04-23 23:02:26366 ASSERT_TRUE(StartTestServer());
[email protected]d9d02762012-12-04 05:18:58367 ASSERT_TRUE(RunPlatformAppTest("platform_apps/navigation")) << message_;
[email protected]4d007b312012-10-17 03:00:48368
369 observer.Wait();
370 ASSERT_EQ(2U, observer.tabs().size());
371 EXPECT_EQ(std::string(chrome::kExtensionInvalidRequestURL),
372 observer.tabs()[0]->GetURL().spec());
373 EXPECT_EQ("http://chromium.org/",
374 observer.tabs()[1]->GetURL().spec());
[email protected]5f000f272012-01-19 05:25:08375}
[email protected]863e6472012-01-24 19:33:58376
[email protected]40eefd52012-10-04 22:54:22377IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Iframes) {
[email protected]fd3238af2012-05-22 18:55:30378 ASSERT_TRUE(StartTestServer());
379 ASSERT_TRUE(RunPlatformAppTest("platform_apps/iframes")) << message_;
380}
381
[email protected]2aac7ff2012-01-25 18:05:11382// Tests that localStorage and WebSQL are disabled for platform apps.
[email protected]edd7ed692012-02-08 02:50:03383IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisallowStorage) {
[email protected]2aac7ff2012-01-25 18:05:11384 ASSERT_TRUE(RunPlatformAppTest("platform_apps/storage")) << message_;
385}
[email protected]6a5a2e52012-03-22 03:21:12386
[email protected]c0cecd1f2012-04-05 16:50:12387IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Restrictions) {
388 ASSERT_TRUE(RunPlatformAppTest("platform_apps/restrictions")) << message_;
389}
390
[email protected]f0233ff2012-07-20 20:14:50391// Tests that platform apps can use the chrome.app.window.* API.
[email protected]4ebed74dd2012-12-20 18:39:26392// Flaky, http://crbug.com/167097 .
393IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DISABLED_WindowsApi) {
[email protected]6a5a2e52012-03-22 03:21:12394 ASSERT_TRUE(RunPlatformAppTest("platform_apps/windows_api")) << message_;
395}
[email protected]605fb8102012-05-04 01:36:55396
[email protected]1df22042012-08-30 19:48:55397// Tests that extensions can't use platform-app-only APIs.
398IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, PlatformAppsOnly) {
399 ASSERT_TRUE(RunExtensionTestIgnoreManifestWarnings(
400 "platform_apps/apps_only")) << message_;
401}
402
[email protected]605fb8102012-05-04 01:36:55403// Tests that platform apps have isolated storage by default.
404IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Isolation) {
405 ASSERT_TRUE(StartTestServer());
406
407 // Load a (non-app) page under the "localhost" origin that sets a cookie.
408 GURL set_cookie_url = test_server()->GetURL(
409 "files/extensions/platform_apps/isolation/set_cookie.html");
410 GURL::Replacements replace_host;
411 std::string host_str("localhost"); // Must stay in scope with replace_host.
412 replace_host.SetHostStr(host_str);
413 set_cookie_url = set_cookie_url.ReplaceComponents(replace_host);
414
415 ui_test_utils::NavigateToURLWithDisposition(
416 browser(), set_cookie_url,
417 CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
418
419 // Make sure the cookie is set.
420 int cookie_size;
421 std::string cookie_value;
422 automation_util::GetCookies(
423 set_cookie_url,
[email protected]52877dbc62012-06-29 22:22:03424 chrome::GetWebContentsAt(browser(), 0),
[email protected]605fb8102012-05-04 01:36:55425 &cookie_size,
426 &cookie_value);
427 ASSERT_EQ("testCookie=1", cookie_value);
428
429 // Let the platform app request the same URL, and make sure that it doesn't
430 // see the cookie.
431 ASSERT_TRUE(RunPlatformAppTest("platform_apps/isolation")) << message_;
432}
[email protected]31bdbfef2012-05-22 19:59:15433
434IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ExtensionWindowingApis) {
435 // Initially there should be just the one browser window visible to the
436 // extensions API.
437 const Extension* extension = LoadExtension(
438 test_data_dir_.AppendASCII("common/background_page"));
439 ASSERT_EQ(1U, RunGetWindowsFunctionForExtension(extension));
440
441 // And no shell windows.
442 ASSERT_EQ(0U, GetShellWindowCount());
443
444 // Launch a platform app that shows a window.
[email protected]d9d02762012-12-04 05:18:58445 ExtensionTestMessageListener launched_listener("Launched", false);
[email protected]ad5bb8a92012-06-07 03:55:58446 LoadAndLaunchPlatformApp("minimal");
[email protected]d9d02762012-12-04 05:18:58447 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
[email protected]31bdbfef2012-05-22 19:59:15448 ASSERT_EQ(1U, GetShellWindowCount());
449 ShellWindowRegistry::ShellWindowSet shell_windows =
450 ShellWindowRegistry::Get(browser()->profile())->shell_windows();
451 int shell_window_id = (*shell_windows.begin())->session_id().id();
452
453 // But it's not visible to the extensions API, it still thinks there's just
454 // one browser window.
455 ASSERT_EQ(1U, RunGetWindowsFunctionForExtension(extension));
456 // It can't look it up by ID either
457 ASSERT_FALSE(RunGetWindowFunctionForExtension(shell_window_id, extension));
458
459 // The app can also only see one window (its own).
[email protected]ad5bb8a92012-06-07 03:55:58460 // TODO(jeremya): add an extension function to get a shell window by ID, and
461 // to get a list of all the shell windows, so we can test this.
[email protected]31bdbfef2012-05-22 19:59:15462
463 // Launch another platform app that also shows a window.
[email protected]d9d02762012-12-04 05:18:58464 ExtensionTestMessageListener launched_listener2("Launched", false);
[email protected]ad5bb8a92012-06-07 03:55:58465 LoadAndLaunchPlatformApp("context_menu");
[email protected]d9d02762012-12-04 05:18:58466 ASSERT_TRUE(launched_listener2.WaitUntilSatisfied());
[email protected]31bdbfef2012-05-22 19:59:15467
468 // There are two total shell windows, but each app can only see its own.
469 ASSERT_EQ(2U, GetShellWindowCount());
[email protected]ad5bb8a92012-06-07 03:55:58470 // TODO(jeremya): as above, this requires more extension functions.
[email protected]31bdbfef2012-05-22 19:59:15471}
[email protected]12e540452012-05-26 07:09:36472
[email protected]a2ece522012-10-16 03:41:10473// ChromeOS does not support passing arguments on the command line, so the tests
474// that rely on this functionality are disabled.
[email protected]12e540452012-05-26 07:09:36475#if !defined(OS_CHROMEOS)
476// Tests that command line parameters get passed through to platform apps
477// via launchData correctly when launching with a file.
[email protected]7d0cbb62012-11-22 04:41:07478// TODO(benwells/jeremya): tests need a way to specify a handler ID.
[email protected]12e540452012-05-26 07:09:36479IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithFile) {
[email protected]85d3d5e2012-08-31 21:19:17480 SetCommandLineArg(kTestFilePath);
[email protected]12e540452012-05-26 07:09:36481 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_file"))
482 << message_;
483}
484
[email protected]a5a0be02012-07-18 05:51:54485// Tests that relative paths can be passed through to the platform app.
486// This test doesn't use the normal test infrastructure as it needs to open
487// the application differently to all other platform app tests, by setting
488// the application_launch::LaunchParams.current_directory field.
489IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithRelativeFile) {
490 // Setup the command line
491 ClearCommandLineArgs();
492 CommandLine* command_line = CommandLine::ForCurrentProcess();
[email protected]85d3d5e2012-08-31 21:19:17493 FilePath relative_test_doc = FilePath::FromUTF8Unsafe(kTestFilePath);
[email protected]a5a0be02012-07-18 05:51:54494 relative_test_doc = relative_test_doc.NormalizePathSeparators();
495 command_line->AppendArgPath(relative_test_doc);
496
497 // Load the extension
498 ResultCatcher catcher;
[email protected]d9ede582012-08-14 19:21:38499 const Extension* extension = LoadExtension(
[email protected]a5a0be02012-07-18 05:51:54500 test_data_dir_.AppendASCII("platform_apps/launch_file"));
501 ASSERT_TRUE(extension);
502
503 // Run the test
504 application_launch::LaunchParams params(browser()->profile(), extension,
505 extension_misc::LAUNCH_NONE,
506 NEW_WINDOW);
507 params.command_line = CommandLine::ForCurrentProcess();
508 params.current_directory = test_data_dir_;
509 application_launch::OpenApplication(params);
510
511 if (!catcher.GetNextResult()) {
512 message_ = catcher.message();
513 ASSERT_TRUE(0);
514 }
515}
516
[email protected]12e540452012-05-26 07:09:36517// Tests that no launch data is sent through if the file is of the wrong MIME
518// type.
519IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithWrongType) {
[email protected]85d3d5e2012-08-31 21:19:17520 SetCommandLineArg(kTestFilePath);
[email protected]12e540452012-05-26 07:09:36521 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_wrong_type"))
522 << message_;
523}
524
525// Tests that no launch data is sent through if the platform app does not
526// provide an intent.
527IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithNoIntent) {
[email protected]85d3d5e2012-08-31 21:19:17528 SetCommandLineArg(kTestFilePath);
[email protected]12e540452012-05-26 07:09:36529 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_no_intent"))
530 << message_;
531}
532
533// Tests that no launch data is sent through if the file MIME type cannot
534// be read.
535IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchNoType) {
536 SetCommandLineArg("platform_apps/launch_files/test.unknownextension");
537 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_invalid"))
538 << message_;
539}
540
541// Tests that no launch data is sent through if the file does not exist.
542IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchNoFile) {
543 SetCommandLineArg("platform_apps/launch_files/doesnotexist.txt");
544 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_invalid"))
545 << message_;
546}
547
548// Tests that no launch data is sent through if the argument is a directory.
549IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithDirectory) {
550 SetCommandLineArg("platform_apps/launch_files");
551 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_invalid"))
552 << message_;
553}
554
555// Tests that no launch data is sent through if there are no arguments passed
556// on the command line
557IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithNothing) {
558 ClearCommandLineArgs();
559 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_nothing"))
560 << message_;
561}
[email protected]ffc7b4d2012-06-08 00:05:32562
563// Test that platform apps can use the chrome.fileSystem.getDisplayPath
564// function to get the native file system path of a file they are launched with.
565IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, GetDisplayPath) {
[email protected]85d3d5e2012-08-31 21:19:17566 SetCommandLineArg(kTestFilePath);
[email protected]ffc7b4d2012-06-08 00:05:32567 ASSERT_TRUE(RunPlatformAppTest("platform_apps/get_display_path"))
568 << message_;
569}
570
[email protected]12e540452012-05-26 07:09:36571#endif // defined(OS_CHROMEOS)
[email protected]5b1a04b42012-06-15 00:41:44572
573IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, OpenLink) {
574 ASSERT_TRUE(StartTestServer());
[email protected]a7fe9112012-07-20 02:34:45575 content::WindowedNotificationObserver observer(
[email protected]5b1a04b42012-06-15 00:41:44576 chrome::NOTIFICATION_TAB_ADDED,
577 content::Source<content::WebContentsDelegate>(browser()));
578 LoadAndLaunchPlatformApp("open_link");
579 observer.Wait();
580 ASSERT_EQ(2, browser()->tab_count());
581}
[email protected]d9ede582012-08-14 19:21:38582
[email protected]3a8e61942012-08-23 01:46:45583IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MutationEventsDisabled) {
584 ASSERT_TRUE(RunPlatformAppTest("platform_apps/mutation_events")) << message_;
585}
586
[email protected]939532d02012-08-31 23:37:33587// Test that windows created with an id will remember and restore their
588// geometry when opening new windows.
[email protected]69080832012-11-20 20:31:47589// Originally disabled due to flakiness (see http://crbug.com/155459)
590// but now because a regression breaks the test (http://crbug.com/160343).
[email protected]19a0f75d2012-11-29 02:28:31591#if defined(TOOLKIT_GTK)
[email protected]329c4e92012-11-09 06:04:24592#define MAYBE_ShellWindowRestorePosition DISABLED_ShellWindowRestorePosition
[email protected]19a0f75d2012-11-29 02:28:31593#else
594#define MAYBE_ShellWindowRestorePosition ShellWindowRestorePosition
595#endif
[email protected]9d53c1c2012-10-18 00:49:54596IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
[email protected]329c4e92012-11-09 06:04:24597 MAYBE_ShellWindowRestorePosition) {
[email protected]939532d02012-08-31 23:37:33598 ExtensionTestMessageListener page2_listener("WaitForPage2", true);
[email protected]939532d02012-08-31 23:37:33599 ExtensionTestMessageListener done_listener("Done1", false);
600 ExtensionTestMessageListener done2_listener("Done2", false);
[email protected]939532d02012-08-31 23:37:33601
602 ASSERT_TRUE(LoadAndLaunchPlatformApp("geometry"));
603
604 // Wait for the app to be launched (although this is mostly to have a
605 // message to reply to to let the script know it should create its second
606 // window.
607 ASSERT_TRUE(page2_listener.WaitUntilSatisfied());
608
609 // Wait for the first window to verify its geometry was correctly set
610 // from the default* attributes passed to the create function.
611 ASSERT_TRUE(done_listener.WaitUntilSatisfied());
612
613 // Programatically move and resize the window.
614 ShellWindow* window = GetFirstShellWindow();
615 ASSERT_TRUE(window);
616 gfx::Rect bounds(137, 143, 203, 187);
617 window->GetBaseWindow()->SetBounds(bounds);
618
619#if defined(TOOLKIT_GTK)
620 // TODO(mek): On GTK we have to wait for a roundtrip to the X server before
621 // a resize actually happens:
622 // "if you call gtk_window_resize() then immediately call
623 // gtk_window_get_size(), the size won't have taken effect yet. After the
624 // window manager processes the resize request, GTK+ receives notification
625 // that the size has changed via a configure event, and the size of the
626 // window gets updated."
627 // Because of this we have to wait for an unknown time for the resize to
628 // actually take effect. So wait some time or until the resize got
629 // handled.
630 base::TimeTicks end_time = base::TimeTicks::Now() +
631 TestTimeouts::action_timeout();
632 while (base::TimeTicks::Now() < end_time &&
633 bounds != window->GetBaseWindow()->GetBounds()) {
634 content::RunAllPendingInMessageLoop();
635 }
636
637 // In the GTK ShellWindow implementation there also is a delay between
[email protected]99d8f092012-11-28 04:42:43638 // getting the correct bounds and it calling SaveWindowPosition, so call a
[email protected]939532d02012-08-31 23:37:33639 // method explicitly to make sure the value was stored.
[email protected]99d8f092012-11-28 04:42:43640 window->OnNativeWindowChanged();
[email protected]939532d02012-08-31 23:37:33641#endif // defined(TOOLKIT_GTK)
642
643 // Make sure the window was properly moved&resized.
644 ASSERT_EQ(bounds, window->GetBaseWindow()->GetBounds());
645
646 // Tell javascript to open a second window.
647 page2_listener.Reply("continue");
648
649 // Wait for javascript to verify that the second window got the updated
650 // coordinates, ignoring the default coordinates passed to the create method.
651 ASSERT_TRUE(done2_listener.WaitUntilSatisfied());
[email protected]939532d02012-08-31 23:37:33652}
[email protected]939532d02012-08-31 23:37:33653
[email protected]28c3eeb2012-10-15 05:47:53654// Tests that a running app is recorded in the preferences as such.
655IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, RunningAppsAreRecorded) {
656 content::WindowedNotificationObserver extension_suspended(
657 chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
658 content::NotificationService::AllSources());
659
660 const Extension* extension = LoadExtension(
661 test_data_dir_.AppendASCII("platform_apps/restart_test"));
662 ASSERT_TRUE(extension);
663 ExtensionService* extension_service =
664 ExtensionSystem::Get(browser()->profile())->extension_service();
665 ExtensionPrefs* extension_prefs = extension_service->extension_prefs();
666
667 // App is running.
668 ASSERT_TRUE(extension_prefs->IsExtensionRunning(extension->id()));
669
670 // Wait for the extension to get suspended.
671 extension_suspended.Wait();
672
673 // App isn't running because it got suspended.
674 ASSERT_FALSE(extension_prefs->IsExtensionRunning(extension->id()));
675
676 // Pretend that the app is supposed to be running.
677 extension_prefs->SetExtensionRunning(extension->id(), true);
678
679 ExtensionTestMessageListener restart_listener("onRestarted", false);
[email protected]119454622012-10-18 09:48:32680 AppRestoreServiceFactory::GetForProfile(browser()->profile())->
681 HandleStartup(true);
[email protected]28c3eeb2012-10-15 05:47:53682 restart_listener.WaitUntilSatisfied();
683}
684
[email protected]545b5312012-11-07 12:18:21685namespace {
686
687class PlatformAppDevToolsBrowserTest : public PlatformAppBrowserTest {
688 protected:
689 enum TestFlags {
690 RELAUNCH = 0x1,
691 HAS_ID = 0x2,
692 };
693 // Runs a test inside a harness that opens DevTools on a shell window.
694 void RunTestWithDevTools(const char* name, int test_flags);
695};
696
697void PlatformAppDevToolsBrowserTest::RunTestWithDevTools(
698 const char* name, int test_flags) {
[email protected]98f66112012-12-25 12:59:36699 using content::DevToolsAgentHost;
[email protected]d9d02762012-12-04 05:18:58700 ExtensionTestMessageListener launched_listener("Launched", false);
[email protected]545b5312012-11-07 12:18:21701 const Extension* extension = LoadAndLaunchPlatformApp(name);
[email protected]e85cc642012-10-24 06:14:23702 ASSERT_TRUE(extension);
[email protected]d9d02762012-12-04 05:18:58703 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
[email protected]e85cc642012-10-24 06:14:23704 ShellWindow* window = GetFirstShellWindow();
705 ASSERT_TRUE(window);
[email protected]545b5312012-11-07 12:18:21706 ASSERT_EQ(window->window_key().empty(), (test_flags & HAS_ID) == 0);
[email protected]e85cc642012-10-24 06:14:23707 content::RenderViewHost* rvh = window->web_contents()->GetRenderViewHost();
708 ASSERT_TRUE(rvh);
709
710 // Ensure no DevTools open for the ShellWindow, then open one.
[email protected]98f66112012-12-25 12:59:36711 ASSERT_FALSE(DevToolsAgentHost::HasFor(rvh));
[email protected]e85cc642012-10-24 06:14:23712 DevToolsWindow* devtools_window = DevToolsWindow::OpenDevToolsWindow(rvh);
713 content::WindowedNotificationObserver loaded_observer(
714 content::NOTIFICATION_LOAD_STOP,
715 content::Source<content::NavigationController>(
[email protected]ee2202a2012-12-11 01:07:20716 &devtools_window->web_contents()->GetController()));
[email protected]e85cc642012-10-24 06:14:23717 loaded_observer.Wait();
[email protected]98f66112012-12-25 12:59:36718 ASSERT_TRUE(DevToolsAgentHost::HasFor(rvh));
[email protected]e85cc642012-10-24 06:14:23719
[email protected]545b5312012-11-07 12:18:21720 if (test_flags & RELAUNCH) {
721 // Close the ShellWindow, and ensure it is gone.
722 CloseShellWindow(window);
723 ASSERT_FALSE(GetFirstShellWindow());
[email protected]e85cc642012-10-24 06:14:23724
[email protected]545b5312012-11-07 12:18:21725 // Relaunch the app and get a new ShellWindow.
726 content::WindowedNotificationObserver app_loaded_observer(
727 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
728 content::NotificationService::AllSources());
729 application_launch::OpenApplication(application_launch::LaunchParams(
730 browser()->profile(), extension, extension_misc::LAUNCH_NONE,
731 NEW_WINDOW));
732 app_loaded_observer.Wait();
733 window = GetFirstShellWindow();
734 ASSERT_TRUE(window);
[email protected]e85cc642012-10-24 06:14:23735
[email protected]545b5312012-11-07 12:18:21736 // DevTools should have reopened with the relaunch.
737 rvh = window->web_contents()->GetRenderViewHost();
738 ASSERT_TRUE(rvh);
[email protected]98f66112012-12-25 12:59:36739 ASSERT_TRUE(DevToolsAgentHost::HasFor(rvh));
[email protected]545b5312012-11-07 12:18:21740 }
[email protected]e85cc642012-10-24 06:14:23741}
742
[email protected]545b5312012-11-07 12:18:21743} // namespace
744
745IN_PROC_BROWSER_TEST_F(PlatformAppDevToolsBrowserTest, ReOpenedWithID) {
746 RunTestWithDevTools("minimal_id", RELAUNCH | HAS_ID);
747}
748
749IN_PROC_BROWSER_TEST_F(PlatformAppDevToolsBrowserTest, ReOpenedWithURL) {
750 RunTestWithDevTools("minimal", RELAUNCH);
751}
752
[email protected]ddf42162012-11-06 21:14:55753// Test that showing a permission request as a constrained window works and is
754// correctly parented.
755#if defined(OS_MACOSX)
[email protected]cd202662012-11-07 19:11:41756#define MAYBE_ConstrainedWindowRequest DISABLED_ConstrainedWindowRequest
[email protected]ddf42162012-11-06 21:14:55757#else
758// TODO(sail): Enable this on other platforms once http://crbug.com/95455 is
759// fixed.
760#define MAYBE_ConstrainedWindowRequest DISABLED_ConstrainedWindowRequest
761#endif
762
763IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_ConstrainedWindowRequest) {
[email protected]758b0b702013-01-10 12:19:33764 RequestPermissionsFunction::SetIgnoreUserGestureForTests(true);
[email protected]ddf42162012-11-06 21:14:55765 const Extension* extension =
766 LoadAndLaunchPlatformApp("optional_permission_request");
767 ASSERT_TRUE(extension) << "Failed to load extension.";
768
769 WebContents* web_contents = GetFirstShellWindowWebContents();
770 ASSERT_TRUE(web_contents);
771
[email protected]d2b16572013-01-03 00:41:58772 // Verify that the shell window has a dialog attached.
773 WebContentsModalDialogManager* web_contents_dialog_manager =
774 WebContentsModalDialogManager::FromWebContents(web_contents);
775 EXPECT_EQ(1u, web_contents_dialog_manager->dialog_count());
[email protected]ddf42162012-11-06 21:14:55776
777 // Close the constrained window and wait for the reply to the permission
778 // request.
779 ExtensionTestMessageListener listener("PermissionRequestDone", false);
[email protected]d2b16572013-01-03 00:41:58780 web_contents_dialog_manager->CloseAllDialogs();
[email protected]ddf42162012-11-06 21:14:55781 ASSERT_TRUE(listener.WaitUntilSatisfied());
[email protected]ddf42162012-11-06 21:14:55782}
783
[email protected]bf1be4e2012-11-07 20:32:27784// Tests that an app calling chrome.runtime.reload will reload the app and
785// relaunch it if it was running.
786IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ReloadRelaunches) {
787 ExtensionTestMessageListener launched_listener("Launched", true);
[email protected]d9d02762012-12-04 05:18:58788 const Extension* extension = LoadAndLaunchPlatformApp("reload");
[email protected]bf1be4e2012-11-07 20:32:27789 ASSERT_TRUE(extension);
[email protected]bf1be4e2012-11-07 20:32:27790 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
791 ASSERT_TRUE(GetFirstShellWindow());
792
793 // Now tell the app to reload itself
794 ExtensionTestMessageListener launched_listener2("Launched", false);
795 launched_listener.Reply("reload");
796 ASSERT_TRUE(launched_listener2.WaitUntilSatisfied());
797 ASSERT_TRUE(GetFirstShellWindow());
[email protected]bf1be4e2012-11-07 20:32:27798}
799
[email protected]8c484b742012-11-29 06:05:36800namespace {
801
802// Simple observer to check for NOTIFICATION_EXTENSION_INSTALLED events to
803// ensure installation does or does not occur in certain scenarios.
804class CheckExtensionInstalledObserver : public content::NotificationObserver {
805 public:
806 CheckExtensionInstalledObserver() : seen_(false) {
807 registrar_.Add(this,
808 chrome::NOTIFICATION_EXTENSION_INSTALLED,
809 content::NotificationService::AllSources());
810 }
811
812 bool seen() const {
813 return seen_;
814 };
815
816 // NotificationObserver:
817 virtual void Observe(int type,
818 const content::NotificationSource& source,
819 const content::NotificationDetails& details) OVERRIDE {
820 EXPECT_FALSE(seen_);
821 seen_ = true;
822 }
823
824 private:
825 bool seen_;
826 content::NotificationRegistrar registrar_;
827};
828
829} // namespace
830
831// Component App Test 1 of 3: ensure that the initial load of a component
832// extension utilizing a background page (e.g. a v2 platform app) has its
833// background page run and is launchable. Waits for the Launched response from
834// the script resource in the opened shell window.
835IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
836 PRE_PRE_ComponentAppBackgroundPage) {
837 CheckExtensionInstalledObserver should_install;
838
839 // Ensure that we wait until the background page is run (to register the
840 // OnLaunched listener) before trying to open the application. This is similar
841 // to LoadAndLaunchPlatformApp, but we want to load as a component extension.
842 content::WindowedNotificationObserver app_loaded_observer(
843 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
844 content::NotificationService::AllSources());
845
846 const Extension* extension = LoadExtensionAsComponent(
847 test_data_dir_.AppendASCII("platform_apps").AppendASCII("component"));
848 ASSERT_TRUE(extension);
849
850 app_loaded_observer.Wait();
851 ASSERT_TRUE(should_install.seen());
852
853 ExtensionTestMessageListener launched_listener("Launched", false);
854 application_launch::OpenApplication(application_launch::LaunchParams(
855 browser()->profile(), extension, extension_misc::LAUNCH_NONE,
856 NEW_WINDOW));
857
858 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
859}
860
861// Component App Test 2 of 3: ensure an installed component app can be launched
862// on a subsequent browser start, without requiring any install/upgrade logic
863// to be run, then perform setup for step 3.
864IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
865 PRE_ComponentAppBackgroundPage) {
866
867 // Since the component app is now installed, re-adding it in the same profile
868 // should not cause it to be re-installed. Instead, we wait for the OnLaunched
869 // in a different observer (which would timeout if not the app was not
870 // previously installed properly) and then check this observer to make sure it
871 // never saw the NOTIFICATION_EXTENSION_INSTALLED event.
872 CheckExtensionInstalledObserver should_not_install;
873 const Extension* extension = LoadExtensionAsComponent(
874 test_data_dir_.AppendASCII("platform_apps").AppendASCII("component"));
875 ASSERT_TRUE(extension);
876
877 ExtensionTestMessageListener launched_listener("Launched", false);
878 application_launch::OpenApplication(application_launch::LaunchParams(
879 browser()->profile(), extension, extension_misc::LAUNCH_NONE,
880 NEW_WINDOW));
881
882 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
883 ASSERT_FALSE(should_not_install.seen());
884
885 // Simulate a "downgrade" from version 2 in the test manifest.json to 1.
886 ExtensionPrefs* extension_prefs =
887 extensions::ExtensionSystem::Get(browser()->profile())->
888 extension_service()->extension_prefs();
889
890 // Clear the registered events to ensure they are updated.
891 extension_prefs->SetRegisteredEvents(extension->id(),
892 std::set<std::string>());
893
894 const base::StringValue old_version("1");
895 std::string pref_path("extensions.settings.");
896 pref_path += extension->id();
897 pref_path += ".manifest.version";
898 extension_prefs->pref_service()->RegisterStringPref(
[email protected]5b199522012-12-22 17:24:44899 pref_path.c_str(), std::string(), PrefServiceSyncable::UNSYNCABLE_PREF);
[email protected]8c484b742012-11-29 06:05:36900 extension_prefs->pref_service()->Set(pref_path.c_str(), old_version);
901}
902
903// Component App Test 3 of 3: simulate a component extension upgrade that
904// re-adds the OnLaunched event, and allows the app to be launched.
905IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ComponentAppBackgroundPage) {
906 CheckExtensionInstalledObserver should_install;
907 // Since we are forcing an upgrade, we need to wait for the load again.
908 content::WindowedNotificationObserver app_loaded_observer(
909 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
910 content::NotificationService::AllSources());
911
912 const Extension* extension = LoadExtensionAsComponent(
913 test_data_dir_.AppendASCII("platform_apps").AppendASCII("component"));
914 ASSERT_TRUE(extension);
915 app_loaded_observer.Wait();
916 ASSERT_TRUE(should_install.seen());
917
918 ExtensionTestMessageListener launched_listener("Launched", false);
919 application_launch::OpenApplication(application_launch::LaunchParams(
920 browser()->profile(), extension, extension_misc::LAUNCH_NONE,
921 NEW_WINDOW));
922
923 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
924}
925
[email protected]481a87e62012-12-19 23:00:27926IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Messaging) {
927 ExtensionApiTest::ResultCatcher result_catcher;
928 LoadAndLaunchPlatformApp("messaging/app2");
929 LoadAndLaunchPlatformApp("messaging/app1");
930 EXPECT_TRUE(result_catcher.GetNextResult());
931}
932
[email protected]d9ede582012-08-14 19:21:38933} // namespace extensions