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