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