1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "apps/app_window.h"
6 #include "apps/app_window_registry.h"
7 #include "apps/common/api/app_runtime.h"
8 #include "apps/launcher.h"
9 #include "apps/ui/native_app_window.h"
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/file_util.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/prefs/pref_service.h"
15 #include "base/stl_util.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "chrome/app/chrome_command_ids.h"
18 #include "chrome/browser/apps/app_browsertest_util.h"
19 #include "chrome/browser/chrome_notification_types.h"
20 #include "chrome/browser/devtools/devtools_window.h"
21 #include "chrome/browser/extensions/api/permissions/permissions_api.h"
22 #include "chrome/browser/extensions/component_loader.h"
23 #include "chrome/browser/extensions/extension_browsertest.h"
24 #include "chrome/browser/extensions/extension_service.h"
25 #include "chrome/browser/extensions/extension_test_message_listener.h"
26 #include "chrome/browser/renderer_context_menu/render_view_context_menu.h"
27 #include "chrome/browser/ui/browser.h"
28 #include "chrome/browser/ui/extensions/application_launch.h"
29 #include "chrome/browser/ui/tabs/tab_strip_model.h"
30 #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
31 #include "chrome/common/chrome_switches.h"
32 #include "chrome/common/pref_names.h"
33 #include "chrome/common/url_constants.h"
34 #include "chrome/test/base/test_switches.h"
35 #include "chrome/test/base/ui_test_utils.h"
36 #include "components/pref_registry/pref_registry_syncable.h"
37 #include "components/web_modal/web_contents_modal_dialog_manager.h"
38 #include "content/public/browser/devtools_agent_host.h"
39 #include "content/public/browser/render_process_host.h"
40 #include "content/public/browser/render_widget_host_view.h"
41 #include "content/public/test/test_utils.h"
42 #include "extensions/browser/event_router.h"
43 #include "extensions/browser/extension_prefs.h"
44 #include "extensions/browser/extension_system.h"
45 #include "extensions/browser/pref_names.h"
46 #include "net/test/embedded_test_server/embedded_test_server.h"
47 #include "url/gurl.h"
48
49 #if defined(OS_CHROMEOS)
50 #include "base/memory/scoped_ptr.h"
51 #include "chrome/browser/chromeos/login/users/mock_user_manager.h"
52 #include "chrome/browser/chromeos/login/users/user_manager.h"
53 #include "chromeos/dbus/dbus_thread_manager.h"
54 #include "chromeos/dbus/fake_dbus_thread_manager.h"
55 #include "chromeos/dbus/fake_power_manager_client.h"
56 #endif
57
58 using apps::AppWindow;
59 using apps::AppWindowRegistry;
60 using content::WebContents;
61 using web_modal::WebContentsModalDialogManager;
62
63 namespace app_runtime = apps::api::app_runtime;
64
65 namespace extensions {
66
67 namespace {
68
69 // Non-abstract RenderViewContextMenu class.
70 class PlatformAppContextMenu : public RenderViewContextMenu {
71 public:
PlatformAppContextMenu(content::RenderFrameHost * render_frame_host,const content::ContextMenuParams & params)72 PlatformAppContextMenu(content::RenderFrameHost* render_frame_host,
73 const content::ContextMenuParams& params)
74 : RenderViewContextMenu(render_frame_host, params) {}
75
HasCommandWithId(int command_id)76 bool HasCommandWithId(int command_id) {
77 return menu_model_.GetIndexOfCommandId(command_id) != -1;
78 }
79
80 protected:
81 // RenderViewContextMenu implementation.
GetAcceleratorForCommandId(int command_id,ui::Accelerator * accelerator)82 virtual bool GetAcceleratorForCommandId(
83 int command_id,
84 ui::Accelerator* accelerator) OVERRIDE {
85 return false;
86 }
PlatformInit()87 virtual void PlatformInit() OVERRIDE {}
PlatformCancel()88 virtual void PlatformCancel() OVERRIDE {}
89 };
90
91 // This class keeps track of tabs as they are added to the browser. It will be
92 // "done" (i.e. won't block on Wait()) once |observations| tabs have been added.
93 class TabsAddedNotificationObserver
94 : public content::WindowedNotificationObserver {
95 public:
TabsAddedNotificationObserver(size_t observations)96 explicit TabsAddedNotificationObserver(size_t observations)
97 : content::WindowedNotificationObserver(
98 chrome::NOTIFICATION_TAB_ADDED,
99 content::NotificationService::AllSources()),
100 observations_(observations) {
101 }
102
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)103 virtual void Observe(int type,
104 const content::NotificationSource& source,
105 const content::NotificationDetails& details) OVERRIDE {
106 observed_tabs_.push_back(
107 content::Details<WebContents>(details).ptr());
108 if (observed_tabs_.size() == observations_)
109 content::WindowedNotificationObserver::Observe(type, source, details);
110 }
111
tabs()112 const std::vector<content::WebContents*>& tabs() { return observed_tabs_; }
113
114 private:
115 size_t observations_;
116 std::vector<content::WebContents*> observed_tabs_;
117
118 DISALLOW_COPY_AND_ASSIGN(TabsAddedNotificationObserver);
119 };
120
121 class ScopedPreviewTestingDelegate : PrintPreviewUI::TestingDelegate {
122 public:
ScopedPreviewTestingDelegate(bool auto_cancel)123 explicit ScopedPreviewTestingDelegate(bool auto_cancel)
124 : auto_cancel_(auto_cancel),
125 total_page_count_(1),
126 rendered_page_count_(0) {
127 PrintPreviewUI::SetDelegateForTesting(this);
128 }
129
~ScopedPreviewTestingDelegate()130 ~ScopedPreviewTestingDelegate() {
131 PrintPreviewUI::SetDelegateForTesting(NULL);
132 }
133
134 // PrintPreviewUI::TestingDelegate implementation.
IsAutoCancelEnabled()135 virtual bool IsAutoCancelEnabled() OVERRIDE {
136 return auto_cancel_;
137 }
138
139 // PrintPreviewUI::TestingDelegate implementation.
DidGetPreviewPageCount(int page_count)140 virtual void DidGetPreviewPageCount(int page_count) OVERRIDE {
141 total_page_count_ = page_count;
142 }
143
144 // PrintPreviewUI::TestingDelegate implementation.
DidRenderPreviewPage(content::WebContents * preview_dialog)145 virtual void DidRenderPreviewPage(content::WebContents* preview_dialog)
146 OVERRIDE {
147 dialog_size_ = preview_dialog->GetContainerBounds().size();
148 ++rendered_page_count_;
149 CHECK(rendered_page_count_ <= total_page_count_);
150 if (waiting_runner_ && rendered_page_count_ == total_page_count_) {
151 waiting_runner_->Quit();
152 }
153 }
154
WaitUntilPreviewIsReady()155 void WaitUntilPreviewIsReady() {
156 CHECK(!waiting_runner_);
157 if (rendered_page_count_ < total_page_count_) {
158 waiting_runner_ = new content::MessageLoopRunner;
159 waiting_runner_->Run();
160 waiting_runner_ = NULL;
161 }
162 }
163
dialog_size()164 gfx::Size dialog_size() {
165 return dialog_size_;
166 }
167
168 private:
169 bool auto_cancel_;
170 int total_page_count_;
171 int rendered_page_count_;
172 scoped_refptr<content::MessageLoopRunner> waiting_runner_;
173 gfx::Size dialog_size_;
174 };
175
176 #if !defined(OS_CHROMEOS) && !defined(OS_WIN)
CopyTestDataAndSetCommandLineArg(const base::FilePath & test_data_file,const base::FilePath & temp_dir,const char * filename)177 bool CopyTestDataAndSetCommandLineArg(
178 const base::FilePath& test_data_file,
179 const base::FilePath& temp_dir,
180 const char* filename) {
181 base::FilePath path = temp_dir.AppendASCII(
182 filename).NormalizePathSeparators();
183 if (!(base::CopyFile(test_data_file, path)))
184 return false;
185
186 CommandLine* command_line = CommandLine::ForCurrentProcess();
187 command_line->AppendArgPath(path);
188 return true;
189 }
190 #endif // !defined(OS_CHROMEOS) && !defined(OS_WIN)
191
192 #if !defined(OS_CHROMEOS)
193 const char kTestFilePath[] = "platform_apps/launch_files/test.txt";
194 #endif
195
196 } // namespace
197
198 // Tests that CreateAppWindow doesn't crash if you close it straight away.
199 // LauncherPlatformAppBrowserTest relies on this behaviour, but is only run for
200 // ash, so we test that it works here.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,CreateAndCloseAppWindow)201 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, CreateAndCloseAppWindow) {
202 const Extension* extension = LoadAndLaunchPlatformApp("minimal", "Launched");
203 AppWindow* window = CreateAppWindow(extension);
204 CloseAppWindow(window);
205 }
206
207 // Tests that platform apps received the "launch" event when launched.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,OnLaunchedEvent)208 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, OnLaunchedEvent) {
209 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch")) << message_;
210 }
211
212 // Tests that platform apps cannot use certain disabled window properties, but
213 // can override them and then use them.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,DisabledWindowProperties)214 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisabledWindowProperties) {
215 ASSERT_TRUE(RunPlatformAppTest("platform_apps/disabled_window_properties"))
216 << message_;
217 }
218
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,EmptyContextMenu)219 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, EmptyContextMenu) {
220 LoadAndLaunchPlatformApp("minimal", "Launched");
221
222 // The empty app doesn't add any context menu items, so its menu should
223 // only include the developer tools.
224 WebContents* web_contents = GetFirstAppWindowWebContents();
225 ASSERT_TRUE(web_contents);
226 content::ContextMenuParams params;
227 scoped_ptr<PlatformAppContextMenu> menu;
228 menu.reset(new PlatformAppContextMenu(web_contents->GetMainFrame(), params));
229 menu->Init();
230 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
231 ASSERT_TRUE(
232 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
233 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
234 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
235 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
236 }
237
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,AppWithContextMenu)238 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenu) {
239 LoadAndLaunchPlatformApp("context_menu", "Launched");
240
241 // The context_menu app has two context menu items. These, along with a
242 // separator and the developer tools, is all that should be in the menu.
243 WebContents* web_contents = GetFirstAppWindowWebContents();
244 ASSERT_TRUE(web_contents);
245 content::ContextMenuParams params;
246 scoped_ptr<PlatformAppContextMenu> menu;
247 menu.reset(new PlatformAppContextMenu(web_contents->GetMainFrame(), params));
248 menu->Init();
249 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
250 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST + 1));
251 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
252 ASSERT_TRUE(
253 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
254 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
255 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
256 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
257 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
258 }
259
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,InstalledAppWithContextMenu)260 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, InstalledAppWithContextMenu) {
261 ExtensionTestMessageListener launched_listener("Launched", false);
262 InstallAndLaunchPlatformApp("context_menu");
263
264 // Wait for the extension to tell us it's initialized its context menus and
265 // launched a window.
266 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
267
268 // The context_menu app has two context menu items. For an installed app
269 // these are all that should be in the menu.
270 WebContents* web_contents = GetFirstAppWindowWebContents();
271 ASSERT_TRUE(web_contents);
272 content::ContextMenuParams params;
273 scoped_ptr<PlatformAppContextMenu> menu;
274 menu.reset(new PlatformAppContextMenu(web_contents->GetMainFrame(), params));
275 menu->Init();
276 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
277 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST + 1));
278 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
279 ASSERT_FALSE(
280 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
281 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
282 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
283 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
284 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
285 }
286
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,AppWithContextMenuTextField)287 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenuTextField) {
288 LoadAndLaunchPlatformApp("context_menu", "Launched");
289
290 // The context_menu app has one context menu item. This, along with a
291 // separator and the developer tools, is all that should be in the menu.
292 WebContents* web_contents = GetFirstAppWindowWebContents();
293 ASSERT_TRUE(web_contents);
294 content::ContextMenuParams params;
295 params.is_editable = true;
296 scoped_ptr<PlatformAppContextMenu> menu;
297 menu.reset(new PlatformAppContextMenu(web_contents->GetMainFrame(), params));
298 menu->Init();
299 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
300 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
301 ASSERT_TRUE(
302 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
303 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
304 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
305 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_COPY));
306 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
307 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
308 }
309
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,AppWithContextMenuSelection)310 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenuSelection) {
311 LoadAndLaunchPlatformApp("context_menu", "Launched");
312
313 // The context_menu app has one context menu item. This, along with a
314 // separator and the developer tools, is all that should be in the menu.
315 WebContents* web_contents = GetFirstAppWindowWebContents();
316 ASSERT_TRUE(web_contents);
317 content::ContextMenuParams params;
318 params.selection_text = base::ASCIIToUTF16("Hello World");
319 scoped_ptr<PlatformAppContextMenu> menu;
320 menu.reset(new PlatformAppContextMenu(web_contents->GetMainFrame(), params));
321 menu->Init();
322 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
323 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTELEMENT));
324 ASSERT_TRUE(
325 menu->HasCommandWithId(IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE));
326 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP));
327 ASSERT_FALSE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_UNDO));
328 ASSERT_TRUE(menu->HasCommandWithId(IDC_CONTENT_CONTEXT_COPY));
329 ASSERT_FALSE(menu->HasCommandWithId(IDC_BACK));
330 ASSERT_FALSE(menu->HasCommandWithId(IDC_SAVE_PAGE));
331 }
332
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,AppWithContextMenuClicked)333 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, AppWithContextMenuClicked) {
334 LoadAndLaunchPlatformApp("context_menu_click", "Launched");
335
336 // Test that the menu item shows up
337 WebContents* web_contents = GetFirstAppWindowWebContents();
338 ASSERT_TRUE(web_contents);
339 content::ContextMenuParams params;
340 params.page_url = GURL("http://foo.bar");
341 scoped_ptr<PlatformAppContextMenu> menu;
342 menu.reset(new PlatformAppContextMenu(web_contents->GetMainFrame(), params));
343 menu->Init();
344 ASSERT_TRUE(menu->HasCommandWithId(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST));
345
346 // Execute the menu item
347 ExtensionTestMessageListener onclicked_listener("onClicked fired for id1",
348 false);
349 menu->ExecuteCommand(IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST, 0);
350
351 ASSERT_TRUE(onclicked_listener.WaitUntilSatisfied());
352 }
353
354 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
355 // TODO(erg): linux_aura bringup: http://crbug.com/163931
356 #define MAYBE_DisallowNavigation DISABLED_DisallowNavigation
357 #else
358 #define MAYBE_DisallowNavigation DisallowNavigation
359 #endif
360
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,MAYBE_DisallowNavigation)361 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_DisallowNavigation) {
362 TabsAddedNotificationObserver observer(2);
363
364 ASSERT_TRUE(StartEmbeddedTestServer());
365 ASSERT_TRUE(RunPlatformAppTest("platform_apps/navigation")) << message_;
366
367 observer.Wait();
368 ASSERT_EQ(2U, observer.tabs().size());
369 EXPECT_EQ(std::string(chrome::kExtensionInvalidRequestURL),
370 observer.tabs()[0]->GetURL().spec());
371 EXPECT_EQ("http://chromium.org/",
372 observer.tabs()[1]->GetURL().spec());
373 }
374
375 // Failing on some Win and Linux buildbots. See crbug.com/354425.
376 #if (defined(OS_WIN) || defined(OS_LINUX)) && defined(ARCH_CPU_X86)
377 #define MAYBE_Iframes DISABLED_Iframes
378 #else
379 #define MAYBE_Iframes Iframes
380 #endif
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,MAYBE_Iframes)381 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_Iframes) {
382 ASSERT_TRUE(StartEmbeddedTestServer());
383 ASSERT_TRUE(RunPlatformAppTest("platform_apps/iframes")) << message_;
384 }
385
386 // Tests that localStorage and WebSQL are disabled for platform apps.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,DisallowStorage)387 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, DisallowStorage) {
388 ASSERT_TRUE(RunPlatformAppTest("platform_apps/storage")) << message_;
389 }
390
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,Restrictions)391 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Restrictions) {
392 ASSERT_TRUE(RunPlatformAppTest("platform_apps/restrictions")) << message_;
393 }
394
395 // Tests that extensions can't use platform-app-only APIs.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,PlatformAppsOnly)396 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, PlatformAppsOnly) {
397 ASSERT_TRUE(RunExtensionTestIgnoreManifestWarnings(
398 "platform_apps/apps_only")) << message_;
399 }
400
401 // Tests that platform apps have isolated storage by default.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,Isolation)402 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Isolation) {
403 ASSERT_TRUE(StartEmbeddedTestServer());
404
405 // Load a (non-app) page under the "localhost" origin that sets a cookie.
406 GURL set_cookie_url = embedded_test_server()->GetURL(
407 "/extensions/platform_apps/isolation/set_cookie.html");
408 GURL::Replacements replace_host;
409 std::string host_str("localhost"); // Must stay in scope with replace_host.
410 replace_host.SetHostStr(host_str);
411 set_cookie_url = set_cookie_url.ReplaceComponents(replace_host);
412
413 ui_test_utils::NavigateToURLWithDisposition(
414 browser(), set_cookie_url,
415 CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
416
417 // Make sure the cookie is set.
418 int cookie_size;
419 std::string cookie_value;
420 ui_test_utils::GetCookies(
421 set_cookie_url,
422 browser()->tab_strip_model()->GetWebContentsAt(0),
423 &cookie_size,
424 &cookie_value);
425 ASSERT_EQ("testCookie=1", cookie_value);
426
427 // Let the platform app request the same URL, and make sure that it doesn't
428 // see the cookie.
429 ASSERT_TRUE(RunPlatformAppTest("platform_apps/isolation")) << message_;
430 }
431
432 // See crbug.com/248441
433 #if defined(OS_WIN)
434 #define MAYBE_ExtensionWindowingApis DISABLED_ExtensionWindowingApis
435 #else
436 #define MAYBE_ExtensionWindowingApis ExtensionWindowingApis
437 #endif
438
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,MAYBE_ExtensionWindowingApis)439 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_ExtensionWindowingApis) {
440 // Initially there should be just the one browser window visible to the
441 // extensions API.
442 const Extension* extension = LoadExtension(
443 test_data_dir_.AppendASCII("common/background_page"));
444 ASSERT_EQ(1U, RunGetWindowsFunctionForExtension(extension));
445
446 // And no app windows.
447 ASSERT_EQ(0U, GetAppWindowCount());
448
449 // Launch a platform app that shows a window.
450 LoadAndLaunchPlatformApp("minimal", "Launched");
451 ASSERT_EQ(1U, GetAppWindowCount());
452 int app_window_id = GetFirstAppWindow()->session_id().id();
453
454 // But it's not visible to the extensions API, it still thinks there's just
455 // one browser window.
456 ASSERT_EQ(1U, RunGetWindowsFunctionForExtension(extension));
457 // It can't look it up by ID either
458 ASSERT_FALSE(RunGetWindowFunctionForExtension(app_window_id, extension));
459
460 // The app can also only see one window (its own).
461 // TODO(jeremya): add an extension function to get an app window by ID, and
462 // to get a list of all the app windows, so we can test this.
463
464 // Launch another platform app that also shows a window.
465 LoadAndLaunchPlatformApp("context_menu", "Launched");
466
467 // There are two total app windows, but each app can only see its own.
468 ASSERT_EQ(2U, GetAppWindowCount());
469 // TODO(jeremya): as above, this requires more extension functions.
470 }
471
472 // ChromeOS does not support passing arguments on the command line, so the tests
473 // that rely on this functionality are disabled.
474 #if !defined(OS_CHROMEOS)
475 // Tests that command line parameters get passed through to platform apps
476 // via launchData correctly when launching with a file.
477 // TODO(benwells/jeremya): tests need a way to specify a handler ID.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,LaunchWithFile)478 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithFile) {
479 SetCommandLineArg(kTestFilePath);
480 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_file"))
481 << message_;
482 }
483
484 // Tests that relative paths can be passed through to the platform app.
485 // This test doesn't use the normal test infrastructure as it needs to open
486 // the application differently to all other platform app tests, by setting
487 // the AppLaunchParams.current_directory field.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,LaunchWithRelativeFile)488 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithRelativeFile) {
489 // Setup the command line
490 ClearCommandLineArgs();
491 CommandLine* command_line = CommandLine::ForCurrentProcess();
492 base::FilePath relative_test_doc =
493 base::FilePath::FromUTF8Unsafe(kTestFilePath);
494 relative_test_doc = relative_test_doc.NormalizePathSeparators();
495 command_line->AppendArgPath(relative_test_doc);
496
497 // Load the extension
498 ResultCatcher catcher;
499 const Extension* extension = LoadExtension(
500 test_data_dir_.AppendASCII("platform_apps/launch_file"));
501 ASSERT_TRUE(extension);
502
503 // Run the test
504 AppLaunchParams params(
505 browser()->profile(), extension, LAUNCH_CONTAINER_NONE, NEW_WINDOW);
506 params.command_line = *CommandLine::ForCurrentProcess();
507 params.current_directory = test_data_dir_;
508 OpenApplication(params);
509
510 if (!catcher.GetNextResult()) {
511 message_ = catcher.message();
512 ASSERT_TRUE(0);
513 }
514 }
515
516 // Tests that launch data is sent through if the file extension matches.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,LaunchWithFileExtension)517 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithFileExtension) {
518 SetCommandLineArg(kTestFilePath);
519 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_file_by_extension"))
520 << message_;
521 }
522
523 // Tests that launch data is sent through to a whitelisted extension if the file
524 // extension matches.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,LaunchWhiteListedExtensionWithFile)525 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
526 LaunchWhiteListedExtensionWithFile) {
527 SetCommandLineArg(kTestFilePath);
528 ASSERT_TRUE(RunPlatformAppTest(
529 "platform_apps/launch_whitelisted_ext_with_file"))
530 << message_;
531 }
532
533 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
534 // TODO(erg): linux_aura bringup: http://crbug.com/163931
535 #define MAYBE_LaunchWithFileExtensionAndMimeType DISABLED_LaunchWithFileExtensionAndMimeType
536 #else
537 #define MAYBE_LaunchWithFileExtensionAndMimeType LaunchWithFileExtensionAndMimeType
538 #endif
539
540 // Tests that launch data is sent through if the file extension and MIME type
541 // both match.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,MAYBE_LaunchWithFileExtensionAndMimeType)542 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
543 MAYBE_LaunchWithFileExtensionAndMimeType) {
544 SetCommandLineArg(kTestFilePath);
545 ASSERT_TRUE(RunPlatformAppTest(
546 "platform_apps/launch_file_by_extension_and_type")) << message_;
547 }
548
549 // Tests that launch data is sent through for a file with no extension if a
550 // handler accepts "".
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,LaunchWithFileWithoutExtension)551 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithFileWithoutExtension) {
552 SetCommandLineArg("platform_apps/launch_files/test");
553 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_file_with_no_extension"))
554 << message_;
555 }
556
557 #if !defined(OS_WIN)
558 // Tests that launch data is sent through for a file with an empty extension if
559 // a handler accepts "".
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,LaunchWithFileEmptyExtension)560 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithFileEmptyExtension) {
561 base::ScopedTempDir temp_dir;
562 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
563 ClearCommandLineArgs();
564 ASSERT_TRUE(CopyTestDataAndSetCommandLineArg(
565 test_data_dir_.AppendASCII(kTestFilePath),
566 temp_dir.path(),
567 "test."));
568 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_file_with_no_extension"))
569 << message_;
570 }
571
572 // Tests that launch data is sent through for a file with an empty extension if
573 // a handler accepts *.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,LaunchWithFileEmptyExtensionAcceptAny)574 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
575 LaunchWithFileEmptyExtensionAcceptAny) {
576 base::ScopedTempDir temp_dir;
577 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
578 ClearCommandLineArgs();
579 ASSERT_TRUE(CopyTestDataAndSetCommandLineArg(
580 test_data_dir_.AppendASCII(kTestFilePath),
581 temp_dir.path(),
582 "test."));
583 ASSERT_TRUE(RunPlatformAppTest(
584 "platform_apps/launch_file_with_any_extension")) << message_;
585 }
586 #endif
587
588 // Tests that launch data is sent through for a file with no extension if a
589 // handler accepts *.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,LaunchWithFileWithoutExtensionAcceptAny)590 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
591 LaunchWithFileWithoutExtensionAcceptAny) {
592 SetCommandLineArg("platform_apps/launch_files/test");
593 ASSERT_TRUE(RunPlatformAppTest(
594 "platform_apps/launch_file_with_any_extension")) << message_;
595 }
596
597 // Tests that launch data is sent through for a file with an extension if a
598 // handler accepts *.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,LaunchWithFileAcceptAnyExtension)599 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
600 LaunchWithFileAcceptAnyExtension) {
601 SetCommandLineArg(kTestFilePath);
602 ASSERT_TRUE(RunPlatformAppTest(
603 "platform_apps/launch_file_with_any_extension")) << message_;
604 }
605
606 // Tests that no launch data is sent through if the file has the wrong
607 // extension.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,LaunchWithWrongExtension)608 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithWrongExtension) {
609 SetCommandLineArg(kTestFilePath);
610 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_wrong_extension"))
611 << message_;
612 }
613
614 // Tests that no launch data is sent through if the file has no extension but
615 // the handler requires a specific extension.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,LaunchWithWrongEmptyExtension)616 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithWrongEmptyExtension) {
617 SetCommandLineArg("platform_apps/launch_files/test");
618 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_wrong_extension"))
619 << message_;
620 }
621
622 // Tests that no launch data is sent through if the file is of the wrong MIME
623 // type.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,LaunchWithWrongType)624 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithWrongType) {
625 SetCommandLineArg(kTestFilePath);
626 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_wrong_type"))
627 << message_;
628 }
629
630 // Tests that no launch data is sent through if the platform app does not
631 // provide an intent.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,LaunchWithNoIntent)632 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithNoIntent) {
633 SetCommandLineArg(kTestFilePath);
634 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_no_intent"))
635 << message_;
636 }
637
638 // Tests that launch data is sent through when the file has unknown extension
639 // but the MIME type can be sniffed and the sniffed type matches.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,LaunchWithSniffableType)640 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithSniffableType) {
641 SetCommandLineArg("platform_apps/launch_files/test.unknownextension");
642 ASSERT_TRUE(RunPlatformAppTest(
643 "platform_apps/launch_file_by_extension_and_type")) << message_;
644 }
645
646 // Tests that launch data is sent through with the MIME type set to
647 // application/octet-stream if the file MIME type cannot be read.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,LaunchNoType)648 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchNoType) {
649 SetCommandLineArg("platform_apps/launch_files/test_binary.unknownextension");
650 ASSERT_TRUE(RunPlatformAppTest(
651 "platform_apps/launch_application_octet_stream")) << message_;
652 }
653
654 // Tests that no launch data is sent through if the file does not exist.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,LaunchNoFile)655 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchNoFile) {
656 SetCommandLineArg("platform_apps/launch_files/doesnotexist.txt");
657 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_invalid"))
658 << message_;
659 }
660
661 // Tests that no launch data is sent through if the argument is a directory.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,LaunchWithDirectory)662 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithDirectory) {
663 SetCommandLineArg("platform_apps/launch_files");
664 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_invalid"))
665 << message_;
666 }
667
668 // Tests that no launch data is sent through if there are no arguments passed
669 // on the command line
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,LaunchWithNothing)670 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchWithNothing) {
671 ClearCommandLineArgs();
672 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_nothing"))
673 << message_;
674 }
675
676 // Test that platform apps can use the chrome.fileSystem.getDisplayPath
677 // function to get the native file system path of a file they are launched with.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,GetDisplayPath)678 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, GetDisplayPath) {
679 SetCommandLineArg(kTestFilePath);
680 ASSERT_TRUE(RunPlatformAppTest("platform_apps/get_display_path"))
681 << message_;
682 }
683
684 // Tests that the file is created if the file does not exist and the app has the
685 // fileSystem.write permission.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,LaunchNewFile)686 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, LaunchNewFile) {
687 base::ScopedTempDir temp_dir;
688 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
689 ClearCommandLineArgs();
690 CommandLine* command_line = CommandLine::ForCurrentProcess();
691 command_line->AppendArgPath(temp_dir.path().AppendASCII("new_file.txt"));
692 ASSERT_TRUE(RunPlatformAppTest("platform_apps/launch_new_file")) << message_;
693 }
694
695 #endif // !defined(OS_CHROMEOS)
696
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,OpenLink)697 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, OpenLink) {
698 ASSERT_TRUE(StartEmbeddedTestServer());
699 content::WindowedNotificationObserver observer(
700 chrome::NOTIFICATION_TAB_ADDED,
701 content::Source<content::WebContentsDelegate>(browser()));
702 LoadAndLaunchPlatformApp("open_link", "Launched");
703 observer.Wait();
704 ASSERT_EQ(2, browser()->tab_strip_model()->count());
705 }
706
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,MutationEventsDisabled)707 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MutationEventsDisabled) {
708 ASSERT_TRUE(RunPlatformAppTest("platform_apps/mutation_events")) << message_;
709 }
710
711 // This appears to be unreliable on linux.
712 // TODO(stevenjb): Investigate and enable
713 #if defined(OS_LINUX) && !defined(USE_ASH)
714 #define MAYBE_AppWindowRestoreState DISABLED_AppWindowRestoreState
715 #else
716 #define MAYBE_AppWindowRestoreState AppWindowRestoreState
717 #endif
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,MAYBE_AppWindowRestoreState)718 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_AppWindowRestoreState) {
719 ASSERT_TRUE(RunPlatformAppTest("platform_apps/restore_state"));
720 }
721
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,AppWindowAdjustBoundsToBeVisibleOnScreen)722 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
723 AppWindowAdjustBoundsToBeVisibleOnScreen) {
724 const Extension* extension = LoadAndLaunchPlatformApp("minimal", "Launched");
725
726 AppWindow* window = CreateAppWindow(extension);
727
728 // The screen bounds didn't change, the cached bounds didn't need to adjust.
729 gfx::Rect cached_bounds(80, 100, 400, 400);
730 gfx::Rect cached_screen_bounds(0, 0, 1600, 900);
731 gfx::Rect current_screen_bounds(0, 0, 1600, 900);
732 gfx::Size minimum_size(200, 200);
733 gfx::Rect bounds;
734 CallAdjustBoundsToBeVisibleOnScreenForAppWindow(window,
735 cached_bounds,
736 cached_screen_bounds,
737 current_screen_bounds,
738 minimum_size,
739 &bounds);
740 EXPECT_EQ(bounds, cached_bounds);
741
742 // We have an empty screen bounds, the cached bounds didn't need to adjust.
743 gfx::Rect empty_screen_bounds;
744 CallAdjustBoundsToBeVisibleOnScreenForAppWindow(window,
745 cached_bounds,
746 empty_screen_bounds,
747 current_screen_bounds,
748 minimum_size,
749 &bounds);
750 EXPECT_EQ(bounds, cached_bounds);
751
752 // Cached bounds is completely off the new screen bounds in horizontal
753 // locations. Expect to reposition the bounds.
754 gfx::Rect horizontal_out_of_screen_bounds(-800, 100, 400, 400);
755 CallAdjustBoundsToBeVisibleOnScreenForAppWindow(
756 window,
757 horizontal_out_of_screen_bounds,
758 gfx::Rect(-1366, 0, 1600, 900),
759 current_screen_bounds,
760 minimum_size,
761 &bounds);
762 EXPECT_EQ(bounds, gfx::Rect(0, 100, 400, 400));
763
764 // Cached bounds is completely off the new screen bounds in vertical
765 // locations. Expect to reposition the bounds.
766 gfx::Rect vertical_out_of_screen_bounds(10, 1000, 400, 400);
767 CallAdjustBoundsToBeVisibleOnScreenForAppWindow(
768 window,
769 vertical_out_of_screen_bounds,
770 gfx::Rect(-1366, 0, 1600, 900),
771 current_screen_bounds,
772 minimum_size,
773 &bounds);
774 EXPECT_EQ(bounds, gfx::Rect(10, 500, 400, 400));
775
776 // From a large screen resulotion to a small one. Expect it fit on screen.
777 gfx::Rect big_cache_bounds(10, 10, 1000, 1000);
778 CallAdjustBoundsToBeVisibleOnScreenForAppWindow(window,
779 big_cache_bounds,
780 gfx::Rect(0, 0, 1600, 1000),
781 gfx::Rect(0, 0, 800, 600),
782 minimum_size,
783 &bounds);
784 EXPECT_EQ(bounds, gfx::Rect(0, 0, 800, 600));
785
786 // Don't resize the bounds smaller than minimum size, when the minimum size is
787 // larger than the screen.
788 CallAdjustBoundsToBeVisibleOnScreenForAppWindow(window,
789 big_cache_bounds,
790 gfx::Rect(0, 0, 1600, 1000),
791 gfx::Rect(0, 0, 800, 600),
792 gfx::Size(900, 900),
793 &bounds);
794 EXPECT_EQ(bounds, gfx::Rect(0, 0, 900, 900));
795 }
796
797 namespace {
798
799 class PlatformAppDevToolsBrowserTest : public PlatformAppBrowserTest {
800 protected:
801 enum TestFlags {
802 RELAUNCH = 0x1,
803 HAS_ID = 0x2,
804 };
805 // Runs a test inside a harness that opens DevTools on an app window.
806 void RunTestWithDevTools(const char* name, int test_flags);
807 };
808
RunTestWithDevTools(const char * name,int test_flags)809 void PlatformAppDevToolsBrowserTest::RunTestWithDevTools(
810 const char* name, int test_flags) {
811 using content::DevToolsAgentHost;
812 const Extension* extension = LoadAndLaunchPlatformApp(name, "Launched");
813 ASSERT_TRUE(extension);
814 AppWindow* window = GetFirstAppWindow();
815 ASSERT_TRUE(window);
816 ASSERT_EQ(window->window_key().empty(), (test_flags & HAS_ID) == 0);
817 content::RenderViewHost* rvh = window->web_contents()->GetRenderViewHost();
818 ASSERT_TRUE(rvh);
819
820 // Ensure no DevTools open for the AppWindow, then open one.
821 ASSERT_FALSE(DevToolsAgentHost::HasFor(rvh));
822 DevToolsWindow::OpenDevToolsWindow(rvh);
823 ASSERT_TRUE(DevToolsAgentHost::HasFor(rvh));
824
825 if (test_flags & RELAUNCH) {
826 // Close the AppWindow, and ensure it is gone.
827 CloseAppWindow(window);
828 ASSERT_FALSE(GetFirstAppWindow());
829
830 // Relaunch the app and get a new AppWindow.
831 content::WindowedNotificationObserver app_loaded_observer(
832 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
833 content::NotificationService::AllSources());
834 OpenApplication(AppLaunchParams(
835 browser()->profile(), extension, LAUNCH_CONTAINER_NONE, NEW_WINDOW));
836 app_loaded_observer.Wait();
837 window = GetFirstAppWindow();
838 ASSERT_TRUE(window);
839
840 // DevTools should have reopened with the relaunch.
841 rvh = window->web_contents()->GetRenderViewHost();
842 ASSERT_TRUE(rvh);
843 ASSERT_TRUE(DevToolsAgentHost::HasFor(rvh));
844 }
845 }
846
847 } // namespace
848
849 // http://crbug.com/246634
850 #if defined(OS_CHROMEOS)
851 #define MAYBE_ReOpenedWithID DISABLED_ReOpenedWithID
852 #else
853 #define MAYBE_ReOpenedWithID ReOpenedWithID
854 #endif
IN_PROC_BROWSER_TEST_F(PlatformAppDevToolsBrowserTest,MAYBE_ReOpenedWithID)855 IN_PROC_BROWSER_TEST_F(PlatformAppDevToolsBrowserTest, MAYBE_ReOpenedWithID) {
856 #if defined(OS_WIN) && defined(USE_ASH)
857 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
858 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
859 return;
860 #endif
861 RunTestWithDevTools("minimal_id", RELAUNCH | HAS_ID);
862 }
863
864 // http://crbug.com/246999
865 #if defined(OS_CHROMEOS) || defined(OS_WIN)
866 #define MAYBE_ReOpenedWithURL DISABLED_ReOpenedWithURL
867 #else
868 #define MAYBE_ReOpenedWithURL ReOpenedWithURL
869 #endif
IN_PROC_BROWSER_TEST_F(PlatformAppDevToolsBrowserTest,MAYBE_ReOpenedWithURL)870 IN_PROC_BROWSER_TEST_F(PlatformAppDevToolsBrowserTest, MAYBE_ReOpenedWithURL) {
871 RunTestWithDevTools("minimal", RELAUNCH);
872 }
873
874 // Test that showing a permission request as a constrained window works and is
875 // correctly parented.
876 #if defined(OS_MACOSX)
877 #define MAYBE_ConstrainedWindowRequest DISABLED_ConstrainedWindowRequest
878 #else
879 // TODO(sail): Enable this on other platforms once http://crbug.com/95455 is
880 // fixed.
881 #define MAYBE_ConstrainedWindowRequest DISABLED_ConstrainedWindowRequest
882 #endif
883
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,MAYBE_ConstrainedWindowRequest)884 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_ConstrainedWindowRequest) {
885 PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
886 const Extension* extension =
887 LoadAndLaunchPlatformApp("optional_permission_request", "Launched");
888 ASSERT_TRUE(extension) << "Failed to load extension.";
889
890 WebContents* web_contents = GetFirstAppWindowWebContents();
891 ASSERT_TRUE(web_contents);
892
893 // Verify that the app window has a dialog attached.
894 WebContentsModalDialogManager* web_contents_modal_dialog_manager =
895 WebContentsModalDialogManager::FromWebContents(web_contents);
896 EXPECT_TRUE(web_contents_modal_dialog_manager->IsDialogActive());
897
898 // Close the constrained window and wait for the reply to the permission
899 // request.
900 ExtensionTestMessageListener listener("PermissionRequestDone", false);
901 WebContentsModalDialogManager::TestApi test_api(
902 web_contents_modal_dialog_manager);
903 test_api.CloseAllDialogs();
904 ASSERT_TRUE(listener.WaitUntilSatisfied());
905 }
906
907 // Tests that an app calling chrome.runtime.reload will reload the app and
908 // relaunch it if it was running.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,ReloadRelaunches)909 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ReloadRelaunches) {
910 ExtensionTestMessageListener launched_listener("Launched", true);
911 const Extension* extension =
912 LoadAndLaunchPlatformApp("reload", &launched_listener);
913 ASSERT_TRUE(extension);
914 ASSERT_TRUE(GetFirstAppWindow());
915
916 // Now tell the app to reload itself
917 ExtensionTestMessageListener launched_listener2("Launched", false);
918 launched_listener.Reply("reload");
919 ASSERT_TRUE(launched_listener2.WaitUntilSatisfied());
920 ASSERT_TRUE(GetFirstAppWindow());
921 }
922
923 namespace {
924
925 // Simple observer to check for NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED
926 // events to
927 // ensure installation does or does not occur in certain scenarios.
928 class CheckExtensionInstalledObserver : public content::NotificationObserver {
929 public:
CheckExtensionInstalledObserver()930 CheckExtensionInstalledObserver() : seen_(false) {
931 registrar_.Add(this,
932 chrome::NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED,
933 content::NotificationService::AllSources());
934 }
935
seen() const936 bool seen() const {
937 return seen_;
938 };
939
940 // NotificationObserver:
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)941 virtual void Observe(int type,
942 const content::NotificationSource& source,
943 const content::NotificationDetails& details) OVERRIDE {
944 EXPECT_FALSE(seen_);
945 seen_ = true;
946 }
947
948 private:
949 bool seen_;
950 content::NotificationRegistrar registrar_;
951 };
952
953 } // namespace
954
955 // Component App Test 1 of 3: ensure that the initial load of a component
956 // extension utilizing a background page (e.g. a v2 platform app) has its
957 // background page run and is launchable. Waits for the Launched response from
958 // the script resource in the opened app window.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,PRE_PRE_ComponentAppBackgroundPage)959 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
960 PRE_PRE_ComponentAppBackgroundPage) {
961 CheckExtensionInstalledObserver should_install;
962
963 // Ensure that we wait until the background page is run (to register the
964 // OnLaunched listener) before trying to open the application. This is similar
965 // to LoadAndLaunchPlatformApp, but we want to load as a component extension.
966 content::WindowedNotificationObserver app_loaded_observer(
967 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
968 content::NotificationService::AllSources());
969
970 const Extension* extension = LoadExtensionAsComponent(
971 test_data_dir_.AppendASCII("platform_apps").AppendASCII("component"));
972 ASSERT_TRUE(extension);
973
974 app_loaded_observer.Wait();
975 ASSERT_TRUE(should_install.seen());
976
977 ExtensionTestMessageListener launched_listener("Launched", false);
978 OpenApplication(AppLaunchParams(
979 browser()->profile(), extension, LAUNCH_CONTAINER_NONE, NEW_WINDOW));
980
981 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
982 }
983
984 // Component App Test 2 of 3: ensure an installed component app can be launched
985 // on a subsequent browser start, without requiring any install/upgrade logic
986 // to be run, then perform setup for step 3.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,PRE_ComponentAppBackgroundPage)987 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
988 PRE_ComponentAppBackgroundPage) {
989
990 // Since the component app is now installed, re-adding it in the same profile
991 // should not cause it to be re-installed. Instead, we wait for the OnLaunched
992 // in a different observer (which would timeout if not the app was not
993 // previously installed properly) and then check this observer to make sure it
994 // never saw the NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED event.
995 CheckExtensionInstalledObserver should_not_install;
996 const Extension* extension = LoadExtensionAsComponent(
997 test_data_dir_.AppendASCII("platform_apps").AppendASCII("component"));
998 ASSERT_TRUE(extension);
999
1000 ExtensionTestMessageListener launched_listener("Launched", false);
1001 OpenApplication(AppLaunchParams(
1002 browser()->profile(), extension, LAUNCH_CONTAINER_NONE, NEW_WINDOW));
1003
1004 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
1005 ASSERT_FALSE(should_not_install.seen());
1006
1007 // Simulate a "downgrade" from version 2 in the test manifest.json to 1.
1008 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(browser()->profile());
1009
1010 // Clear the registered events to ensure they are updated.
1011 extensions::EventRouter::Get(browser()->profile())
1012 ->SetRegisteredEvents(extension->id(), std::set<std::string>());
1013
1014 DictionaryPrefUpdate update(extension_prefs->pref_service(),
1015 extensions::pref_names::kExtensions);
1016 base::DictionaryValue* dict = update.Get();
1017 std::string key(extension->id());
1018 key += ".manifest.version";
1019 dict->SetString(key, "1");
1020 }
1021
1022 // Component App Test 3 of 3: simulate a component extension upgrade that
1023 // re-adds the OnLaunched event, and allows the app to be launched.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,ComponentAppBackgroundPage)1024 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ComponentAppBackgroundPage) {
1025 CheckExtensionInstalledObserver should_install;
1026 // Since we are forcing an upgrade, we need to wait for the load again.
1027 content::WindowedNotificationObserver app_loaded_observer(
1028 content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
1029 content::NotificationService::AllSources());
1030
1031 const Extension* extension = LoadExtensionAsComponent(
1032 test_data_dir_.AppendASCII("platform_apps").AppendASCII("component"));
1033 ASSERT_TRUE(extension);
1034 app_loaded_observer.Wait();
1035 ASSERT_TRUE(should_install.seen());
1036
1037 ExtensionTestMessageListener launched_listener("Launched", false);
1038 OpenApplication(AppLaunchParams(
1039 browser()->profile(), extension, LAUNCH_CONTAINER_NONE, NEW_WINDOW));
1040
1041 ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
1042 }
1043
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,Messaging)1044 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Messaging) {
1045 ExtensionApiTest::ResultCatcher result_catcher;
1046 LoadAndLaunchPlatformApp("messaging/app2", "Launched");
1047 LoadAndLaunchPlatformApp("messaging/app1", "Launched");
1048 EXPECT_TRUE(result_catcher.GetNextResult());
1049 }
1050
1051 // TODO(linux_aura) http://crbug.com/163931
1052 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
1053 #define MAYBE_WebContentsHasFocus DISABLED_WebContentsHasFocus
1054 #else
1055 // This test depends on focus and so needs to be in interactive_ui_tests.
1056 // http://crbug.com/227041
1057 #define MAYBE_WebContentsHasFocus DISABLED_WebContentsHasFocus
1058 #endif
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,MAYBE_WebContentsHasFocus)1059 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_WebContentsHasFocus) {
1060 LoadAndLaunchPlatformApp("minimal", "Launched");
1061
1062 EXPECT_EQ(1LU, GetAppWindowCount());
1063 EXPECT_TRUE(GetFirstAppWindow()
1064 ->web_contents()
1065 ->GetRenderWidgetHostView()
1066 ->HasFocus());
1067 }
1068
1069 #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_MACOSX)
1070 #define MAYBE_WindowDotPrintShouldBringUpPrintPreview \
1071 DISABLED_WindowDotPrintShouldBringUpPrintPreview
1072 #else
1073 #define MAYBE_WindowDotPrintShouldBringUpPrintPreview \
1074 WindowDotPrintShouldBringUpPrintPreview
1075 #endif
1076
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,MAYBE_WindowDotPrintShouldBringUpPrintPreview)1077 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
1078 MAYBE_WindowDotPrintShouldBringUpPrintPreview) {
1079 ScopedPreviewTestingDelegate preview_delegate(true);
1080 ASSERT_TRUE(RunPlatformAppTest("platform_apps/print_api")) << message_;
1081 preview_delegate.WaitUntilPreviewIsReady();
1082 }
1083
1084 // This test verifies that http://crbug.com/297179 is fixed.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,DISABLED_ClosingWindowWhilePrintingShouldNotCrash)1085 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
1086 DISABLED_ClosingWindowWhilePrintingShouldNotCrash) {
1087 ScopedPreviewTestingDelegate preview_delegate(false);
1088 ASSERT_TRUE(RunPlatformAppTest("platform_apps/print_api")) << message_;
1089 preview_delegate.WaitUntilPreviewIsReady();
1090 GetFirstAppWindow()->GetBaseWindow()->Close();
1091 }
1092
1093 // This test currently only passes on OS X (on other platforms the print preview
1094 // dialog's size is limited by the size of the window being printed).
1095 #if !defined(OS_MACOSX)
1096 #define MAYBE_PrintPreviewShouldNotBeTooSmall \
1097 DISABLED_PrintPreviewShouldNotBeTooSmall
1098 #else
1099 #define MAYBE_PrintPreviewShouldNotBeTooSmall \
1100 PrintPreviewShouldNotBeTooSmall
1101 #endif
1102
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,MAYBE_PrintPreviewShouldNotBeTooSmall)1103 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
1104 MAYBE_PrintPreviewShouldNotBeTooSmall) {
1105 // Print preview dialogs with widths less than 410 pixels will have preview
1106 // areas that are too small, and ones with heights less than 191 pixels will
1107 // have vertical scrollers for their controls that are too small.
1108 gfx::Size minimum_dialog_size(410, 191);
1109 ScopedPreviewTestingDelegate preview_delegate(false);
1110 ASSERT_TRUE(RunPlatformAppTest("platform_apps/print_api")) << message_;
1111 preview_delegate.WaitUntilPreviewIsReady();
1112 EXPECT_GE(preview_delegate.dialog_size().width(),
1113 minimum_dialog_size.width());
1114 EXPECT_GE(preview_delegate.dialog_size().height(),
1115 minimum_dialog_size.height());
1116 GetFirstAppWindow()->GetBaseWindow()->Close();
1117 }
1118
1119
1120 #if defined(OS_CHROMEOS)
1121
1122 class PlatformAppIncognitoBrowserTest : public PlatformAppBrowserTest,
1123 public AppWindowRegistry::Observer {
1124 public:
SetUpCommandLine(CommandLine * command_line)1125 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
1126 // Tell chromeos to launch in Guest mode, aka incognito.
1127 command_line->AppendSwitch(switches::kIncognito);
1128 PlatformAppBrowserTest::SetUpCommandLine(command_line);
1129 }
SetUp()1130 virtual void SetUp() OVERRIDE {
1131 // Make sure the file manager actually gets loaded.
1132 ComponentLoader::EnableBackgroundExtensionsForTesting();
1133 PlatformAppBrowserTest::SetUp();
1134 }
1135
1136 // AppWindowRegistry::Observer implementation.
OnAppWindowAdded(AppWindow * app_window)1137 virtual void OnAppWindowAdded(AppWindow* app_window) OVERRIDE {
1138 opener_app_ids_.insert(app_window->extension_id());
1139 }
1140
1141 protected:
1142 // A set of ids of apps we've seen open a app window.
1143 std::set<std::string> opener_app_ids_;
1144 };
1145
IN_PROC_BROWSER_TEST_F(PlatformAppIncognitoBrowserTest,IncognitoComponentApp)1146 IN_PROC_BROWSER_TEST_F(PlatformAppIncognitoBrowserTest, IncognitoComponentApp) {
1147 // Get the file manager app.
1148 const Extension* file_manager = extension_service()->GetExtensionById(
1149 "hhaomjibdihmijegdhdafkllkbggdgoj", false);
1150 ASSERT_TRUE(file_manager != NULL);
1151 Profile* incognito_profile = profile()->GetOffTheRecordProfile();
1152 ASSERT_TRUE(incognito_profile != NULL);
1153
1154 // Wait until the file manager has had a chance to register its listener
1155 // for the launch event.
1156 EventRouter* router = EventRouter::Get(incognito_profile);
1157 ASSERT_TRUE(router != NULL);
1158 while (!router->ExtensionHasEventListener(
1159 file_manager->id(), app_runtime::OnLaunched::kEventName)) {
1160 content::RunAllPendingInMessageLoop();
1161 }
1162
1163 // Listen for new app windows so we see the file manager app launch itself.
1164 AppWindowRegistry* registry = AppWindowRegistry::Get(incognito_profile);
1165 ASSERT_TRUE(registry != NULL);
1166 registry->AddObserver(this);
1167
1168 OpenApplication(AppLaunchParams(
1169 incognito_profile, file_manager, 0, chrome::HOST_DESKTOP_TYPE_NATIVE));
1170
1171 while (!ContainsKey(opener_app_ids_, file_manager->id())) {
1172 content::RunAllPendingInMessageLoop();
1173 }
1174 }
1175
1176 class RestartDeviceTest : public PlatformAppBrowserTest {
1177 public:
RestartDeviceTest()1178 RestartDeviceTest()
1179 : power_manager_client_(NULL),
1180 mock_user_manager_(NULL) {}
~RestartDeviceTest()1181 virtual ~RestartDeviceTest() {}
1182
1183 // PlatformAppBrowserTest overrides
SetUpInProcessBrowserTestFixture()1184 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
1185 PlatformAppBrowserTest::SetUpInProcessBrowserTestFixture();
1186
1187 chromeos::FakeDBusThreadManager* dbus_manager =
1188 new chromeos::FakeDBusThreadManager;
1189 dbus_manager->SetFakeClients();
1190 power_manager_client_ = new chromeos::FakePowerManagerClient;
1191 dbus_manager->SetPowerManagerClient(
1192 scoped_ptr<chromeos::PowerManagerClient>(power_manager_client_));
1193 chromeos::DBusThreadManager::SetInstanceForTesting(dbus_manager);
1194 }
1195
SetUpOnMainThread()1196 virtual void SetUpOnMainThread() OVERRIDE {
1197 PlatformAppBrowserTest::SetUpOnMainThread();
1198
1199 mock_user_manager_ = new chromeos::MockUserManager;
1200 user_manager_enabler_.reset(
1201 new chromeos::ScopedUserManagerEnabler(mock_user_manager_));
1202
1203 EXPECT_CALL(*mock_user_manager_, IsUserLoggedIn())
1204 .WillRepeatedly(testing::Return(true));
1205 EXPECT_CALL(*mock_user_manager_, IsLoggedInAsKioskApp())
1206 .WillRepeatedly(testing::Return(true));
1207 }
1208
CleanUpOnMainThread()1209 virtual void CleanUpOnMainThread() OVERRIDE {
1210 user_manager_enabler_.reset();
1211 PlatformAppBrowserTest::CleanUpOnMainThread();
1212 }
1213
TearDownInProcessBrowserTestFixture()1214 virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
1215 PlatformAppBrowserTest::TearDownInProcessBrowserTestFixture();
1216 }
1217
num_request_restart_calls() const1218 int num_request_restart_calls() const {
1219 return power_manager_client_->num_request_restart_calls();
1220 }
1221
1222 private:
1223 chromeos::FakePowerManagerClient* power_manager_client_;
1224 chromeos::MockUserManager* mock_user_manager_;
1225 scoped_ptr<chromeos::ScopedUserManagerEnabler> user_manager_enabler_;
1226
1227 DISALLOW_COPY_AND_ASSIGN(RestartDeviceTest);
1228 };
1229
1230 // Tests that chrome.runtime.restart would request device restart in
1231 // ChromeOS kiosk mode.
IN_PROC_BROWSER_TEST_F(RestartDeviceTest,Restart)1232 IN_PROC_BROWSER_TEST_F(RestartDeviceTest, Restart) {
1233 ASSERT_EQ(0, num_request_restart_calls());
1234
1235 ExtensionTestMessageListener launched_listener("Launched", true);
1236 const Extension* extension = LoadAndLaunchPlatformApp("restart_device",
1237 &launched_listener);
1238 ASSERT_TRUE(extension);
1239
1240 launched_listener.Reply("restart");
1241 ExtensionTestMessageListener restart_requested_listener("restartRequested",
1242 false);
1243 ASSERT_TRUE(restart_requested_listener.WaitUntilSatisfied());
1244
1245 EXPECT_EQ(1, num_request_restart_calls());
1246 }
1247
1248 #endif // defined(OS_CHROMEOS)
1249
1250 // Test that when an application is uninstalled and re-install it does not have
1251 // access to the previously set data.
IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,ReinstallDataCleanup)1252 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ReinstallDataCleanup) {
1253 // The application is installed and launched. After the 'Launched' message is
1254 // acknowledged by the browser process, the application will test that some
1255 // data are not installed and then install them. The application will then be
1256 // uninstalled and the same process will be repeated.
1257 std::string extension_id;
1258
1259 {
1260 const Extension* extension =
1261 LoadAndLaunchPlatformApp("reinstall_data_cleanup", "Launched");
1262 ASSERT_TRUE(extension);
1263 extension_id = extension->id();
1264
1265 ExtensionApiTest::ResultCatcher result_catcher;
1266 EXPECT_TRUE(result_catcher.GetNextResult());
1267 }
1268
1269 UninstallExtension(extension_id);
1270 content::RunAllPendingInMessageLoop();
1271
1272 {
1273 const Extension* extension =
1274 LoadAndLaunchPlatformApp("reinstall_data_cleanup", "Launched");
1275 ASSERT_TRUE(extension);
1276 ASSERT_EQ(extension_id, extension->id());
1277
1278 ExtensionApiTest::ResultCatcher result_catcher;
1279 EXPECT_TRUE(result_catcher.GetNextResult());
1280 }
1281 }
1282
1283 } // namespace extensions
1284