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