diff options
-rw-r--r-- | apps/DEPS | 1 | ||||
-rw-r--r-- | apps/app_shim/app_shim_handler_mac.h | 7 | ||||
-rw-r--r-- | apps/app_shim/app_shim_host_mac.cc | 31 | ||||
-rw-r--r-- | apps/app_shim/app_shim_host_mac.h | 15 | ||||
-rw-r--r-- | apps/app_shim/app_shim_host_mac_unittest.cc | 64 | ||||
-rw-r--r-- | apps/app_shim/app_shim_launch.h | 20 | ||||
-rw-r--r-- | apps/app_shim/app_shim_messages.h | 19 | ||||
-rw-r--r-- | apps/app_shim/extension_app_shim_handler_mac.cc | 48 | ||||
-rw-r--r-- | apps/app_shim/extension_app_shim_handler_mac.h | 12 | ||||
-rw-r--r-- | apps/app_shim/extension_app_shim_handler_mac_unittest.cc | 15 | ||||
-rw-r--r-- | chrome/app/chrome_main_app_mode_mac.mm | 11 | ||||
-rw-r--r-- | chrome/browser/ui/app_list/app_list_service_mac.mm | 6 | ||||
-rw-r--r-- | chrome/browser/ui/app_list/app_list_service_mac_browsertest.mm | 3 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app_mac.h | 3 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app_mac.mm | 21 | ||||
-rw-r--r-- | chrome/chrome_common.gypi | 1 | ||||
-rw-r--r-- | chrome/common/mac/app_mode_common.h | 4 | ||||
-rw-r--r-- | chrome/common/mac/app_mode_common.mm | 2 |
18 files changed, 210 insertions, 73 deletions
@@ -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"; |