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