summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/DEPS1
-rw-r--r--apps/app_shim/app_shim_handler_mac.h3
-rw-r--r--apps/app_shim/app_shim_host_mac.cc8
-rw-r--r--apps/app_shim/app_shim_host_mac.h3
-rw-r--r--apps/app_shim/app_shim_host_mac_unittest.cc10
-rw-r--r--apps/app_shim/app_shim_messages.h6
-rw-r--r--apps/app_shim/extension_app_shim_handler_mac.cc20
-rw-r--r--apps/app_shim/extension_app_shim_handler_mac.h1
-rw-r--r--apps/apps.gypi2
-rw-r--r--chrome/app/chrome_main_app_mode_mac.mm74
-rw-r--r--chrome/browser/ui/app_list/app_list_service_mac.mm5
11 files changed, 121 insertions, 12 deletions
diff --git a/apps/DEPS b/apps/DEPS
index b7951f8..60fa875 100644
--- a/apps/DEPS
+++ b/apps/DEPS
@@ -11,6 +11,7 @@ include_rules = [
"+chrome/browser/profiles",
"+chrome/browser/shell_integration.h",
"+chrome/browser/ui/extensions/application_launch.h",
+ "+chrome/browser/ui/extensions/native_app_window.h",
"+chrome/browser/ui/extensions/shell_window.h",
"+chrome/browser/ui/host_desktop.h",
"+chrome/browser/ui/web_applications/web_app_ui.h",
diff --git a/apps/app_shim/app_shim_handler_mac.h b/apps/app_shim/app_shim_handler_mac.h
index 507fe5f..e4a35fb 100644
--- a/apps/app_shim/app_shim_handler_mac.h
+++ b/apps/app_shim/app_shim_handler_mac.h
@@ -55,6 +55,9 @@ class AppShimHandler {
// Invoked by the shim host when the shim process receives a focus event.
virtual void OnShimFocus(Host* host) = 0;
+ // Invoked by the shim host when the shim process receives a quit event.
+ virtual void OnShimQuit(Host* host) = 0;
+
protected:
AppShimHandler() {}
virtual ~AppShimHandler() {}
diff --git a/apps/app_shim/app_shim_host_mac.cc b/apps/app_shim/app_shim_host_mac.cc
index ad63e93..07c9903 100644
--- a/apps/app_shim/app_shim_host_mac.cc
+++ b/apps/app_shim/app_shim_host_mac.cc
@@ -47,6 +47,7 @@ bool AppShimHost::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(AppShimHost, message)
IPC_MESSAGE_HANDLER(AppShimHostMsg_LaunchApp, OnLaunchApp)
IPC_MESSAGE_HANDLER(AppShimHostMsg_FocusApp, OnFocus)
+ IPC_MESSAGE_HANDLER(AppShimHostMsg_QuitApp, OnQuit)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -85,6 +86,13 @@ void AppShimHost::OnFocus() {
handler->OnShimFocus(this);
}
+void AppShimHost::OnQuit() {
+ DCHECK(CalledOnValidThread());
+ apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
+ if (handler)
+ handler->OnShimQuit(this);
+}
+
Profile* AppShimHost::FetchProfileForDirectory(const std::string& profile_dir) {
ProfileManager* profileManager = g_browser_process->profile_manager();
// Even though the name of this function is "unsafe", there's no security
diff --git a/apps/app_shim/app_shim_host_mac.h b/apps/app_shim/app_shim_host_mac.h
index e68380c..dd31047 100644
--- a/apps/app_shim/app_shim_host_mac.h
+++ b/apps/app_shim/app_shim_host_mac.h
@@ -62,6 +62,9 @@ class AppShimHost : public IPC::Listener,
// Cmd+Tabbed to it.)
void OnFocus();
+ // Called when the app shim process notifies that the app should quit.
+ void OnQuit();
+
// apps::AppShimHandler::Host overrides:
virtual void OnAppClosed() OVERRIDE;
virtual Profile* GetProfile() const OVERRIDE;
diff --git a/apps/app_shim/app_shim_host_mac_unittest.cc b/apps/app_shim/app_shim_host_mac_unittest.cc
index f9a8e4d..0a7ef2b 100644
--- a/apps/app_shim/app_shim_host_mac_unittest.cc
+++ b/apps/app_shim/app_shim_host_mac_unittest.cc
@@ -72,7 +72,10 @@ Profile* TestingAppShimHost::FetchProfileForDirectory(
class AppShimHostTest : public testing::Test,
public apps::AppShimHandler {
public:
- AppShimHostTest() : launch_count_(0), close_count_(0), focus_count_(0) {}
+ AppShimHostTest() : launch_count_(0),
+ close_count_(0),
+ focus_count_(0),
+ quit_count_(0) {}
TestingAppShimHost* host() { return host_.get(); }
TestingProfile* profile() { return profile_.get(); }
@@ -98,10 +101,12 @@ class AppShimHostTest : public testing::Test,
virtual void OnShimClose(Host* host) OVERRIDE { ++close_count_; }
virtual void OnShimFocus(Host* host) OVERRIDE { ++focus_count_; }
+ virtual void OnShimQuit(Host* host) OVERRIDE { ++quit_count_; }
int launch_count_;
int close_count_;
int focus_count_;
+ int quit_count_;
private:
virtual void SetUp() OVERRIDE {
@@ -135,6 +140,9 @@ TEST_F(AppShimHostTest, TestLaunchAppWithHandler) {
EXPECT_TRUE(host()->ReceiveMessage(new AppShimHostMsg_FocusApp()));
EXPECT_EQ(1, focus_count_);
+ EXPECT_TRUE(host()->ReceiveMessage(new AppShimHostMsg_QuitApp()));
+ EXPECT_EQ(1, quit_count_);
+
SimulateDisconnect();
EXPECT_EQ(1, close_count_);
apps::AppShimHandler::RemoveHandler(kTestAppId);
diff --git a/apps/app_shim/app_shim_messages.h b/apps/app_shim/app_shim_messages.h
index 6a6cc6d..5b8c194 100644
--- a/apps/app_shim/app_shim_messages.h
+++ b/apps/app_shim/app_shim_messages.h
@@ -25,3 +25,9 @@ IPC_MESSAGE_CONTROL2(AppShimHostMsg_LaunchApp,
// clicking on the app's icon in the dock or by selecting it with Cmd+Tab. In
// response, Chrome brings the app's windows to the foreground.
IPC_MESSAGE_CONTROL0(AppShimHostMsg_FocusApp)
+
+// Sent when the shim process receives a request to terminate. Once all of the
+// app's windows have closed, and the extension is unloaded, the AppShimHost
+// closes the channel. The shim process then completes the terminate request
+// and exits.
+IPC_MESSAGE_CONTROL0(AppShimHostMsg_QuitApp)
diff --git a/apps/app_shim/extension_app_shim_handler_mac.cc b/apps/app_shim/extension_app_shim_handler_mac.cc
index 9d31d69..902e0c2 100644
--- a/apps/app_shim/extension_app_shim_handler_mac.cc
+++ b/apps/app_shim/extension_app_shim_handler_mac.cc
@@ -12,6 +12,7 @@
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/ui/extensions/application_launch.h"
+#include "chrome/browser/ui/extensions/native_app_window.h"
#include "chrome/browser/ui/extensions/shell_window.h"
#include "ui/base/cocoa/focus_window_set.h"
@@ -73,13 +74,26 @@ void ExtensionAppShimHandler::OnShimFocus(Host* host) {
const extensions::ShellWindowRegistry::ShellWindowList windows =
registry->GetShellWindowsForApp(host->GetAppId());
std::set<gfx::NativeWindow> native_windows;
- for (extensions::ShellWindowRegistry::const_iterator i = windows.begin();
- i != windows.end(); ++i) {
- native_windows.insert((*i)->GetNativeWindow());
+ for (extensions::ShellWindowRegistry::const_iterator it = windows.begin();
+ it != windows.end(); ++it) {
+ native_windows.insert((*it)->GetNativeWindow());
}
ui::FocusWindowSet(native_windows);
}
+void ExtensionAppShimHandler::OnShimQuit(Host* host) {
+ if (!host->GetProfile())
+ return;
+
+ extensions::ShellWindowRegistry::ShellWindowList windows =
+ extensions::ShellWindowRegistry::Get(host->GetProfile())->
+ GetShellWindowsForApp(host->GetAppId());
+ for (extensions::ShellWindowRegistry::const_iterator it = windows.begin();
+ it != windows.end(); ++it) {
+ (*it)->GetBaseWindow()->Close();
+ }
+}
+
bool ExtensionAppShimHandler::LaunchApp(Profile* profile,
const std::string& app_id) {
extensions::ExtensionSystem* extension_system =
diff --git a/apps/app_shim/extension_app_shim_handler_mac.h b/apps/app_shim/extension_app_shim_handler_mac.h
index ea9a8c7..86c86e1 100644
--- a/apps/app_shim/extension_app_shim_handler_mac.h
+++ b/apps/app_shim/extension_app_shim_handler_mac.h
@@ -28,6 +28,7 @@ class ExtensionAppShimHandler : public AppShimHandler,
virtual bool OnShimLaunch(Host* host) OVERRIDE;
virtual void OnShimClose(Host* host) OVERRIDE;
virtual void OnShimFocus(Host* host) OVERRIDE;
+ virtual void OnShimQuit(Host* host) OVERRIDE;
protected:
typedef std::map<std::pair<Profile*, std::string>, AppShimHandler::Host*>
diff --git a/apps/apps.gypi b/apps/apps.gypi
index 92a677e..49681a2 100644
--- a/apps/apps.gypi
+++ b/apps/apps.gypi
@@ -36,8 +36,8 @@
'app_shim/app_shim_host_mac.h',
'app_shim/app_shim_host_manager_mac.h',
'app_shim/app_shim_host_manager_mac.mm',
- 'app_shim/extension_app_shim_handler_mac.h',
'app_shim/extension_app_shim_handler_mac.cc',
+ 'app_shim/extension_app_shim_handler_mac.h',
'field_trial_names.cc',
'field_trial_names.h',
'pref_names.cc',
diff --git a/chrome/app/chrome_main_app_mode_mac.mm b/chrome/app/chrome_main_app_mode_mac.mm
index 1de3fe5..e464612 100644
--- a/chrome/app/chrome_main_app_mode_mac.mm
+++ b/chrome/app/chrome_main_app_mode_mac.mm
@@ -17,6 +17,7 @@
#include "base/mac/mac_logging.h"
#include "base/mac/mac_util.h"
#include "base/mac/scoped_nsautorelease_pool.h"
+#include "base/memory/scoped_nsobject.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/strings/sys_string_conversions.h"
@@ -36,6 +37,21 @@ base::Thread* g_io_thread = NULL;
} // namespace
+class AppShimController;
+
+@interface AppShimDelegate : NSObject<NSApplicationDelegate> {
+ @private
+ AppShimController* appShimController_; // Weak. Owns us.
+ BOOL terminateNow_;
+ BOOL terminateRequested_;
+}
+
+- (id)initWithController:(AppShimController*)controller;
+
+- (void)terminateNow;
+
+@end
+
// The AppShimController is responsible for communication with the main Chrome
// process, and generally controls the lifetime of the app shim process.
class AppShimController : public IPC::Listener {
@@ -45,6 +61,9 @@ class AppShimController : public IPC::Listener {
// Connects to Chrome and sends a LaunchApp message.
void Init();
+ // Sends a QuitApp message to Chrome.
+ void QuitApp();
+
private:
// IPC::Listener implemetation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
@@ -58,10 +77,11 @@ class AppShimController : public IPC::Listener {
// dock or by Cmd+Tabbing to it.
void OnDidActivateApplication();
- // Quits the app shim process.
- void Quit();
+ // Terminates the app shim process.
+ void Close();
IPC::ChannelProxy* channel_;
+ scoped_nsobject<AppShimDelegate> nsapp_delegate_;
DISALLOW_COPY_AND_ASSIGN(AppShimController);
};
@@ -77,7 +97,7 @@ void AppShimController::Init() {
base::FilePath user_data_dir;
if (!chrome::GetUserDataDirectoryForBrowserBundle(chrome_bundle,
&user_data_dir)) {
- Quit();
+ Close();
return;
}
@@ -89,6 +109,14 @@ void AppShimController::Init() {
channel_->Send(new AppShimHostMsg_LaunchApp(
g_info->profile_dir.value(), g_info->app_mode_id));
+
+ nsapp_delegate_.reset([[AppShimDelegate alloc] initWithController:this]);
+ DCHECK(![NSApp delegate]);
+ [NSApp setDelegate:nsapp_delegate_];
+}
+
+void AppShimController::QuitApp() {
+ channel_->Send(new AppShimHostMsg_QuitApp);
}
bool AppShimController::OnMessageReceived(const IPC::Message& message) {
@@ -103,12 +131,12 @@ bool AppShimController::OnMessageReceived(const IPC::Message& message) {
void AppShimController::OnChannelError() {
LOG(ERROR) << "App shim channel error.";
- Quit();
+ Close();
}
void AppShimController::OnLaunchAppDone(bool success) {
if (!success) {
- Quit();
+ Close();
return;
}
[[[NSWorkspace sharedWorkspace] notificationCenter]
@@ -123,14 +151,46 @@ void AppShimController::OnLaunchAppDone(bool success) {
}];
}
-void AppShimController::Quit() {
- [NSApp terminate:nil];
+void AppShimController::Close() {
+ [nsapp_delegate_ terminateNow];
}
void AppShimController::OnDidActivateApplication() {
channel_->Send(new AppShimHostMsg_FocusApp);
}
+@implementation AppShimDelegate
+
+- (id)initWithController:(AppShimController*)controller {
+ if ((self = [super init])) {
+ appShimController_ = controller;
+ }
+ return self;
+}
+
+- (NSApplicationTerminateReply)
+ applicationShouldTerminate:(NSApplication*)sender {
+ if (terminateNow_)
+ return NSTerminateNow;
+
+ appShimController_->QuitApp();
+ // Wait for the channel to close before terminating.
+ terminateRequested_ = YES;
+ return NSTerminateLater;
+}
+
+- (void)terminateNow {
+ if (terminateRequested_) {
+ [NSApp replyToApplicationShouldTerminate:NSTerminateNow];
+ return;
+ }
+
+ terminateNow_ = YES;
+ [NSApp terminate:nil];
+}
+
+@end
+
//-----------------------------------------------------------------------------
// A ReplyEventHandler is a helper class to send an Apple Event to a process
diff --git a/chrome/browser/ui/app_list/app_list_service_mac.mm b/chrome/browser/ui/app_list/app_list_service_mac.mm
index 677ed2b..254527b 100644
--- a/chrome/browser/ui/app_list/app_list_service_mac.mm
+++ b/chrome/browser/ui/app_list/app_list_service_mac.mm
@@ -64,6 +64,7 @@ class AppListServiceMac : public AppListServiceImpl,
virtual bool OnShimLaunch(apps::AppShimHandler::Host* host) OVERRIDE;
virtual void OnShimClose(apps::AppShimHandler::Host* host) OVERRIDE;
virtual void OnShimFocus(apps::AppShimHandler::Host* host) OVERRIDE;
+ virtual void OnShimQuit(apps::AppShimHandler::Host* host) OVERRIDE;
private:
friend struct DefaultSingletonTraits<AppListServiceMac>;
@@ -285,6 +286,10 @@ void AppListServiceMac::OnShimFocus(apps::AppShimHandler::Host* host) {
DismissAppList();
}
+void AppListServiceMac::OnShimQuit(apps::AppShimHandler::Host* host) {
+ DismissAppList();
+}
+
enum DockLocation {
DockLocationOtherDisplay,
DockLocationBottom,