blob: 1f124a800e77ee91031c4ca6c2beea68d8f982b6 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// 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
Ben Murdochbb1529c2013-08-08 10:24:53 +01005#include "apps/launcher.h"
Ben Murdoch2385ea32013-08-06 11:01:04 +01006#include "apps/native_app_window.h"
Ben Murdocheb525c52013-07-10 11:40:50 +01007#include "apps/shell_window.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +00008#include "base/bind.h"
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +01009#include "base/command_line.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010#include "base/file_util.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010011#include "base/files/scoped_temp_dir.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000012#include "base/prefs/pref_service.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010013#include "base/stl_util.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010014#include "base/strings/utf_string_conversions.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000015#include "base/test/test_timeouts.h"
16#include "base/threading/platform_thread.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000017#include "chrome/app/chrome_command_ids.h"
18#include "chrome/browser/automation/automation_util.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010019#include "chrome/browser/chrome_notification_types.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000020#include "chrome/browser/devtools/devtools_window.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000021#include "chrome/browser/extensions/api/permissions/permissions_api.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010022#include "chrome/browser/extensions/component_loader.h"
23#include "chrome/browser/extensions/event_names.h"
24#include "chrome/browser/extensions/event_router.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000025#include "chrome/browser/extensions/extension_browsertest.h"
26#include "chrome/browser/extensions/extension_prefs.h"
27#include "chrome/browser/extensions/extension_service.h"
28#include "chrome/browser/extensions/extension_system.h"
29#include "chrome/browser/extensions/extension_test_message_listener.h"
30#include "chrome/browser/extensions/platform_app_browsertest_util.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000031#include "chrome/browser/extensions/shell_window_registry.h"
32#include "chrome/browser/tab_contents/render_view_context_menu.h"
33#include "chrome/browser/ui/browser.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000034#include "chrome/browser/ui/extensions/application_launch.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000035#include "chrome/browser/ui/tabs/tab_strip_model.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010036#include "chrome/common/chrome_switches.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000037#include "chrome/common/url_constants.h"
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +010038#include "chrome/test/base/test_switches.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000039#include "chrome/test/base/ui_test_utils.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000040#include "components/user_prefs/pref_registry_syncable.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010041#include "components/web_modal/web_contents_modal_dialog_manager.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000042#include "content/public/browser/devtools_agent_host.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000043#include "content/public/browser/render_process_host.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000044#include "content/public/browser/render_widget_host_view.h"
45#include "content/public/browser/web_contents_view.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000046#include "content/public/test/test_utils.h"
Ben Murdocheb525c52013-07-10 11:40:50 +010047#include "net/test/embedded_test_server/embedded_test_server.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010048#include "url/gurl.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000049
Ben Murdocheb525c52013-07-10 11:40:50 +010050using apps::ShellWindow;
Torne (Richard Coles)58218062012-11-14 11:43:16 +000051using content::WebContents;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010052using web_modal::WebContentsModalDialogManager;
Torne (Richard Coles)58218062012-11-14 11:43:16 +000053
54namespace extensions {
55
56namespace {
57
58// Non-abstract RenderViewContextMenu class.
59class PlatformAppContextMenu : public RenderViewContextMenu {
60 public:
61 PlatformAppContextMenu(WebContents* web_contents,
62 const content::ContextMenuParams& params)
63 : RenderViewContextMenu(web_contents, params) {}
64
65 bool HasCommandWithId(int command_id) {
66 return menu_model_.GetIndexOfCommandId(command_id) != -1;
67 }
68
69 protected:
70 // RenderViewContextMenu implementation.
71 virtual bool GetAcceleratorForCommandId(
72 int command_id,
73 ui::Accelerator* accelerator) OVERRIDE {
74 return false;
75 }
76 virtual void PlatformInit() OVERRIDE {}
77 virtual void PlatformCancel() OVERRIDE {}
78};
79
Torne (Richard Coles)58218062012-11-14 11:43:16 +000080// This class keeps track of tabs as they are added to the browser. It will be
81// "done" (i.e. won't block on Wait()) once |observations| tabs have been added.
82class TabsAddedNotificationObserver
83 : public content::WindowedNotificationObserver {
84 public:
85 explicit TabsAddedNotificationObserver(size_t observations)
86 : content::WindowedNotificationObserver(
87 chrome::NOTIFICATION_TAB_ADDED,
88 content::NotificationService::AllSources()),
89 observations_(observations) {
90 }
91
92 virtual void Observe(int type,
93 const content::NotificationSource& source,
94 const content::NotificationDetails& details) OVERRIDE {
95 observed_tabs_.push_back(
96 content::Details<WebContents>(details).ptr());
97 if (observed_tabs_.size() == observations_)
98 content::WindowedNotificationObserver::Observe(type, source, details);
99 }
100
101 const std::vector<content::WebContents*>& tabs() { return observed_tabs_; }
102
103 private:
104 size_t observations_;
105 std::vector<content::WebContents*> observed_tabs_;
106
107 DISALLOW_COPY_AND_ASSIGN(TabsAddedNotificationObserver);
108};
109
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100110bool CopyTestDataAndSetCommandLineArg(
111 const base::FilePath& test_data_file,
112 const base::FilePath& temp_dir,
113 const char* filename) {
114 base::FilePath path = temp_dir.AppendASCII(
115 filename).NormalizePathSeparators();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100116 if (!(base::CopyFile(test_data_file, path)))
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100117 return false;
118
119 CommandLine* command_line = CommandLine::ForCurrentProcess();
120 command_line->AppendArgPath(path);
121 return true;
122}
123
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000124const char kTestFilePath[] = "platform_apps/launch_files/test.txt";
125
126} // namespace
127
128// Tests that CreateShellWindow doesn't crash if you close it straight away.
129// LauncherPlatformAppBrowserTest relies on this behaviour, but is only run for
130// ash, so we test that it works here.
131IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, CreateAndCloseShellWindow) {
132 const Extension* extension = LoadAndLaunchPlatformApp("minimal");
133 ShellWindow* window = CreateShellWindow(extension);
134 CloseShellWindow(window);
135}
136
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000137// Tests that platform apps received the "launch" event when launched.
138IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, OnLaunchedEvent) {
139 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch")) << message_;
140}
141
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000142// Tests that platform apps cannot use certain disabled window properties, but
143// can override them and then use them.
144IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisabledWindowProperties) {
145 ASSERT_TRUE(RunPlatformAppTest("platform_apps/disabled_window_properties"))
146 << message_;
147}
148
149IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, EmptyContextMenu) {
150 ExtensionTestMessageListener launched_listener("Launched", false);
151 LoadAndLaunchPlatformApp("minimal");
152
153 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
154
155 // The empty app doesn't add any context menu items, so its menu should
156 // only include the developer tools.
157 WebContents* web_contents = GetFirstShellWindowWebContents();
158 ASSERT_TRUE(web_contents);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100159 content::ContextMenuParams params;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000160 scoped_ptr<PlatformAppContextMenu> menu;
161 menu.reset(new PlatformAppContextMenu(web_contents, params));
162 menu->Init();
163 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
164 ASSERT_TRUE(
165 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
166 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
167 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
168 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
169}
170
171IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenu) {
172 ExtensionTestMessageListener launched_listener("Launched", false);
173 LoadAndLaunchPlatformApp("context_menu");
174
175 // Wait for the extension to tell us it's initialized its context menus and
176 // launched a window.
177 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
178
179 // The context_menu app has two context menu items. These, along with a
180 // separator and the developer tools, is all that should be in the menu.
181 WebContents* web_contents = GetFirstShellWindowWebContents();
182 ASSERT_TRUE(web_contents);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100183 content::ContextMenuParams params;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000184 scoped_ptr<PlatformAppContextMenu> menu;
185 menu.reset(new PlatformAppContextMenu(web_contents, params));
186 menu->Init();
187 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
188 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST + 1));
189 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
190 ASSERT_TRUE(
191 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
192 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
193 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
194 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
195 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
196}
197
198IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, InstalledAppWithContextMenu) {
199 ExtensionTestMessageListener launched_listener("Launched", false);
200 InstallAndLaunchPlatformApp("context_menu");
201
202 // Wait for the extension to tell us it's initialized its context menus and
203 // launched a window.
204 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
205
206 // The context_menu app has two context menu items. For an installed app
207 // these are all that should be in the menu.
208 WebContents* web_contents = GetFirstShellWindowWebContents();
209 ASSERT_TRUE(web_contents);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100210 content::ContextMenuParams params;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000211 scoped_ptr<PlatformAppContextMenu> menu;
212 menu.reset(new PlatformAppContextMenu(web_contents, params));
213 menu->Init();
214 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
215 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST + 1));
216 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
217 ASSERT_FALSE(
218 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
219 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
220 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
221 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
222 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
223}
224
225IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenuTextField) {
226 ExtensionTestMessageListener launched_listener("Launched", false);
227 LoadAndLaunchPlatformApp("context_menu");
228
229 // Wait for the extension to tell us it's initialized its context menus and
230 // launched a window.
231 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
232
233 // The context_menu app has one context menu item. This, along with a
234 // separator and the developer tools, is all that should be in the menu.
235 WebContents* web_contents = GetFirstShellWindowWebContents();
236 ASSERT_TRUE(web_contents);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100237 content::ContextMenuParams params;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000238 params.is_editable = true;
239 scoped_ptr<PlatformAppContextMenu> menu;
240 menu.reset(new PlatformAppContextMenu(web_contents, params));
241 menu->Init();
242 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
243 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
244 ASSERT_TRUE(
245 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
246 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
247 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
248 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_COPY));
249 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
250 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
251}
252
253IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenuSelection) {
254 ExtensionTestMessageListener launched_listener("Launched", false);
255 LoadAndLaunchPlatformApp("context_menu");
256
257 // Wait for the extension to tell us it's initialized its context menus and
258 // launched a window.
259 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
260
261 // The context_menu app has one context menu item. This, along with a
262 // separator and the developer tools, is all that should be in the menu.
263 WebContents* web_contents = GetFirstShellWindowWebContents();
264 ASSERT_TRUE(web_contents);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100265 content::ContextMenuParams params;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000266 params.selection_text = ASCIIToUTF16("Hello World");
267 scoped_ptr<PlatformAppContextMenu> menu;
268 menu.reset(new PlatformAppContextMenu(web_contents, params));
269 menu->Init();
270 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
271 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
272 ASSERT_TRUE(
273 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
274 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
275 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
276 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_COPY));
277 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
278 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
279}
280
281IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenuClicked) {
282 ExtensionTestMessageListener launched_listener("Launched", false);
283 LoadAndLaunchPlatformApp("context_menu_click");
284
285 // Wait for the extension to tell us it's initialized its context menus and
286 // launched a window.
287 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
288
289 // Test that the menu item shows up
290 WebContents* web_contents = GetFirstShellWindowWebContents();
291 ASSERT_TRUE(web_contents);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100292 content::ContextMenuParams params;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000293 params.page_url = GURL("http://foo.bar");
294 scoped_ptr<PlatformAppContextMenu> menu;
295 menu.reset(new PlatformAppContextMenu(web_contents, params));
296 menu->Init();
297 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
298
299 // Execute the menu item
300 ExtensionTestMessageListener onclicked_listener("onClicked fired for id1",
301 false);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000302 menu->ExecuteCommand(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST, 0);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000303
304 ASSERT_TRUE(onclicked_listener.WaitUntilSatisfied());
305}
306
307IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisallowNavigation) {
308 TabsAddedNotificationObserver observer(2);
309
Ben Murdocheb525c52013-07-10 11:40:50 +0100310 ASSERT_TRUE(StartEmbeddedTestServer());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000311 ASSERT_TRUE(RunPlatformAppTest("platform_apps/navigation")) << message_;
312
313 observer.Wait();
314 ASSERT_EQ(2U, observer.tabs().size());
315 EXPECT_EQ(std::string(chrome::kExtensionInvalidRequestURL),
316 observer.tabs()[0]->GetURL().spec());
317 EXPECT_EQ("http://chromium.org/",
318 observer.tabs()[1]->GetURL().spec());
319}
320
321IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Iframes) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100322 ASSERT_TRUE(StartEmbeddedTestServer());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000323 ASSERT_TRUE(RunPlatformAppTest("platform_apps/iframes")) << message_;
324}
325
326// Tests that localStorage and WebSQL are disabled for platform apps.
327IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisallowStorage) {
328 ASSERT_TRUE(RunPlatformAppTest("platform_apps/storage")) << message_;
329}
330
331IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Restrictions) {
332 ASSERT_TRUE(RunPlatformAppTest("platform_apps/restrictions")) << message_;
333}
334
335// Tests that platform apps can use the chrome.app.window.* API.
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100336// It is flaky: http://crbug.com/223467
337IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DISABLED_WindowsApi) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000338 ASSERT_TRUE(RunPlatformAppTest("platform_apps/windows_api")) << message_;
339}
340
341// Tests that extensions can't use platform-app-only APIs.
342IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, PlatformAppsOnly) {
343 ASSERT_TRUE(RunExtensionTestIgnoreManifestWarnings(
344 "platform_apps/apps_only")) << message_;
345}
346
347// Tests that platform apps have isolated storage by default.
348IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Isolation) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100349 ASSERT_TRUE(StartEmbeddedTestServer());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000350
351 // Load a (non-app) page under the "localhost" origin that sets a cookie.
Ben Murdocheb525c52013-07-10 11:40:50 +0100352 GURL set_cookie_url = embedded_test_server()->GetURL(
353 "/extensions/platform_apps/isolation/set_cookie.html");
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000354 GURL::Replacements replace_host;
355 std::string host_str("localhost"); // Must stay in scope with replace_host.
356 replace_host.SetHostStr(host_str);
357 set_cookie_url = set_cookie_url.ReplaceComponents(replace_host);
358
359 ui_test_utils::NavigateToURLWithDisposition(
360 browser(), set_cookie_url,
361 CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
362
363 // Make sure the cookie is set.
364 int cookie_size;
365 std::string cookie_value;
366 automation_util::GetCookies(
367 set_cookie_url,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000368 browser()->tab_strip_model()->GetWebContentsAt(0),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000369 &cookie_size,
370 &cookie_value);
371 ASSERT_EQ("testCookie=1", cookie_value);
372
373 // Let the platform app request the same URL, and make sure that it doesn't
374 // see the cookie.
375 ASSERT_TRUE(RunPlatformAppTest("platform_apps/isolation")) << message_;
376}
377
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100378// See crbug.com/248441
379#if defined(OS_WIN)
380#define MAYBE_ExtensionWindowingApis DISABLED_ExtensionWindowingApis
381#else
382#define MAYBE_ExtensionWindowingApis ExtensionWindowingApis
383#endif
384
385IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_ExtensionWindowingApis) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000386 // Initially there should be just the one browser window visible to the
387 // extensions API.
388 const Extension* extension = LoadExtension(
389 test_data_dir_.AppendASCII("common/background_page"));
390 ASSERT_EQ(1U, RunGetWindowsFunctionForExtension(extension));
391
392 // And no shell windows.
393 ASSERT_EQ(0U, GetShellWindowCount());
394
395 // Launch a platform app that shows a window.
396 ExtensionTestMessageListener launched_listener("Launched", false);
397 LoadAndLaunchPlatformApp("minimal");
398 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
399 ASSERT_EQ(1U, GetShellWindowCount());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100400 ShellWindowRegistry::ShellWindowList shell_windows =
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000401 ShellWindowRegistry::Get(browser()->profile())->shell_windows();
402 int shell_window_id = (*shell_windows.begin())->session_id().id();
403
404 // But it's not visible to the extensions API, it still thinks there's just
405 // one browser window.
406 ASSERT_EQ(1U, RunGetWindowsFunctionForExtension(extension));
407 // It can't look it up by ID either
408 ASSERT_FALSE(RunGetWindowFunctionForExtension(shell_window_id, extension));
409
410 // The app can also only see one window (its own).
411 // TODO(jeremya): add an extension function to get a shell window by ID, and
412 // to get a list of all the shell windows, so we can test this.
413
414 // Launch another platform app that also shows a window.
415 ExtensionTestMessageListener launched_listener2("Launched", false);
416 LoadAndLaunchPlatformApp("context_menu");
417 ASSERT_TRUE(launched_listener2.WaitUntilSatisfied());
418
419 // There are two total shell windows, but each app can only see its own.
420 ASSERT_EQ(2U, GetShellWindowCount());
421 // TODO(jeremya): as above, this requires more extension functions.
422}
423
424// ChromeOS does not support passing arguments on the command line, so the tests
425// that rely on this functionality are disabled.
426#if !defined(OS_CHROMEOS)
427// Tests that command line parameters get passed through to platform apps
428// via launchData correctly when launching with a file.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000429// TODO(benwells/jeremya): tests need a way to specify a handler ID.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000430IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithFile) {
431 SetCommandLineArg(kTestFilePath);
432 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_file"))
433 << message_;
434}
435
436// Tests that relative paths can be passed through to the platform app.
437// This test doesn't use the normal test infrastructure as it needs to open
438// the application differently to all other platform app tests, by setting
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000439// the chrome::AppLaunchParams.current_directory field.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000440IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithRelativeFile) {
441 // Setup the command line
442 ClearCommandLineArgs();
443 CommandLine* command_line = CommandLine::ForCurrentProcess();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000444 base::FilePath relative_test_doc =
445 base::FilePath::FromUTF8Unsafe(kTestFilePath);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000446 relative_test_doc = relative_test_doc.NormalizePathSeparators();
447 command_line->AppendArgPath(relative_test_doc);
448
449 // Load the extension
450 ResultCatcher catcher;
451 const Extension* extension = LoadExtension(
452 test_data_dir_.AppendASCII("platform_apps/launch_file"));
453 ASSERT_TRUE(extension);
454
455 // Run the test
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000456 chrome::AppLaunchParams params(browser()->profile(), extension,
457 extension_misc::LAUNCH_NONE, NEW_WINDOW);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000458 params.command_line = CommandLine::ForCurrentProcess();
459 params.current_directory = test_data_dir_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000460 chrome::OpenApplication(params);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000461
462 if (!catcher.GetNextResult()) {
463 message_ = catcher.message();
464 ASSERT_TRUE(0);
465 }
466}
467
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100468// Tests that launch data is sent through if the file extension matches.
469IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithFileExtension) {
470 SetCommandLineArg(kTestFilePath);
471 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_file_by_extension"))
472 << message_;
473}
474
475// Tests that launch data is sent through if the file extension and MIME type
476// both match.
477IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
478 LaunchWithFileExtensionAndMimeType) {
479 SetCommandLineArg(kTestFilePath);
480 ASSERT_TRUE(RunPlatformAppTest(
481 "platform_apps/launch_file_by_extension_and_type")) << message_;
482}
483
484// Tests that launch data is sent through for a file with no extension if a
485// handler accepts "".
486IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithFileWithoutExtension) {
487 SetCommandLineArg("platform_apps/launch_files/test");
488 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_file_with_no_extension"))
489 << message_;
490}
491
492#if !defined(OS_WIN)
493// Tests that launch data is sent through for a file with an empty extension if
494// a handler accepts "".
495IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithFileEmptyExtension) {
496 base::ScopedTempDir temp_dir;
497 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
498 ClearCommandLineArgs();
499 ASSERT_TRUE(CopyTestDataAndSetCommandLineArg(
500 test_data_dir_.AppendASCII(kTestFilePath),
501 temp_dir.path(),
502 "test."));
503 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_file_with_no_extension"))
504 << message_;
505}
506
507// Tests that launch data is sent through for a file with an empty extension if
508// a handler accepts *.
509IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
510 LaunchWithFileEmptyExtensionAcceptAny) {
511 base::ScopedTempDir temp_dir;
512 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
513 ClearCommandLineArgs();
514 ASSERT_TRUE(CopyTestDataAndSetCommandLineArg(
515 test_data_dir_.AppendASCII(kTestFilePath),
516 temp_dir.path(),
517 "test."));
518 ASSERT_TRUE(RunPlatformAppTest(
519 "platform_apps/launch_file_with_any_extension")) << message_;
520}
521#endif
522
523// Tests that launch data is sent through for a file with no extension if a
524// handler accepts *.
525IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
526 LaunchWithFileWithoutExtensionAcceptAny) {
527 SetCommandLineArg("platform_apps/launch_files/test");
528 ASSERT_TRUE(RunPlatformAppTest(
529 "platform_apps/launch_file_with_any_extension")) << message_;
530}
531
532// Tests that launch data is sent through for a file with an extension if a
533// handler accepts *.
534IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
535 LaunchWithFileAcceptAnyExtension) {
536 SetCommandLineArg(kTestFilePath);
537 ASSERT_TRUE(RunPlatformAppTest(
538 "platform_apps/launch_file_with_any_extension")) << message_;
539}
540
541// Tests that no launch data is sent through if the file has the wrong
542// extension.
543IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithWrongExtension) {
544 SetCommandLineArg(kTestFilePath);
545 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_wrong_extension"))
546 << message_;
547}
548
549// Tests that no launch data is sent through if the file has no extension but
550// the handler requires a specific extension.
551IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithWrongEmptyExtension) {
552 SetCommandLineArg("platform_apps/launch_files/test");
553 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_wrong_extension"))
554 << message_;
555}
556
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000557// Tests that no launch data is sent through if the file is of the wrong MIME
558// type.
559IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithWrongType) {
560 SetCommandLineArg(kTestFilePath);
561 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_wrong_type"))
562 << message_;
563}
564
565// Tests that no launch data is sent through if the platform app does not
566// provide an intent.
567IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithNoIntent) {
568 SetCommandLineArg(kTestFilePath);
569 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_no_intent"))
570 << message_;
571}
572
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100573// Tests that launch data is sent through with the MIME type set to
574// application/octet-stream if the file MIME type cannot be read.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000575IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchNoType) {
576 SetCommandLineArg("platform_apps/launch_files/test.unknownextension");
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100577 ASSERT_TRUE(RunPlatformAppTest(
578 "platform_apps/launch_application_octet_stream")) << message_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000579}
580
581// Tests that no launch data is sent through if the file does not exist.
582IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchNoFile) {
583 SetCommandLineArg("platform_apps/launch_files/doesnotexist.txt");
584 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_invalid"))
585 << message_;
586}
587
588// Tests that no launch data is sent through if the argument is a directory.
589IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithDirectory) {
590 SetCommandLineArg("platform_apps/launch_files");
591 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_invalid"))
592 << message_;
593}
594
595// Tests that no launch data is sent through if there are no arguments passed
596// on the command line
597IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithNothing) {
598 ClearCommandLineArgs();
599 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_nothing"))
600 << message_;
601}
602
603// Test that platform apps can use the chrome.fileSystem.getDisplayPath
604// function to get the native file system path of a file they are launched with.
605IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, GetDisplayPath) {
606 SetCommandLineArg(kTestFilePath);
607 ASSERT_TRUE(RunPlatformAppTest("platform_apps/get_display_path"))
608 << message_;
609}
610
611#endif // defined(OS_CHROMEOS)
612
613IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, OpenLink) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100614 ASSERT_TRUE(StartEmbeddedTestServer());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000615 content::WindowedNotificationObserver observer(
616 chrome::NOTIFICATION_TAB_ADDED,
617 content::Source<content::WebContentsDelegate>(browser()));
618 LoadAndLaunchPlatformApp("open_link");
619 observer.Wait();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000620 ASSERT_EQ(2, browser()->tab_strip_model()->count());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000621}
622
623IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MutationEventsDisabled) {
624 ASSERT_TRUE(RunPlatformAppTest("platform_apps/mutation_events")) << message_;
625}
626
627// Test that windows created with an id will remember and restore their
628// geometry when opening new windows.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000629// Originally disabled due to flakiness (see http://crbug.com/155459)
630// but now because a regression breaks the test (http://crbug.com/160343).
631#if defined(TOOLKIT_GTK)
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000632#define MAYBE_ShellWindowRestorePosition DISABLED_ShellWindowRestorePosition
633#else
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000634#define MAYBE_ShellWindowRestorePosition ShellWindowRestorePosition
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000635#endif
636IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
637 MAYBE_ShellWindowRestorePosition) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000638 ASSERT_TRUE(RunPlatformAppTest("platform_apps/geometry"));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000639}
640
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100641// This appears to be unreliable on linux.
642// TODO(stevenjb): Investigate and enable
643#if defined(OS_LINUX) && !defined(USE_ASH)
644#define MAYBE_ShellWindowRestoreState DISABLED_ShellWindowRestoreState
645#else
646#define MAYBE_ShellWindowRestoreState ShellWindowRestoreState
647#endif
648IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
649 MAYBE_ShellWindowRestoreState) {
650 ASSERT_TRUE(RunPlatformAppTest("platform_apps/restore_state"));
651}
652
Ben Murdocheb525c52013-07-10 11:40:50 +0100653IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
654 ShellWindowAdjustBoundsToBeVisibleOnScreen) {
655 const Extension* extension = LoadAndLaunchPlatformApp("minimal");
656 ShellWindow* window = CreateShellWindow(extension);
657
658 // The screen bounds didn't change, the cached bounds didn't need to adjust.
659 gfx::Rect cached_bounds(80, 100, 400, 400);
660 gfx::Rect cached_screen_bounds(0, 0, 1600, 900);
661 gfx::Rect current_screen_bounds(0, 0, 1600, 900);
662 gfx::Size minimum_size(200, 200);
663 gfx::Rect bounds;
664 CallAdjustBoundsToBeVisibleOnScreenForShellWindow(window,
665 cached_bounds,
666 cached_screen_bounds,
667 current_screen_bounds,
668 minimum_size,
669 &bounds);
670 EXPECT_EQ(bounds, cached_bounds);
671
672 // We have an empty screen bounds, the cached bounds didn't need to adjust.
673 gfx::Rect empty_screen_bounds;
674 CallAdjustBoundsToBeVisibleOnScreenForShellWindow(window,
675 cached_bounds,
676 empty_screen_bounds,
677 current_screen_bounds,
678 minimum_size,
679 &bounds);
680 EXPECT_EQ(bounds, cached_bounds);
681
682 // Cached bounds is completely off the new screen bounds in horizontal
683 // locations. Expect to reposition the bounds.
684 gfx::Rect horizontal_out_of_screen_bounds(-800, 100, 400, 400);
685 CallAdjustBoundsToBeVisibleOnScreenForShellWindow(
686 window,
687 horizontal_out_of_screen_bounds,
688 gfx::Rect(-1366, 0, 1600, 900),
689 current_screen_bounds,
690 minimum_size,
691 &bounds);
692 EXPECT_EQ(bounds, gfx::Rect(0, 100, 400, 400));
693
694 // Cached bounds is completely off the new screen bounds in vertical
695 // locations. Expect to reposition the bounds.
696 gfx::Rect vertical_out_of_screen_bounds(10, 1000, 400, 400);
697 CallAdjustBoundsToBeVisibleOnScreenForShellWindow(
698 window,
699 vertical_out_of_screen_bounds,
700 gfx::Rect(-1366, 0, 1600, 900),
701 current_screen_bounds,
702 minimum_size,
703 &bounds);
704 EXPECT_EQ(bounds, gfx::Rect(10, 500, 400, 400));
705
706 // From a large screen resulotion to a small one. Expect it fit on screen.
707 gfx::Rect big_cache_bounds(10, 10, 1000, 1000);
708 CallAdjustBoundsToBeVisibleOnScreenForShellWindow(
709 window,
710 big_cache_bounds,
711 gfx::Rect(0, 0, 1600, 1000),
712 gfx::Rect(0, 0, 800, 600),
713 minimum_size,
714 &bounds);
715 EXPECT_EQ(bounds, gfx::Rect(0, 0, 800, 600));
716
717 // Don't resize the bounds smaller than minimum size, when the minimum size is
718 // larger than the screen.
719 CallAdjustBoundsToBeVisibleOnScreenForShellWindow(
720 window,
721 big_cache_bounds,
722 gfx::Rect(0, 0, 1600, 1000),
723 gfx::Rect(0, 0, 800, 600),
724 gfx::Size(900, 900),
725 &bounds);
726 EXPECT_EQ(bounds, gfx::Rect(0, 0, 900, 900));
727}
728
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000729namespace {
730
731class PlatformAppDevToolsBrowserTest : public PlatformAppBrowserTest {
732 protected:
733 enum TestFlags {
734 RELAUNCH = 0x1,
735 HAS_ID = 0x2,
736 };
737 // Runs a test inside a harness that opens DevTools on a shell window.
738 void RunTestWithDevTools(const char* name, int test_flags);
739};
740
741void PlatformAppDevToolsBrowserTest::RunTestWithDevTools(
742 const char* name, int test_flags) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000743 using content::DevToolsAgentHost;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000744 ExtensionTestMessageListener launched_listener("Launched", false);
745 const Extension* extension = LoadAndLaunchPlatformApp(name);
746 ASSERT_TRUE(extension);
747 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
748 ShellWindow* window = GetFirstShellWindow();
749 ASSERT_TRUE(window);
750 ASSERT_EQ(window->window_key().empty(), (test_flags & HAS_ID) == 0);
751 content::RenderViewHost* rvh = window->web_contents()->GetRenderViewHost();
752 ASSERT_TRUE(rvh);
753
754 // Ensure no DevTools open for the ShellWindow, then open one.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000755 ASSERT_FALSE(DevToolsAgentHost::HasFor(rvh));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000756 DevToolsWindow* devtools_window = DevToolsWindow::OpenDevToolsWindow(rvh);
757 content::WindowedNotificationObserver loaded_observer(
758 content::NOTIFICATION_LOAD_STOP,
759 content::Source<content::NavigationController>(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000760 &devtools_window->web_contents()->GetController()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000761 loaded_observer.Wait();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000762 ASSERT_TRUE(DevToolsAgentHost::HasFor(rvh));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000763
764 if (test_flags & RELAUNCH) {
765 // Close the ShellWindow, and ensure it is gone.
766 CloseShellWindow(window);
767 ASSERT_FALSE(GetFirstShellWindow());
768
769 // Relaunch the app and get a new ShellWindow.
770 content::WindowedNotificationObserver app_loaded_observer(
771 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
772 content::NotificationService::AllSources());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000773 chrome::OpenApplication(chrome::AppLaunchParams(browser()->profile(),
774 extension,
775 extension_misc::LAUNCH_NONE,
776 NEW_WINDOW));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000777 app_loaded_observer.Wait();
778 window = GetFirstShellWindow();
779 ASSERT_TRUE(window);
780
781 // DevTools should have reopened with the relaunch.
782 rvh = window->web_contents()->GetRenderViewHost();
783 ASSERT_TRUE(rvh);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000784 ASSERT_TRUE(DevToolsAgentHost::HasFor(rvh));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000785 }
786}
787
788} // namespace
789
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100790// http://crbug.com/246634
791#if defined(OS_CHROMEOS)
792#define MAYBE_ReOpenedWithID DISABLED_ReOpenedWithID
793#else
794#define MAYBE_ReOpenedWithID ReOpenedWithID
795#endif
796IN_PROC_BROWSER_TEST_F(PlatformAppDevToolsBrowserTest, MAYBE_ReOpenedWithID) {
Ben Murdochca12bfa2013-07-23 11:17:05 +0100797#if defined(OS_WIN) && defined(USE_ASH)
Torne (Richard Coles)a36e5922013-08-05 13:57:33 +0100798 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
799 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
Ben Murdochca12bfa2013-07-23 11:17:05 +0100800 return;
801#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000802 RunTestWithDevTools("minimal_id", RELAUNCH | HAS_ID);
803}
804
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100805// http://crbug.com/246999
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100806#if defined(OS_CHROMEOS) || defined(OS_WIN)
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100807#define MAYBE_ReOpenedWithURL DISABLED_ReOpenedWithURL
808#else
809#define MAYBE_ReOpenedWithURL ReOpenedWithURL
810#endif
811IN_PROC_BROWSER_TEST_F(PlatformAppDevToolsBrowserTest, MAYBE_ReOpenedWithURL) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000812 RunTestWithDevTools("minimal", RELAUNCH);
813}
814
815// Test that showing a permission request as a constrained window works and is
816// correctly parented.
817#if defined(OS_MACOSX)
818#define MAYBE_ConstrainedWindowRequest DISABLED_ConstrainedWindowRequest
819#else
820// TODO(sail): Enable this on other platforms once http://crbug.com/95455 is
821// fixed.
822#define MAYBE_ConstrainedWindowRequest DISABLED_ConstrainedWindowRequest
823#endif
824
825IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_ConstrainedWindowRequest) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000826 PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000827 const Extension* extension =
828 LoadAndLaunchPlatformApp("optional_permission_request");
829 ASSERT_TRUE(extension) << "Failed to load extension.";
830
831 WebContents* web_contents = GetFirstShellWindowWebContents();
832 ASSERT_TRUE(web_contents);
833
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000834 // Verify that the shell window has a dialog attached.
835 WebContentsModalDialogManager* web_contents_modal_dialog_manager =
836 WebContentsModalDialogManager::FromWebContents(web_contents);
837 EXPECT_TRUE(web_contents_modal_dialog_manager->IsShowingDialog());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000838
839 // Close the constrained window and wait for the reply to the permission
840 // request.
841 ExtensionTestMessageListener listener("PermissionRequestDone", false);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000842 WebContentsModalDialogManager::TestApi test_api(
843 web_contents_modal_dialog_manager);
844 test_api.CloseAllDialogs();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000845 ASSERT_TRUE(listener.WaitUntilSatisfied());
846}
847
848// Tests that an app calling chrome.runtime.reload will reload the app and
849// relaunch it if it was running.
850IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ReloadRelaunches) {
851 ExtensionTestMessageListener launched_listener("Launched", true);
852 const Extension* extension = LoadAndLaunchPlatformApp("reload");
853 ASSERT_TRUE(extension);
854 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
855 ASSERT_TRUE(GetFirstShellWindow());
856
857 // Now tell the app to reload itself
858 ExtensionTestMessageListener launched_listener2("Launched", false);
859 launched_listener.Reply("reload");
860 ASSERT_TRUE(launched_listener2.WaitUntilSatisfied());
861 ASSERT_TRUE(GetFirstShellWindow());
862}
863
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000864namespace {
865
866// Simple observer to check for NOTIFICATION_EXTENSION_INSTALLED events to
867// ensure installation does or does not occur in certain scenarios.
868class CheckExtensionInstalledObserver : public content::NotificationObserver {
869 public:
870 CheckExtensionInstalledObserver() : seen_(false) {
871 registrar_.Add(this,
872 chrome::NOTIFICATION_EXTENSION_INSTALLED,
873 content::NotificationService::AllSources());
874 }
875
876 bool seen() const {
877 return seen_;
878 };
879
880 // NotificationObserver:
881 virtual void Observe(int type,
882 const content::NotificationSource& source,
883 const content::NotificationDetails& details) OVERRIDE {
884 EXPECT_FALSE(seen_);
885 seen_ = true;
886 }
887
888 private:
889 bool seen_;
890 content::NotificationRegistrar registrar_;
891};
892
893} // namespace
894
895// Component App Test 1 of 3: ensure that the initial load of a component
896// extension utilizing a background page (e.g. a v2 platform app) has its
897// background page run and is launchable. Waits for the Launched response from
898// the script resource in the opened shell window.
899IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
900 PRE_PRE_ComponentAppBackgroundPage) {
901 CheckExtensionInstalledObserver should_install;
902
903 // Ensure that we wait until the background page is run (to register the
904 // OnLaunched listener) before trying to open the application. This is similar
905 // to LoadAndLaunchPlatformApp, but we want to load as a component extension.
906 content::WindowedNotificationObserver app_loaded_observer(
907 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
908 content::NotificationService::AllSources());
909
910 const Extension* extension = LoadExtensionAsComponent(
911 test_data_dir_.AppendASCII("platform_apps").AppendASCII("component"));
912 ASSERT_TRUE(extension);
913
914 app_loaded_observer.Wait();
915 ASSERT_TRUE(should_install.seen());
916
917 ExtensionTestMessageListener launched_listener("Launched", false);
918 chrome::OpenApplication(chrome::AppLaunchParams(browser()->profile(),
919 extension,
920 extension_misc::LAUNCH_NONE,
921 NEW_WINDOW));
922
923 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
924}
925
926// Component App Test 2 of 3: ensure an installed component app can be launched
927// on a subsequent browser start, without requiring any install/upgrade logic
928// to be run, then perform setup for step 3.
929IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
930 PRE_ComponentAppBackgroundPage) {
931
932 // Since the component app is now installed, re-adding it in the same profile
933 // should not cause it to be re-installed. Instead, we wait for the OnLaunched
934 // in a different observer (which would timeout if not the app was not
935 // previously installed properly) and then check this observer to make sure it
936 // never saw the NOTIFICATION_EXTENSION_INSTALLED event.
937 CheckExtensionInstalledObserver should_not_install;
938 const Extension* extension = LoadExtensionAsComponent(
939 test_data_dir_.AppendASCII("platform_apps").AppendASCII("component"));
940 ASSERT_TRUE(extension);
941
942 ExtensionTestMessageListener launched_listener("Launched", false);
943 chrome::OpenApplication(chrome::AppLaunchParams(browser()->profile(),
944 extension,
945 extension_misc::LAUNCH_NONE,
946 NEW_WINDOW));
947
948 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
949 ASSERT_FALSE(should_not_install.seen());
950
951 // Simulate a "downgrade" from version 2 in the test manifest.json to 1.
952 ExtensionPrefs* extension_prefs =
953 extensions::ExtensionSystem::Get(browser()->profile())->
954 extension_service()->extension_prefs();
955
956 // Clear the registered events to ensure they are updated.
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100957 extensions::ExtensionSystem::Get(browser()->profile())->event_router()->
958 SetRegisteredEvents(extension->id(), std::set<std::string>());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000959
Ben Murdochca12bfa2013-07-23 11:17:05 +0100960 DictionaryPrefUpdate update(extension_prefs->pref_service(),
961 ExtensionPrefs::kExtensionsPref);
962 DictionaryValue* dict = update.Get();
963 std::string key(extension->id());
964 key += ".manifest.version";
965 dict->SetString(key, "1");
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000966}
967
968// Component App Test 3 of 3: simulate a component extension upgrade that
969// re-adds the OnLaunched event, and allows the app to be launched.
970IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ComponentAppBackgroundPage) {
971 CheckExtensionInstalledObserver should_install;
972 // Since we are forcing an upgrade, we need to wait for the load again.
973 content::WindowedNotificationObserver app_loaded_observer(
974 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
975 content::NotificationService::AllSources());
976
977 const Extension* extension = LoadExtensionAsComponent(
978 test_data_dir_.AppendASCII("platform_apps").AppendASCII("component"));
979 ASSERT_TRUE(extension);
980 app_loaded_observer.Wait();
981 ASSERT_TRUE(should_install.seen());
982
983 ExtensionTestMessageListener launched_listener("Launched", false);
984 chrome::OpenApplication(chrome::AppLaunchParams(browser()->profile(),
985 extension,
986 extension_misc::LAUNCH_NONE,
987 NEW_WINDOW));
988
989 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
990}
991
992// Flakes on Windows: http://crbug.com/171450
993#if defined(OS_WIN)
994#define MAYBE_Messaging DISABLED_Messaging
995#else
996#define MAYBE_Messaging Messaging
997#endif
998IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_Messaging) {
999 ExtensionApiTest::ResultCatcher result_catcher;
1000 LoadAndLaunchPlatformApp("messaging/app2");
1001 LoadAndLaunchPlatformApp("messaging/app1");
1002 EXPECT_TRUE(result_catcher.GetNextResult());
1003}
1004
1005// TODO(linux_aura) http://crbug.com/163931
1006#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
1007#define MAYBE_WebContentsHasFocus DISABLED_WebContentsHasFocus
1008#else
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001009// This test depends on focus and so needs to be in interactive_ui_tests.
1010// http://crbug.com/227041
1011#define MAYBE_WebContentsHasFocus DISABLED_WebContentsHasFocus
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001012#endif
1013IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_WebContentsHasFocus) {
1014 ExtensionTestMessageListener launched_listener("Launched", true);
1015 LoadAndLaunchPlatformApp("minimal");
1016 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
1017
1018 EXPECT_EQ(1LU, GetShellWindowCount());
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01001019 ShellWindowRegistry::ShellWindowList shell_windows = ShellWindowRegistry::Get(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001020 browser()->profile())->shell_windows();
1021 EXPECT_TRUE((*shell_windows.begin())->web_contents()->
1022 GetRenderWidgetHostView()->HasFocus());
1023}
1024
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001025
1026#if defined(OS_CHROMEOS)
1027
1028class PlatformAppIncognitoBrowserTest : public PlatformAppBrowserTest,
1029 public ShellWindowRegistry::Observer {
1030 public:
1031 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
1032 // Tell chromeos to launch in Guest mode, aka incognito.
1033 command_line->AppendSwitch(switches::kIncognito);
1034 PlatformAppBrowserTest::SetUpCommandLine(command_line);
1035 }
1036 virtual void SetUp() OVERRIDE {
1037 // Make sure the file manager actually gets loaded.
1038 ComponentLoader::EnableBackgroundExtensionsForTesting();
1039 PlatformAppBrowserTest::SetUp();
1040 }
1041
1042 // ShellWindowRegistry::Observer implementation.
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001043 virtual void OnShellWindowAdded(ShellWindow* shell_window) OVERRIDE {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001044 opener_app_ids_.insert(shell_window->extension()->id());
1045 }
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +01001046 virtual void OnShellWindowIconChanged(ShellWindow* shell_window) OVERRIDE {}
1047 virtual void OnShellWindowRemoved(ShellWindow* shell_window) OVERRIDE {}
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001048
1049 protected:
1050 // A set of ids of apps we've seen open a shell window.
1051 std::set<std::string> opener_app_ids_;
1052};
1053
1054IN_PROC_BROWSER_TEST_F(PlatformAppIncognitoBrowserTest, IncognitoComponentApp) {
1055 // Get the file manager app.
1056 const Extension* file_manager = extension_service()->GetExtensionById(
1057 "hhaomjibdihmijegdhdafkllkbggdgoj", false);
1058 ASSERT_TRUE(file_manager != NULL);
1059 Profile* incognito_profile = profile()->GetOffTheRecordProfile();
1060 ASSERT_TRUE(incognito_profile != NULL);
1061
1062 // Wait until the file manager has had a chance to register its listener
1063 // for the launch event.
1064 EventRouter* router = ExtensionSystem::Get(incognito_profile)->event_router();
1065 ASSERT_TRUE(router != NULL);
1066 while (!router->ExtensionHasEventListener(file_manager->id(),
1067 event_names::kOnLaunched)) {
1068 content::RunAllPendingInMessageLoop();
1069 }
1070
1071 // Listen for new shell windows so we see the file manager app launch itself.
1072 ShellWindowRegistry* registry = ShellWindowRegistry::Get(incognito_profile);
1073 ASSERT_TRUE(registry != NULL);
1074 registry->AddObserver(this);
1075
1076 chrome::AppLaunchParams params(incognito_profile, file_manager, 0);
1077 chrome::OpenApplication(params);
1078
1079 while (!ContainsKey(opener_app_ids_, file_manager->id())) {
1080 content::RunAllPendingInMessageLoop();
1081 }
1082}
1083
1084#endif // defined(OS_CHROMEOS)
1085
1086
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001087} // namespace extensions