summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/DEPS1
-rw-r--r--apps/app_shim/app_shim_handler_mac.h7
-rw-r--r--apps/app_shim/app_shim_host_mac.cc31
-rw-r--r--apps/app_shim/app_shim_host_mac.h15
-rw-r--r--apps/app_shim/app_shim_host_mac_unittest.cc64
-rw-r--r--apps/app_shim/app_shim_launch.h20
-rw-r--r--apps/app_shim/app_shim_messages.h19
-rw-r--r--apps/app_shim/extension_app_shim_handler_mac.cc48
-rw-r--r--apps/app_shim/extension_app_shim_handler_mac.h12
-rw-r--r--apps/app_shim/extension_app_shim_handler_mac_unittest.cc15
-rw-r--r--chrome/app/chrome_main_app_mode_mac.mm11
-rw-r--r--chrome/browser/ui/app_list/app_list_service_mac.mm6
-rw-r--r--chrome/browser/ui/app_list/app_list_service_mac_browsertest.mm3
-rw-r--r--chrome/browser/web_applications/web_app_mac.h3
-rw-r--r--chrome/browser/web_applications/web_app_mac.mm21
-rw-r--r--chrome/chrome_common.gypi1
-rw-r--r--chrome/common/mac/app_mode_common.h4
-rw-r--r--chrome/common/mac/app_mode_common.mm2
18 files changed, 210 insertions, 73 deletions
diff --git a/apps/DEPS b/apps/DEPS
index 60fa875..cf729ef 100644
--- a/apps/DEPS
+++ b/apps/DEPS
@@ -16,6 +16,7 @@ include_rules = [
"+chrome/browser/ui/host_desktop.h",
"+chrome/browser/ui/web_applications/web_app_ui.h",
"+chrome/browser/web_applications/web_app.h",
+ "+chrome/browser/web_applications/web_app_mac.h",
"+chrome/common/chrome_notification_types.h",
"+chrome/common/chrome_paths.h",
"+chrome/common/extensions",
diff --git a/apps/app_shim/app_shim_handler_mac.h b/apps/app_shim/app_shim_handler_mac.h
index e4a35fb..c24b340 100644
--- a/apps/app_shim/app_shim_handler_mac.h
+++ b/apps/app_shim/app_shim_handler_mac.h
@@ -7,6 +7,8 @@
#include <string>
+#include "apps/app_shim/app_shim_launch.h"
+
class Profile;
namespace apps {
@@ -46,8 +48,9 @@ class AppShimHandler {
// Invoked by the shim host when the shim process is launched. The handler
// must return true if successful, or false to indicate back to the shim
- // process that it should close.
- virtual bool OnShimLaunch(Host* host) = 0;
+ // process that it should close. |launch_now| indicates whether to launch the
+ // associated app.
+ virtual bool OnShimLaunch(Host* host, AppShimLaunchType launch_type) = 0;
// Invoked by the shim host when the connection to the shim process is closed.
virtual void OnShimClose(Host* host) = 0;
diff --git a/apps/app_shim/app_shim_host_mac.cc b/apps/app_shim/app_shim_host_mac.cc
index 07c9903..7ae2dd6 100644
--- a/apps/app_shim/app_shim_host_mac.cc
+++ b/apps/app_shim/app_shim_host_mac.cc
@@ -63,7 +63,9 @@ bool AppShimHost::Send(IPC::Message* message) {
return channel_->Send(message);
}
-void AppShimHost::OnLaunchApp(std::string profile_dir, std::string app_id) {
+void AppShimHost::OnLaunchApp(base::FilePath profile_dir,
+ std::string app_id,
+ apps::AppShimLaunchType launch_type) {
DCHECK(CalledOnValidThread());
DCHECK(!profile_);
if (profile_) {
@@ -72,10 +74,15 @@ void AppShimHost::OnLaunchApp(std::string profile_dir, std::string app_id) {
return;
}
- profile_ = FetchProfileForDirectory(profile_dir);
+ if (!(profile_ = FetchProfileForDirectory(profile_dir))) {
+ Send(new AppShimMsg_LaunchApp_Done(false));
+ return;
+ }
+
app_id_ = app_id;
+
apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
- bool success = handler && handler->OnShimLaunch(this);
+ bool success = handler && handler->OnShimLaunch(this, launch_type);
Send(new AppShimMsg_LaunchApp_Done(success));
}
@@ -93,24 +100,22 @@ void AppShimHost::OnQuit() {
handler->OnShimQuit(this);
}
-Profile* AppShimHost::FetchProfileForDirectory(const std::string& profile_dir) {
+Profile* AppShimHost::FetchProfileForDirectory(
+ const base::FilePath& profile_dir) {
ProfileManager* profileManager = g_browser_process->profile_manager();
- // Even though the name of this function is "unsafe", there's no security
- // issue here -- the check for the profile name in the profile info cache
- // ensures that we never access any directory that isn't a known profile.
- base::FilePath path = base::FilePath::FromUTF8Unsafe(profile_dir);
- path = profileManager->user_data_dir().Append(path);
+ // Check for the profile name in the profile info cache to ensure that we
+ // never access any directory that isn't a known profile.
+ base::FilePath path = profileManager->user_data_dir().Append(profile_dir);
ProfileInfoCache& cache = profileManager->GetProfileInfoCache();
- // This ensures that the given profile path is acutally a profile that we
- // already know about.
if (cache.GetIndexOfProfileWithPath(path) == std::string::npos) {
LOG(ERROR) << "Requested directory is not a known profile '"
- << profile_dir << "'.";
+ << profile_dir.value() << "'.";
return NULL;
}
Profile* profile = profileManager->GetProfile(path);
if (!profile) {
- LOG(ERROR) << "Couldn't get profile for directory '" << profile_dir << "'.";
+ LOG(ERROR) << "Couldn't get profile for directory '"
+ << profile_dir.value() << "'.";
return NULL;
}
return profile;
diff --git a/apps/app_shim/app_shim_host_mac.h b/apps/app_shim/app_shim_host_mac.h
index dd31047..ce5ce5b 100644
--- a/apps/app_shim/app_shim_host_mac.h
+++ b/apps/app_shim/app_shim_host_mac.h
@@ -8,6 +8,7 @@
#include <string>
#include "apps/app_shim/app_shim_handler_mac.h"
+#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "ipc/ipc_listener.h"
@@ -41,7 +42,7 @@ class AppShimHost : public IPC::Listener,
protected:
// Used internally; virtual so they can be mocked for testing.
- virtual Profile* FetchProfileForDirectory(const std::string& profile_dir);
+ virtual Profile* FetchProfileForDirectory(const base::FilePath& profile_dir);
// IPC::Listener implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
@@ -51,11 +52,13 @@ class AppShimHost : public IPC::Listener,
virtual bool Send(IPC::Message* message) OVERRIDE;
private:
- // The app shim process is requesting that an app be launched. Once it has
- // done so the |profile| and |app_id| are stored, and all future messages
- // from the app shim relate to the app it launched. It is an error for the
- // app shim to send multiple launch messages.
- void OnLaunchApp(std::string profile, std::string app_id);
+ // The app shim process is requesting to be associated with the given profile
+ // and app_id. Once the profile and app_id are stored, and all future
+ // messages from the app shim relate to this app. The app is launched
+ // immediately if |launch_now| is true.
+ void OnLaunchApp(base::FilePath profile_dir,
+ std::string app_id,
+ apps::AppShimLaunchType launch_type);
// Called when the app shim process notifies that the app should be brought
// to the front (i.e. the user has clicked on the app's icon in the dock or
diff --git a/apps/app_shim/app_shim_host_mac_unittest.cc b/apps/app_shim/app_shim_host_mac_unittest.cc
index 0a7ef2b..6b1d049 100644
--- a/apps/app_shim/app_shim_host_mac_unittest.cc
+++ b/apps/app_shim/app_shim_host_mac_unittest.cc
@@ -28,19 +28,14 @@ class TestingAppShimHost : public AppShimHost {
fails_profile_ = fails_profile;
}
- void set_fails_launch(bool fails_launch) {
- fails_launch_ = fails_launch;
- }
-
protected:
- virtual Profile* FetchProfileForDirectory(const std::string& profile_dir)
+ virtual Profile* FetchProfileForDirectory(const base::FilePath& profile_dir)
OVERRIDE;
virtual bool Send(IPC::Message* message) OVERRIDE;
private:
Profile* test_profile_;
bool fails_profile_;
- bool fails_launch_;
ScopedVector<IPC::Message> sent_messages_;
@@ -49,8 +44,7 @@ class TestingAppShimHost : public AppShimHost {
TestingAppShimHost::TestingAppShimHost(Profile* profile)
: test_profile_(profile),
- fails_profile_(false),
- fails_launch_(false) {
+ fails_profile_(false) {
}
bool TestingAppShimHost::ReceiveMessage(IPC::Message* message) {
@@ -65,14 +59,19 @@ bool TestingAppShimHost::Send(IPC::Message* message) {
}
Profile* TestingAppShimHost::FetchProfileForDirectory(
- const std::string& profile_dir) {
+ const base::FilePath& profile_dir) {
return fails_profile_ ? NULL : test_profile_;
}
+const char kTestAppId[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+const char kTestProfileDir[] = "Default";
+
class AppShimHostTest : public testing::Test,
public apps::AppShimHandler {
public:
- AppShimHostTest() : launch_count_(0),
+ AppShimHostTest() : fail_launch_(false),
+ launch_count_(0),
+ launch_now_count_(0),
close_count_(0),
focus_count_(0),
quit_count_(0) {}
@@ -80,6 +79,13 @@ class AppShimHostTest : public testing::Test,
TestingAppShimHost* host() { return host_.get(); }
TestingProfile* profile() { return profile_.get(); }
+ void LaunchApp(bool launch_now) {
+ EXPECT_TRUE(host()->ReceiveMessage(new AppShimHostMsg_LaunchApp(
+ base::FilePath(kTestProfileDir), kTestAppId,
+ launch_now ? apps::APP_SHIM_LAUNCH_NORMAL :
+ apps::APP_SHIM_LAUNCH_REGISTER_ONLY)));
+ }
+
bool LaunchWasSuccessful() {
EXPECT_EQ(1u, host()->sent_messages().size());
IPC::Message* message = host()->sent_messages()[0];
@@ -94,16 +100,21 @@ class AppShimHostTest : public testing::Test,
}
protected:
- virtual bool OnShimLaunch(Host* host) OVERRIDE {
+ virtual bool OnShimLaunch(Host* host,
+ apps::AppShimLaunchType launch_type) OVERRIDE {
++launch_count_;
- return true;
+ if (launch_type == apps::APP_SHIM_LAUNCH_NORMAL)
+ ++launch_now_count_;
+ return !fail_launch_;
}
virtual void OnShimClose(Host* host) OVERRIDE { ++close_count_; }
virtual void OnShimFocus(Host* host) OVERRIDE { ++focus_count_; }
virtual void OnShimQuit(Host* host) OVERRIDE { ++quit_count_; }
+ bool fail_launch_;
int launch_count_;
+ int launch_now_count_;
int close_count_;
int focus_count_;
int quit_count_;
@@ -121,19 +132,17 @@ class AppShimHostTest : public testing::Test,
DISALLOW_COPY_AND_ASSIGN(AppShimHostTest);
};
-const char kTestAppId[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
-const char kTestProfileDir[] = "Default";
} // namespace
TEST_F(AppShimHostTest, TestLaunchAppWithHandler) {
apps::AppShimHandler::RegisterHandler(kTestAppId, this);
- EXPECT_TRUE(host()->ReceiveMessage(
- new AppShimHostMsg_LaunchApp(kTestProfileDir, kTestAppId)));
+ LaunchApp(true);
EXPECT_EQ(kTestAppId,
implicit_cast<apps::AppShimHandler::Host*>(host())->GetAppId());
EXPECT_TRUE(LaunchWasSuccessful());
EXPECT_EQ(1, launch_count_);
+ EXPECT_EQ(1, launch_now_count_);
EXPECT_EQ(0, focus_count_);
EXPECT_EQ(0, close_count_);
@@ -148,16 +157,29 @@ TEST_F(AppShimHostTest, TestLaunchAppWithHandler) {
apps::AppShimHandler::RemoveHandler(kTestAppId);
}
+TEST_F(AppShimHostTest, TestNoLaunchNow) {
+ apps::AppShimHandler::RegisterHandler(kTestAppId, this);
+ LaunchApp(false);
+ EXPECT_EQ(kTestAppId,
+ implicit_cast<apps::AppShimHandler::Host*>(host())->GetAppId());
+ EXPECT_TRUE(LaunchWasSuccessful());
+ EXPECT_EQ(1, launch_count_);
+ EXPECT_EQ(0, launch_now_count_);
+ EXPECT_EQ(0, focus_count_);
+ EXPECT_EQ(0, close_count_);
+ apps::AppShimHandler::RemoveHandler(kTestAppId);
+}
+
TEST_F(AppShimHostTest, TestFailProfile) {
host()->set_fails_profile(true);
- host()->ReceiveMessage(
- new AppShimHostMsg_LaunchApp(kTestProfileDir, kTestAppId));
+ LaunchApp(true);
ASSERT_FALSE(LaunchWasSuccessful());
}
TEST_F(AppShimHostTest, TestFailLaunch) {
- host()->set_fails_launch(true);
- host()->ReceiveMessage(
- new AppShimHostMsg_LaunchApp(kTestProfileDir, kTestAppId));
+ apps::AppShimHandler::RegisterHandler(kTestAppId, this);
+ fail_launch_ = true;
+ LaunchApp(true);
ASSERT_FALSE(LaunchWasSuccessful());
+ apps::AppShimHandler::RemoveHandler(kTestAppId);
}
diff --git a/apps/app_shim/app_shim_launch.h b/apps/app_shim/app_shim_launch.h
new file mode 100644
index 0000000..2c71333
--- /dev/null
+++ b/apps/app_shim/app_shim_launch.h
@@ -0,0 +1,20 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef APPS_APP_SHIM_APP_SHIM_LAUNCH_H_
+#define APPS_APP_SHIM_APP_SHIM_LAUNCH_H_
+
+namespace apps {
+
+enum AppShimLaunchType {
+ // Process the app shim's LaunchAppmessage and associate the shim with the
+ // given profile and app id.
+ APP_SHIM_LAUNCH_REGISTER_ONLY = 0,
+ // Do the above and launch the app.
+ APP_SHIM_LAUNCH_NORMAL,
+};
+
+} // namespace apps
+
+#endif // APPS_APP_SHIM_APP_SHIM_LAUNCH_H_
diff --git a/apps/app_shim/app_shim_messages.h b/apps/app_shim/app_shim_messages.h
index 5b8c194..1b38c39 100644
--- a/apps/app_shim/app_shim_messages.h
+++ b/apps/app_shim/app_shim_messages.h
@@ -6,20 +6,27 @@
#include <string>
+#include "apps/app_shim/app_shim_launch.h"
+#include "base/files/file_path.h"
#include "ipc/ipc_message_macros.h"
+#include "ipc/param_traits_macros.h"
#define IPC_MESSAGE_START AppShimMsgStart
+IPC_ENUM_TRAITS(apps::AppShimLaunchType)
+
// Signals that a previous LaunchApp message has been processed, and lets the
-// app shim process know whether the app launch was successful.
+// app shim process know whether it was registered successfully.
IPC_MESSAGE_CONTROL1(AppShimMsg_LaunchApp_Done,
bool /* succeeded */)
-// Tells the main Chrome process to launch a particular app with the given
-// profile name and app id.
-IPC_MESSAGE_CONTROL2(AppShimHostMsg_LaunchApp,
- std::string /* profile name */,
- std::string /* app id */)
+// Signals to the main Chrome process that a shim has started indicating the
+// profile and app_id that the shim should be associated with and whether to
+// launch the app immediately.
+IPC_MESSAGE_CONTROL3(AppShimHostMsg_LaunchApp,
+ base::FilePath /* profile dir */,
+ std::string /* app id */,
+ apps::AppShimLaunchType /* launch type */)
// Sent when the user has indicated a desire to focus the app, either by
// clicking on the app's icon in the dock or by selecting it with Cmd+Tab. In
diff --git a/apps/app_shim/extension_app_shim_handler_mac.cc b/apps/app_shim/extension_app_shim_handler_mac.cc
index 902e0c2..9e97735 100644
--- a/apps/app_shim/extension_app_shim_handler_mac.cc
+++ b/apps/app_shim/extension_app_shim_handler_mac.cc
@@ -14,11 +14,16 @@
#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 "chrome/browser/ui/web_applications/web_app_ui.h"
+#include "chrome/browser/web_applications/web_app_mac.h"
#include "ui/base/cocoa/focus_window_set.h"
namespace apps {
-ExtensionAppShimHandler::ExtensionAppShimHandler() {}
+ExtensionAppShimHandler::ExtensionAppShimHandler() {
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_CREATED,
+ content::NotificationService::AllBrowserContextsAndSources());
+}
ExtensionAppShimHandler::~ExtensionAppShimHandler() {
for (HostMap::iterator it = hosts_.begin(); it != hosts_.end(); ) {
@@ -28,7 +33,8 @@ ExtensionAppShimHandler::~ExtensionAppShimHandler() {
}
}
-bool ExtensionAppShimHandler::OnShimLaunch(Host* host) {
+bool ExtensionAppShimHandler::OnShimLaunch(Host* host,
+ AppShimLaunchType launch_type) {
Profile* profile = host->GetProfile();
DCHECK(profile);
@@ -38,13 +44,15 @@ bool ExtensionAppShimHandler::OnShimLaunch(Host* host) {
return false;
}
- if (!LaunchApp(profile, app_id))
+ if (!LaunchApp(profile, app_id, launch_type))
return false;
// The first host to claim this (profile, app_id) becomes the main host.
- // For any others, we launch the app but return false.
- if (!hosts_.insert(make_pair(make_pair(profile, app_id), host)).second)
+ // For any others, we focus the app and return false.
+ if (!hosts_.insert(make_pair(make_pair(profile, app_id), host)).second) {
+ OnShimFocus(host);
return false;
+ }
if (!registrar_.IsRegistered(
this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
@@ -95,7 +103,8 @@ void ExtensionAppShimHandler::OnShimQuit(Host* host) {
}
bool ExtensionAppShimHandler::LaunchApp(Profile* profile,
- const std::string& app_id) {
+ const std::string& app_id,
+ AppShimLaunchType launch_type) {
extensions::ExtensionSystem* extension_system =
extensions::ExtensionSystem::Get(profile);
ExtensionServiceInterface* extension_service =
@@ -107,6 +116,10 @@ bool ExtensionAppShimHandler::LaunchApp(Profile* profile,
<< app_id << "'.";
return false;
}
+
+ if (launch_type == APP_SHIM_LAUNCH_REGISTER_ONLY)
+ return true;
+
// TODO(jeremya): Handle the case that launching the app fails. Probably we
// need to watch for 'app successfully launched' or at least 'background page
// exists/was created' and time out with failure if we don't see that sign of
@@ -121,19 +134,34 @@ void ExtensionAppShimHandler::Observe(
const content::NotificationSource& source,
const content::NotificationDetails& details) {
Profile* profile = content::Source<Profile>(source).ptr();
+ extensions::ExtensionHost* extension_host =
+ content::Details<extensions::ExtensionHost>(details).ptr();
switch (type) {
- case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: {
- extensions::ExtensionHost* extension_host =
- content::Details<extensions::ExtensionHost>(details).ptr();
+ case chrome::NOTIFICATION_EXTENSION_HOST_CREATED:
+ StartShim(profile, extension_host->extension());
+ break;
+ case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED:
CloseShim(profile, extension_host->extension_id());
break;
- }
default:
NOTREACHED(); // Unexpected notification.
break;
}
}
+void ExtensionAppShimHandler::StartShim(
+ Profile* profile,
+ const extensions::Extension* extension) {
+ if (!extension->is_platform_app())
+ return;
+
+ if (hosts_.count(make_pair(profile, extension->id())))
+ return;
+
+ web_app::MaybeLaunchShortcut(
+ web_app::ShortcutInfoForExtensionAndProfile(extension, profile));
+}
+
void ExtensionAppShimHandler::CloseShim(Profile* profile,
const std::string& app_id) {
HostMap::const_iterator it = hosts_.find(make_pair(profile, app_id));
diff --git a/apps/app_shim/extension_app_shim_handler_mac.h b/apps/app_shim/extension_app_shim_handler_mac.h
index 86c86e1..f5a7d66 100644
--- a/apps/app_shim/extension_app_shim_handler_mac.h
+++ b/apps/app_shim/extension_app_shim_handler_mac.h
@@ -14,6 +14,10 @@
class Profile;
+namespace extensions {
+class Extension;
+}
+
namespace apps {
// This app shim handler that handles events for app shims that correspond to an
@@ -25,7 +29,7 @@ class ExtensionAppShimHandler : public AppShimHandler,
virtual ~ExtensionAppShimHandler();
// AppShimHandler overrides:
- virtual bool OnShimLaunch(Host* host) OVERRIDE;
+ virtual bool OnShimLaunch(Host* host, AppShimLaunchType launch_type) OVERRIDE;
virtual void OnShimClose(Host* host) OVERRIDE;
virtual void OnShimFocus(Host* host) OVERRIDE;
virtual void OnShimQuit(Host* host) OVERRIDE;
@@ -39,7 +43,9 @@ class ExtensionAppShimHandler : public AppShimHandler,
content::NotificationRegistrar& registrar() { return registrar_; }
private:
- virtual bool LaunchApp(Profile* profile, const std::string& app_id);
+ virtual bool LaunchApp(Profile* profile,
+ const std::string& app_id,
+ AppShimLaunchType launch_type);
// Listen to the NOTIFICATION_EXTENSION_HOST_DESTROYED message to detect when
// an app closes. When that happens, call OnAppClosed on the relevant
@@ -49,6 +55,8 @@ class ExtensionAppShimHandler : public AppShimHandler,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
+ void StartShim(Profile* profile, const extensions::Extension* extension);
+
void CloseShim(Profile* profile, const std::string& app_id);
HostMap hosts_;
diff --git a/apps/app_shim/extension_app_shim_handler_mac_unittest.cc b/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
index dbbbd13..651d597 100644
--- a/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
+++ b/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
@@ -31,7 +31,9 @@ class TestingExtensionAppShimHandler : public ExtensionAppShimHandler {
content::NotificationRegistrar& GetRegistrar() { return registrar(); }
protected:
- virtual bool LaunchApp(Profile* profile, const std::string& app_id) OVERRIDE {
+ virtual bool LaunchApp(Profile* profile,
+ const std::string& app_id,
+ AppShimLaunchType launch_type) OVERRIDE {
return !fails_launch_;
}
@@ -96,20 +98,20 @@ class ExtensionAppShimHandlerTest : public testing::Test {
TEST_F(ExtensionAppShimHandlerTest, LaunchAndCloseShim) {
// If launch fails, the host is not added to the map.
handler_->set_fails_launch(true);
- EXPECT_EQ(false, handler_->OnShimLaunch(&host_aa_));
+ EXPECT_EQ(false, handler_->OnShimLaunch(&host_aa_, APP_SHIM_LAUNCH_NORMAL));
EXPECT_FALSE(handler_->FindHost(&profile_a_, kTestAppIdA));
// Normal startup.
handler_->set_fails_launch(false);
- EXPECT_EQ(true, handler_->OnShimLaunch(&host_aa_));
+ EXPECT_EQ(true, handler_->OnShimLaunch(&host_aa_, APP_SHIM_LAUNCH_NORMAL));
EXPECT_EQ(&host_aa_, handler_->FindHost(&profile_a_, kTestAppIdA));
EXPECT_TRUE(handler_->GetRegistrar().IsRegistered(
handler_.get(),
chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
content::Source<Profile>(&profile_a_)));
- EXPECT_EQ(true, handler_->OnShimLaunch(&host_ab_));
+ EXPECT_EQ(true, handler_->OnShimLaunch(&host_ab_, APP_SHIM_LAUNCH_NORMAL));
EXPECT_EQ(&host_ab_, handler_->FindHost(&profile_a_, kTestAppIdB));
- EXPECT_EQ(true, handler_->OnShimLaunch(&host_bb_));
+ EXPECT_EQ(true, handler_->OnShimLaunch(&host_bb_, APP_SHIM_LAUNCH_NORMAL));
EXPECT_EQ(&host_bb_, handler_->FindHost(&profile_b_, kTestAppIdB));
EXPECT_TRUE(handler_->GetRegistrar().IsRegistered(
handler_.get(),
@@ -117,7 +119,8 @@ TEST_F(ExtensionAppShimHandlerTest, LaunchAndCloseShim) {
content::Source<Profile>(&profile_b_)));
// Starting and closing a second host does nothing.
- EXPECT_EQ(false, handler_->OnShimLaunch(&host_aa_duplicate_));
+ EXPECT_EQ(false, handler_->OnShimLaunch(&host_aa_duplicate_,
+ APP_SHIM_LAUNCH_NORMAL));
EXPECT_EQ(&host_aa_, handler_->FindHost(&profile_a_, kTestAppIdA));
handler_->OnShimClose(&host_aa_duplicate_);
EXPECT_EQ(&host_aa_, handler_->FindHost(&profile_a_, kTestAppIdA));
diff --git a/chrome/app/chrome_main_app_mode_mac.mm b/chrome/app/chrome_main_app_mode_mac.mm
index e464612..8038788 100644
--- a/chrome/app/chrome_main_app_mode_mac.mm
+++ b/chrome/app/chrome_main_app_mode_mac.mm
@@ -86,8 +86,7 @@ class AppShimController : public IPC::Listener {
DISALLOW_COPY_AND_ASSIGN(AppShimController);
};
-AppShimController::AppShimController() : channel_(NULL) {
-}
+AppShimController::AppShimController() : channel_(NULL) {}
void AppShimController::Init() {
DCHECK(g_io_thread);
@@ -108,7 +107,9 @@ void AppShimController::Init() {
this, g_io_thread->message_loop_proxy());
channel_->Send(new AppShimHostMsg_LaunchApp(
- g_info->profile_dir.value(), g_info->app_mode_id));
+ g_info->profile_dir, g_info->app_mode_id,
+ CommandLine::ForCurrentProcess()->HasSwitch(app_mode::kNoLaunchApp) ?
+ apps::APP_SHIM_LAUNCH_REGISTER_ONLY : apps::APP_SHIM_LAUNCH_NORMAL));
nsapp_delegate_.reset([[AppShimDelegate alloc] initWithController:this]);
DCHECK(![NSApp delegate]);
@@ -130,7 +131,6 @@ bool AppShimController::OnMessageReceived(const IPC::Message& message) {
}
void AppShimController::OnChannelError() {
- LOG(ERROR) << "App shim channel error.";
Close();
}
@@ -139,6 +139,7 @@ void AppShimController::OnLaunchAppDone(bool success) {
Close();
return;
}
+
[[[NSWorkspace sharedWorkspace] notificationCenter]
addObserverForName:NSWorkspaceDidActivateApplicationNotification
object:nil
@@ -319,6 +320,8 @@ int ChromeAppModeStart(const app_mode::ChromeAppModeInfo* info);
} // extern "C"
int ChromeAppModeStart(const app_mode::ChromeAppModeInfo* info) {
+ CommandLine::Init(info->argc, info->argv);
+
base::mac::ScopedNSAutoreleasePool scoped_pool;
base::AtExitManager exit_manager;
chrome::RegisterPathProvider();
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 cf8555c..d890860 100644
--- a/chrome/browser/ui/app_list/app_list_service_mac.mm
+++ b/chrome/browser/ui/app_list/app_list_service_mac.mm
@@ -61,7 +61,8 @@ class AppListServiceMac : public AppListServiceImpl,
virtual gfx::NativeWindow GetAppListWindow() OVERRIDE;
// AppShimHandler overrides:
- virtual bool OnShimLaunch(apps::AppShimHandler::Host* host) OVERRIDE;
+ virtual bool OnShimLaunch(apps::AppShimHandler::Host* host,
+ apps::AppShimLaunchType launch_type) 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;
@@ -271,7 +272,8 @@ NSWindow* AppListServiceMac::GetAppListWindow() {
return [window_controller_ window];
}
-bool AppListServiceMac::OnShimLaunch(apps::AppShimHandler::Host* host) {
+bool AppListServiceMac::OnShimLaunch(apps::AppShimHandler::Host* host,
+ apps::AppShimLaunchType launch_type) {
ShowForSavedProfile();
observers_.AddObserver(host);
return true;
diff --git a/chrome/browser/ui/app_list/app_list_service_mac_browsertest.mm b/chrome/browser/ui/app_list/app_list_service_mac_browsertest.mm
index 4f7aee7..8566af4 100644
--- a/chrome/browser/ui/app_list/app_list_service_mac_browsertest.mm
+++ b/chrome/browser/ui/app_list/app_list_service_mac_browsertest.mm
@@ -25,7 +25,8 @@ class AppListServiceMacBrowserTest : public InProcessBrowserTest,
DCHECK(!running_);
// AppList shims should always succced showing the app list.
EXPECT_TRUE(AppShimHandler::GetForAppMode(
- app_mode::kAppListModeId)->OnShimLaunch(this));
+ app_mode::kAppListModeId)->OnShimLaunch(this,
+ apps::APP_SHIM_LAUNCH_NORMAL));
running_ = true;
}
diff --git a/chrome/browser/web_applications/web_app_mac.h b/chrome/browser/web_applications/web_app_mac.h
index 236fe95..91d46d7 100644
--- a/chrome/browser/web_applications/web_app_mac.h
+++ b/chrome/browser/web_applications/web_app_mac.h
@@ -25,6 +25,9 @@ namespace web_app {
base::FilePath GetAppInstallPath(
const ShellIntegration::ShortcutInfo& shortcut_info);
+// If necessary, launch the shortcut for an app.
+void MaybeLaunchShortcut(const ShellIntegration::ShortcutInfo& shortcut_info);
+
// Creates a shortcut for a web application. The shortcut is a stub app
// that simply loads the browser framework and runs the given app.
class WebAppShortcutCreator {
diff --git a/chrome/browser/web_applications/web_app_mac.mm b/chrome/browser/web_applications/web_app_mac.mm
index 582a7b5..756f8b3 100644
--- a/chrome/browser/web_applications/web_app_mac.mm
+++ b/chrome/browser/web_applications/web_app_mac.mm
@@ -7,16 +7,19 @@
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
+#include "base/command_line.h"
#include "base/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/mac/bundle_locations.h"
#include "base/mac/foundation_util.h"
+#include "base/mac/launch_services_util.h"
#include "base/mac/mac_logging.h"
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/memory/scoped_nsobject.h"
#include "base/strings/sys_string_conversions.h"
#include "base/utf_string_conversions.h"
+#include "chrome/browser/ui/web_applications/web_app_ui.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/common/chrome_paths_internal.h"
#include "chrome/common/mac/app_mode_common.h"
@@ -316,6 +319,18 @@ void WebAppShortcutCreator::RevealGeneratedBundleInFinder(
inFileViewerRootedAtPath:nil];
}
+void LaunchShimOnFileThread(
+ const ShellIntegration::ShortcutInfo& shortcut_info) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+ base::FilePath shim_path = web_app::GetAppInstallPath(shortcut_info);
+ if (shim_path.empty())
+ return;
+
+ CommandLine command_line(CommandLine::NO_PROGRAM);
+ command_line.AppendSwitch(app_mode::kNoLaunchApp);
+ base::mac::OpenApplicationWithPath(shim_path, command_line, NULL);
+}
+
} // namespace
namespace web_app {
@@ -328,6 +343,12 @@ base::FilePath GetAppInstallPath(
return shortcut_creator.GetShortcutPath();
}
+void MaybeLaunchShortcut(const ShellIntegration::ShortcutInfo& shortcut_info) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::FILE, FROM_HERE,
+ base::Bind(&LaunchShimOnFileThread, shortcut_info));
+}
+
namespace internals {
base::FilePath GetAppBundleByExtensionId(std::string extension_id) {
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index 43700b2..28e82db 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -51,6 +51,7 @@
'<(DEPTH)/webkit/support/webkit_support.gyp:user_agent',
],
'sources': [
+ '../apps/app_shim/app_shim_launch.h',
'../apps/app_shim/app_shim_messages.h',
'../extensions/common/constants.cc',
'../extensions/common/constants.h',
diff --git a/chrome/common/mac/app_mode_common.h b/chrome/common/mac/app_mode_common.h
index eb068fa..8bb114f 100644
--- a/chrome/common/mac/app_mode_common.h
+++ b/chrome/common/mac/app_mode_common.h
@@ -29,6 +29,10 @@ extern const char kAppShimSocketName[];
// Special app mode id used for the App Launcher.
extern const char kAppListModeId[];
+// Instructs the app shim to send LaunchApp with launch_now = false. This
+// associates the shim without launching the app.
+extern const char kNoLaunchApp[];
+
// The key under which the browser's bundle ID will be stored in the
// app mode launcher bundle's Info.plist.
extern NSString* const kBrowserBundleIDKey;
diff --git a/chrome/common/mac/app_mode_common.mm b/chrome/common/mac/app_mode_common.mm
index 7be84ca..ae5e2f7 100644
--- a/chrome/common/mac/app_mode_common.mm
+++ b/chrome/common/mac/app_mode_common.mm
@@ -10,6 +10,8 @@ const char kAppShimSocketName[] = "App Shim Socket";
const char kAppListModeId[] = "app_list";
+const char kNoLaunchApp[] = "no-launch-app";
+
NSString* const kBrowserBundleIDKey = @"CrBundleIdentifier";
NSString* const kCrAppModeShortcutIDKey = @"CrAppModeShortcutID";
NSString* const kCrAppModeShortcutNameKey = @"CrAppModeShortcutName";