Home | History | Annotate | Download | only in app_shim
      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 // Tests behavior when quitting apps with app shims.
      6 
      7 #import <Cocoa/Cocoa.h>
      8 #include <vector>
      9 
     10 #include "apps/switches.h"
     11 #include "chrome/browser/apps/app_browsertest_util.h"
     12 #include "chrome/browser/apps/app_shim/app_shim_host_manager_mac.h"
     13 #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h"
     14 #include "chrome/browser/browser_process.h"
     15 #include "chrome/browser/browser_shutdown.h"
     16 #include "chrome/browser/profiles/profile.h"
     17 #include "chrome/common/chrome_switches.h"
     18 #include "chrome/test/base/interactive_test_utils.h"
     19 #include "content/public/test/test_utils.h"
     20 #include "extensions/browser/extension_registry.h"
     21 #include "extensions/test/extension_test_message_listener.h"
     22 #include "ui/events/test/cocoa_test_event_utils.h"
     23 
     24 using extensions::PlatformAppBrowserTest;
     25 
     26 namespace apps {
     27 
     28 namespace {
     29 
     30 class FakeHost : public apps::AppShimHandler::Host {
     31  public:
     32   FakeHost(const base::FilePath& profile_path,
     33            const std::string& app_id,
     34            ExtensionAppShimHandler* handler)
     35       : profile_path_(profile_path),
     36         app_id_(app_id),
     37         handler_(handler) {}
     38 
     39   virtual void OnAppLaunchComplete(AppShimLaunchResult result) OVERRIDE {}
     40   virtual void OnAppClosed() OVERRIDE {
     41     handler_->OnShimClose(this);
     42   }
     43   virtual void OnAppHide() OVERRIDE {}
     44   virtual void OnAppRequestUserAttention(AppShimAttentionType type) OVERRIDE {}
     45   virtual base::FilePath GetProfilePath() const OVERRIDE {
     46     return profile_path_;
     47   }
     48   virtual std::string GetAppId() const OVERRIDE { return app_id_; }
     49 
     50  private:
     51   base::FilePath profile_path_;
     52   std::string app_id_;
     53   ExtensionAppShimHandler* handler_;
     54 
     55   DISALLOW_COPY_AND_ASSIGN(FakeHost);
     56 };
     57 
     58 // Starts an app without a browser window using --load_and_launch_app and
     59 // --silent_launch.
     60 class AppShimQuitTest : public PlatformAppBrowserTest {
     61  protected:
     62   AppShimQuitTest() {}
     63 
     64   void SetUpAppShim() {
     65     ASSERT_EQ(0u, [[NSApp windows] count]);
     66     ExtensionTestMessageListener launched_listener("Launched", false);
     67     ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
     68     ASSERT_EQ(1u, [[NSApp windows] count]);
     69 
     70     handler_ = g_browser_process->platform_part()->app_shim_host_manager()->
     71         extension_app_shim_handler();
     72 
     73     // Attach a host for the app.
     74     extensions::ExtensionRegistry* registry =
     75         extensions::ExtensionRegistry::Get(profile());
     76     extension_id_ =
     77         GetExtensionByPath(&registry->enabled_extensions(), app_path_)->id();
     78     host_.reset(new FakeHost(profile()->GetPath().BaseName(),
     79                              extension_id_,
     80                              handler_));
     81     handler_->OnShimLaunch(host_.get(),
     82                            APP_SHIM_LAUNCH_REGISTER_ONLY,
     83                            std::vector<base::FilePath>());
     84     EXPECT_EQ(host_.get(), handler_->FindHost(profile(), extension_id_));
     85 
     86     // Focus the app window.
     87     NSWindow* window = [[NSApp windows] objectAtIndex:0];
     88     EXPECT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(window));
     89     content::RunAllPendingInMessageLoop();
     90   }
     91 
     92   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
     93     PlatformAppBrowserTest::SetUpCommandLine(command_line);
     94     // Simulate an app shim initiated launch, i.e. launch app but not browser.
     95     app_path_ = test_data_dir_
     96         .AppendASCII("platform_apps")
     97         .AppendASCII("minimal");
     98     command_line->AppendSwitchNative(apps::kLoadAndLaunchApp,
     99                                      app_path_.value());
    100     command_line->AppendSwitch(switches::kSilentLaunch);
    101   }
    102 
    103   base::FilePath app_path_;
    104   ExtensionAppShimHandler* handler_;
    105   std::string extension_id_;
    106   scoped_ptr<FakeHost> host_;
    107 
    108   DISALLOW_COPY_AND_ASSIGN(AppShimQuitTest);
    109 };
    110 
    111 }  // namespace
    112 
    113 // Test that closing an app with Cmd+Q when no browsers have ever been open
    114 // terminates Chrome.
    115 IN_PROC_BROWSER_TEST_F(AppShimQuitTest, QuitWithKeyEvent) {
    116   SetUpAppShim();
    117 
    118   // Simulate a Cmd+Q event.
    119   NSWindow* window = [[NSApp windows] objectAtIndex:0];
    120   NSEvent* event = cocoa_test_event_utils::KeyEventWithKeyCode(
    121       0, 'q', NSKeyDown, NSCommandKeyMask);
    122   [window postEvent:event
    123             atStart:NO];
    124 
    125   // This will time out if the event above does not terminate Chrome.
    126   content::RunMessageLoop();
    127 
    128   EXPECT_FALSE(handler_->FindHost(profile(), extension_id_));
    129   EXPECT_TRUE(browser_shutdown::IsTryingToQuit());
    130 }
    131 
    132 }  // namespace apps
    133