diff options
Diffstat (limited to 'apps')
23 files changed, 0 insertions, 3910 deletions
diff --git a/apps/app_shim/DEPS b/apps/app_shim/DEPS deleted file mode 100644 index ec27f8a..0000000 --- a/apps/app_shim/DEPS +++ /dev/null @@ -1,19 +0,0 @@ -include_rules = [ - # TODO(benwells): move this whole folder out of apps and review these. - # See http://crbug.com/266705. - "+chrome/browser/browser_process.h", - "+chrome/browser/ui/app_list/app_list_service.h", - "+chrome/browser/ui/app_list/app_list_util.h", - "+chrome/browser/ui/extensions/application_launch.h", - "+chrome/browser/ui/extensions/extension_enable_flow.h", - "+chrome/browser/ui/extensions/extension_enable_flow_delegate.h", - "+chrome/browser/ui/webui/ntp/core_app_launcher_handler.h", - "+chrome/browser/web_applications/web_app_mac.h", - "+chrome/common/chrome_constants.h", - "+chrome/common/chrome_paths.h", - "+chrome/common/chrome_version_info.h", - "+chrome/common/extensions/extension_constants.h", - "+chrome/common/mac/app_mode_common.h", - "+components/crx_file", - "+grit/generated_resources.h", -] diff --git a/apps/app_shim/OWNERS b/apps/app_shim/OWNERS deleted file mode 100644 index 13c6f49..0000000 --- a/apps/app_shim/OWNERS +++ /dev/null @@ -1 +0,0 @@ -tapted@chromium.org diff --git a/apps/app_shim/app_shim.gypi b/apps/app_shim/app_shim.gypi deleted file mode 100644 index 51a729a..0000000 --- a/apps/app_shim/app_shim.gypi +++ /dev/null @@ -1,36 +0,0 @@ -# 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. - -{ - 'targets': [ - { - 'target_name': 'app_shim', - 'type': 'static_library', - # Since app_shim and browser depend on each other, we omit the dependency - # on browser here. - 'dependencies': [ - '../chrome/chrome_resources.gyp:chrome_strings', - '../content/content.gyp:content_common', - '../skia/skia.gyp:skia', - ], - 'include_dirs': [ - '<(INTERMEDIATE_DIR)', - '<(grit_out_dir)', - ], - 'sources': [ - 'app_shim_handler_mac.cc', - 'app_shim_handler_mac.h', - 'app_shim_host_mac.cc', - 'app_shim_host_mac.h', - 'app_shim_host_manager_mac.h', - 'app_shim_host_manager_mac.mm', - 'chrome_main_app_mode_mac.mm', - 'extension_app_shim_handler_mac.cc', - 'extension_app_shim_handler_mac.h', - 'unix_domain_socket_acceptor.cc', - 'unix_domain_socket_acceptor.h', - ], - }, - ], # targets -} diff --git a/apps/app_shim/app_shim_handler_mac.cc b/apps/app_shim/app_shim_handler_mac.cc deleted file mode 100644 index 3153bd4..0000000 --- a/apps/app_shim/app_shim_handler_mac.cc +++ /dev/null @@ -1,156 +0,0 @@ -// 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. - -#include "apps/app_shim/app_shim_handler_mac.h" - -#include <map> - -#include "base/bind.h" -#include "base/logging.h" -#include "base/memory/singleton.h" -#include "base/message_loop/message_loop.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/lifetime/application_lifetime.h" -#include "chrome/browser/ui/app_list/app_list_service.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" -#include "content/public/browser/notification_service.h" -#include "extensions/browser/app_window/app_window_registry.h" - -namespace apps { - -namespace { - -void TerminateIfNoAppWindows() { - bool app_windows_left = - extensions::AppWindowRegistry::IsAppWindowRegisteredInAnyProfile(0); - if (!app_windows_left && - !AppListService::Get(chrome::HOST_DESKTOP_TYPE_NATIVE) - ->IsAppListVisible()) { - chrome::AttemptExit(); - } -} - -class AppShimHandlerRegistry : public content::NotificationObserver { - public: - static AppShimHandlerRegistry* GetInstance() { - return Singleton<AppShimHandlerRegistry, - LeakySingletonTraits<AppShimHandlerRegistry> >::get(); - } - - AppShimHandler* GetForAppMode(const std::string& app_mode_id) const { - HandlerMap::const_iterator it = handlers_.find(app_mode_id); - if (it != handlers_.end()) - return it->second; - - return default_handler_; - } - - bool SetForAppMode(const std::string& app_mode_id, AppShimHandler* handler) { - bool inserted_or_removed = handler ? - handlers_.insert(HandlerMap::value_type(app_mode_id, handler)).second : - handlers_.erase(app_mode_id) == 1; - DCHECK(inserted_or_removed); - return inserted_or_removed; - } - - void SetDefaultHandler(AppShimHandler* handler) { - DCHECK_NE(default_handler_ == NULL, handler == NULL); - default_handler_ = handler; - } - - void MaybeTerminate() { - if (!browser_session_running_) { - // Post this to give AppWindows a chance to remove themselves from the - // registry. - base::MessageLoop::current()->PostTask( - FROM_HERE, base::Bind(&TerminateIfNoAppWindows)); - } - } - - bool ShouldRestoreSession() { - return !browser_session_running_; - } - - private: - friend struct DefaultSingletonTraits<AppShimHandlerRegistry>; - typedef std::map<std::string, AppShimHandler*> HandlerMap; - - AppShimHandlerRegistry() - : default_handler_(NULL), - browser_session_running_(false) { - registrar_.Add( - this, chrome::NOTIFICATION_BROWSER_OPENED, - content::NotificationService::AllBrowserContextsAndSources()); - registrar_.Add( - this, chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST, - content::NotificationService::AllBrowserContextsAndSources()); - registrar_.Add( - this, chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, - content::NotificationService::AllBrowserContextsAndSources()); - } - - virtual ~AppShimHandlerRegistry() {} - - // content::NotificationObserver override: - virtual void Observe( - int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) OVERRIDE { - switch (type) { - case chrome::NOTIFICATION_BROWSER_OPENED: - case chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED: - browser_session_running_ = true; - break; - case chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST: - browser_session_running_ = false; - break; - default: - NOTREACHED(); - } - } - - HandlerMap handlers_; - AppShimHandler* default_handler_; - content::NotificationRegistrar registrar_; - bool browser_session_running_; - - DISALLOW_COPY_AND_ASSIGN(AppShimHandlerRegistry); -}; - -} // namespace - -// static -void AppShimHandler::RegisterHandler(const std::string& app_mode_id, - AppShimHandler* handler) { - DCHECK(handler); - AppShimHandlerRegistry::GetInstance()->SetForAppMode(app_mode_id, handler); -} - -// static -void AppShimHandler::RemoveHandler(const std::string& app_mode_id) { - AppShimHandlerRegistry::GetInstance()->SetForAppMode(app_mode_id, NULL); -} - -// static -AppShimHandler* AppShimHandler::GetForAppMode(const std::string& app_mode_id) { - return AppShimHandlerRegistry::GetInstance()->GetForAppMode(app_mode_id); -} - -// static -void AppShimHandler::SetDefaultHandler(AppShimHandler* handler) { - AppShimHandlerRegistry::GetInstance()->SetDefaultHandler(handler); -} - -// static -void AppShimHandler::MaybeTerminate() { - AppShimHandlerRegistry::GetInstance()->MaybeTerminate(); -} - -// static -bool AppShimHandler::ShouldRestoreSession() { - return AppShimHandlerRegistry::GetInstance()->ShouldRestoreSession(); -} - -} // namespace apps diff --git a/apps/app_shim/app_shim_handler_mac.h b/apps/app_shim/app_shim_handler_mac.h deleted file mode 100644 index 2cc3425..0000000 --- a/apps/app_shim/app_shim_handler_mac.h +++ /dev/null @@ -1,96 +0,0 @@ -// 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_HANDLER_MAC_H_ -#define APPS_APP_SHIM_APP_SHIM_HANDLER_MAC_H_ - -#include <string> -#include <vector> - -#include "apps/app_shim/app_shim_launch.h" -#include "base/files/file_path.h" - -namespace apps { - -// Registrar, and interface for services that can handle interactions with OSX -// shim processes. -class AppShimHandler { - public: - class Host { - public: - // Invoked when the app is successfully launched. - virtual void OnAppLaunchComplete(AppShimLaunchResult result) = 0; - // Invoked when the app is closed in the browser process. - virtual void OnAppClosed() = 0; - // Invoked when the app should be hidden. - virtual void OnAppHide() = 0; - // Invoked when the app is requesting user attention. - virtual void OnAppRequestUserAttention(AppShimAttentionType type) = 0; - - // Allows the handler to determine which app this host corresponds to. - virtual base::FilePath GetProfilePath() const = 0; - virtual std::string GetAppId() const = 0; - - protected: - virtual ~Host() {} - }; - - // Register a handler for an |app_mode_id|. - static void RegisterHandler(const std::string& app_mode_id, - AppShimHandler* handler); - - // Remove a handler for an |app_mode_id|. - static void RemoveHandler(const std::string& app_mode_id); - - // Returns the handler registered for the given |app_mode_id|. If there is - // none registered, it returns the default handler or NULL if there is no - // default handler. - static AppShimHandler* GetForAppMode(const std::string& app_mode_id); - - // Sets the default handler to return when there is no app-specific handler. - // Setting this to NULL removes the default handler. - static void SetDefaultHandler(AppShimHandler* handler); - - // Terminate Chrome if a browser window has never been opened, there are no - // shell windows, and the app list is not visible. - static void MaybeTerminate(); - - // Whether browser sessions should be restored right now. This is true if - // the browser has been quit but kept alive because Chrome Apps are still - // running. - static bool ShouldRestoreSession(); - - // Invoked by the shim host when the shim process is launched. The handler - // must call OnAppLaunchComplete to inform the shim of the result. - // |launch_type| indicates the type of launch. - // |files|, if non-empty, holds an array of files paths given as arguments, or - // dragged onto the app bundle or dock icon. - virtual void OnShimLaunch(Host* host, - AppShimLaunchType launch_type, - const std::vector<base::FilePath>& files) = 0; - - // Invoked by the shim host when the connection to the shim process is closed. - virtual void OnShimClose(Host* host) = 0; - - // Invoked by the shim host when the shim process receives a focus event. - // |files|, if non-empty, holds an array of files dragged onto the app bundle - // or dock icon. - virtual void OnShimFocus(Host* host, - AppShimFocusType focus_type, - const std::vector<base::FilePath>& files) = 0; - - // Invoked by the shim host when the shim process is hidden or shown. - virtual void OnShimSetHidden(Host* host, bool hidden) = 0; - - // Invoked by the shim host when the shim process receives a quit event. - virtual void OnShimQuit(Host* host) = 0; - - protected: - AppShimHandler() {} - virtual ~AppShimHandler() {} -}; - -} // namespace apps - -#endif // APPS_APP_SHIM_APP_SHIM_HANDLER_MAC_H_ diff --git a/apps/app_shim/app_shim_host_mac.cc b/apps/app_shim/app_shim_host_mac.cc deleted file mode 100644 index b8a6b90..0000000 --- a/apps/app_shim/app_shim_host_mac.cc +++ /dev/null @@ -1,130 +0,0 @@ -// 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. - -#include "apps/app_shim/app_shim_host_mac.h" - -#include "apps/app_shim/app_shim_handler_mac.h" -#include "apps/app_shim/app_shim_messages.h" -#include "base/bind.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "content/public/browser/browser_thread.h" -#include "ipc/ipc_channel_proxy.h" - -AppShimHost::AppShimHost() : initial_launch_finished_(false) {} - -AppShimHost::~AppShimHost() { - DCHECK(CalledOnValidThread()); - apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_); - if (handler) - handler->OnShimClose(this); -} - -void AppShimHost::ServeChannel(const IPC::ChannelHandle& handle) { - DCHECK(CalledOnValidThread()); - DCHECK(!channel_.get()); - channel_ = IPC::ChannelProxy::Create( - handle, - IPC::Channel::MODE_SERVER, - this, - content::BrowserThread::GetMessageLoopProxyForThread( - content::BrowserThread::IO).get()); -} - -base::FilePath AppShimHost::GetProfilePath() const { - return profile_path_; -} - -std::string AppShimHost::GetAppId() const { - return app_id_; -} - -bool AppShimHost::OnMessageReceived(const IPC::Message& message) { - DCHECK(CalledOnValidThread()); - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(AppShimHost, message) - IPC_MESSAGE_HANDLER(AppShimHostMsg_LaunchApp, OnLaunchApp) - IPC_MESSAGE_HANDLER(AppShimHostMsg_FocusApp, OnFocus) - IPC_MESSAGE_HANDLER(AppShimHostMsg_SetAppHidden, OnSetHidden) - IPC_MESSAGE_HANDLER(AppShimHostMsg_QuitApp, OnQuit) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - - return handled; -} - -void AppShimHost::OnChannelError() { - Close(); -} - -bool AppShimHost::Send(IPC::Message* message) { - DCHECK(channel_.get()); - return channel_->Send(message); -} - -void AppShimHost::OnLaunchApp(const base::FilePath& profile_dir, - const std::string& app_id, - apps::AppShimLaunchType launch_type, - const std::vector<base::FilePath>& files) { - DCHECK(CalledOnValidThread()); - DCHECK(profile_path_.empty()); - // Only one app launch message per channel. - if (!profile_path_.empty()) - return; - - profile_path_ = profile_dir; - app_id_ = app_id; - - apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_); - if (handler) - handler->OnShimLaunch(this, launch_type, files); - // |handler| can only be NULL after AppShimHostManager is destroyed. Since - // this only happens at shutdown, do nothing here. -} - -void AppShimHost::OnFocus(apps::AppShimFocusType focus_type, - const std::vector<base::FilePath>& files) { - DCHECK(CalledOnValidThread()); - apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_); - if (handler) - handler->OnShimFocus(this, focus_type, files); -} - -void AppShimHost::OnSetHidden(bool hidden) { - DCHECK(CalledOnValidThread()); - apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_); - if (handler) - handler->OnShimSetHidden(this, hidden); -} - -void AppShimHost::OnQuit() { - DCHECK(CalledOnValidThread()); - apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_); - if (handler) - handler->OnShimQuit(this); -} - -void AppShimHost::OnAppLaunchComplete(apps::AppShimLaunchResult result) { - if (!initial_launch_finished_) { - Send(new AppShimMsg_LaunchApp_Done(result)); - initial_launch_finished_ = true; - } -} - -void AppShimHost::OnAppClosed() { - Close(); -} - -void AppShimHost::OnAppHide() { - Send(new AppShimMsg_Hide); -} - -void AppShimHost::OnAppRequestUserAttention(apps::AppShimAttentionType type) { - Send(new AppShimMsg_SetUserAttention(type)); -} - -void AppShimHost::Close() { - DCHECK(CalledOnValidThread()); - delete this; -} diff --git a/apps/app_shim/app_shim_host_mac.h b/apps/app_shim/app_shim_host_mac.h deleted file mode 100644 index 5b3f00e..0000000 --- a/apps/app_shim/app_shim_host_mac.h +++ /dev/null @@ -1,86 +0,0 @@ -// 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_HOST_MAC_H_ -#define APPS_APP_SHIM_APP_SHIM_HOST_MAC_H_ - -#include <string> -#include <vector> - -#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" -#include "ipc/ipc_sender.h" - -namespace IPC { -struct ChannelHandle; -class ChannelProxy; -class Message; -} // namespace IPC - -// This is the counterpart to AppShimController in -// chrome/app/chrome_main_app_mode_mac.mm. The AppShimHost owns itself, and is -// destroyed when the app it corresponds to is closed or when the channel -// connected to the app shim is closed. -class AppShimHost : public IPC::Listener, - public IPC::Sender, - public apps::AppShimHandler::Host, - public base::NonThreadSafe { - public: - AppShimHost(); - virtual ~AppShimHost(); - - // Creates a new server-side IPC channel at |handle|, which should contain a - // file descriptor of a channel created by an UnixDomainSocketAcceptor, - // and begins listening for messages on it. - void ServeChannel(const IPC::ChannelHandle& handle); - - protected: - // IPC::Listener implementation. - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - virtual void OnChannelError() OVERRIDE; - - // IPC::Sender implementation. - virtual bool Send(IPC::Message* message) OVERRIDE; - - private: - // 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(const base::FilePath& profile_dir, - const std::string& app_id, - apps::AppShimLaunchType launch_type, - const std::vector<base::FilePath>& files); - - // Called when the app shim process notifies that the app was focused. - void OnFocus(apps::AppShimFocusType focus_type, - const std::vector<base::FilePath>& files); - - void OnSetHidden(bool hidden); - - // Called when the app shim process notifies that the app should quit. - void OnQuit(); - - // apps::AppShimHandler::Host overrides: - virtual void OnAppLaunchComplete(apps::AppShimLaunchResult result) OVERRIDE; - virtual void OnAppClosed() OVERRIDE; - virtual void OnAppHide() OVERRIDE; - virtual void OnAppRequestUserAttention( - apps::AppShimAttentionType type) OVERRIDE; - virtual base::FilePath GetProfilePath() const OVERRIDE; - virtual std::string GetAppId() const OVERRIDE; - - // Closes the channel and destroys the AppShimHost. - void Close(); - - scoped_ptr<IPC::ChannelProxy> channel_; - std::string app_id_; - base::FilePath profile_path_; - bool initial_launch_finished_; -}; - -#endif // APPS_APP_SHIM_APP_SHIM_HOST_MAC_H_ diff --git a/apps/app_shim/app_shim_host_mac_unittest.cc b/apps/app_shim/app_shim_host_mac_unittest.cc deleted file mode 100644 index b4b56fb6..0000000 --- a/apps/app_shim/app_shim_host_mac_unittest.cc +++ /dev/null @@ -1,175 +0,0 @@ -// 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. - -#include "apps/app_shim/app_shim_host_mac.h" - -#include <vector> - -#include "apps/app_shim/app_shim_messages.h" -#include "base/basictypes.h" -#include "base/memory/scoped_vector.h" -#include "ipc/ipc_message.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -class TestingAppShimHost : public AppShimHost { - public: - TestingAppShimHost() {} - virtual ~TestingAppShimHost() {} - - bool ReceiveMessage(IPC::Message* message); - - const std::vector<IPC::Message*>& sent_messages() { - return sent_messages_.get(); - } - - protected: - virtual bool Send(IPC::Message* message) OVERRIDE; - - private: - ScopedVector<IPC::Message> sent_messages_; - - DISALLOW_COPY_AND_ASSIGN(TestingAppShimHost); -}; - -bool TestingAppShimHost::ReceiveMessage(IPC::Message* message) { - bool handled = OnMessageReceived(*message); - delete message; - return handled; -} - -bool TestingAppShimHost::Send(IPC::Message* message) { - sent_messages_.push_back(message); - return true; -} - -const char kTestAppId[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; -const char kTestProfileDir[] = "Profile 1"; - -class AppShimHostTest : public testing::Test, - public apps::AppShimHandler { - public: - AppShimHostTest() : launch_result_(apps::APP_SHIM_LAUNCH_SUCCESS), - launch_count_(0), - launch_now_count_(0), - close_count_(0), - focus_count_(0), - quit_count_(0) {} - - TestingAppShimHost* host() { return host_.get(); } - - void LaunchApp(apps::AppShimLaunchType launch_type) { - EXPECT_TRUE(host()->ReceiveMessage( - new AppShimHostMsg_LaunchApp(base::FilePath(kTestProfileDir), - kTestAppId, - launch_type, - std::vector<base::FilePath>()))); - } - - apps::AppShimLaunchResult GetLaunchResult() { - EXPECT_EQ(1u, host()->sent_messages().size()); - IPC::Message* message = host()->sent_messages()[0]; - EXPECT_EQ(AppShimMsg_LaunchApp_Done::ID, message->type()); - AppShimMsg_LaunchApp_Done::Param param; - AppShimMsg_LaunchApp_Done::Read(message, ¶m); - return param.a; - } - - void SimulateDisconnect() { - implicit_cast<IPC::Listener*>(host_.release())->OnChannelError(); - } - - protected: - virtual void OnShimLaunch(Host* host, - apps::AppShimLaunchType launch_type, - const std::vector<base::FilePath>& file) OVERRIDE { - ++launch_count_; - if (launch_type == apps::APP_SHIM_LAUNCH_NORMAL) - ++launch_now_count_; - host->OnAppLaunchComplete(launch_result_); - } - - virtual void OnShimClose(Host* host) OVERRIDE { ++close_count_; } - - virtual void OnShimFocus(Host* host, - apps::AppShimFocusType focus_type, - const std::vector<base::FilePath>& file) OVERRIDE { - ++focus_count_; - } - - virtual void OnShimSetHidden(Host* host, bool hidden) OVERRIDE {} - - virtual void OnShimQuit(Host* host) OVERRIDE { ++quit_count_; } - - apps::AppShimLaunchResult launch_result_; - int launch_count_; - int launch_now_count_; - int close_count_; - int focus_count_; - int quit_count_; - - private: - virtual void SetUp() OVERRIDE { - testing::Test::SetUp(); - host_.reset(new TestingAppShimHost()); - } - - scoped_ptr<TestingAppShimHost> host_; - - DISALLOW_COPY_AND_ASSIGN(AppShimHostTest); -}; - - -} // namespace - -TEST_F(AppShimHostTest, TestLaunchAppWithHandler) { - apps::AppShimHandler::RegisterHandler(kTestAppId, this); - LaunchApp(apps::APP_SHIM_LAUNCH_NORMAL); - EXPECT_EQ(kTestAppId, - implicit_cast<apps::AppShimHandler::Host*>(host())->GetAppId()); - EXPECT_EQ(apps::APP_SHIM_LAUNCH_SUCCESS, GetLaunchResult()); - EXPECT_EQ(1, launch_count_); - EXPECT_EQ(1, launch_now_count_); - EXPECT_EQ(0, focus_count_); - EXPECT_EQ(0, close_count_); - - // A second OnAppLaunchComplete is ignored. - implicit_cast<apps::AppShimHandler::Host*>(host())-> - OnAppLaunchComplete(apps::APP_SHIM_LAUNCH_APP_NOT_FOUND); - EXPECT_EQ(apps::APP_SHIM_LAUNCH_SUCCESS, GetLaunchResult()); - - EXPECT_TRUE(host()->ReceiveMessage( - new AppShimHostMsg_FocusApp(apps::APP_SHIM_FOCUS_NORMAL, - std::vector<base::FilePath>()))); - 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); -} - -TEST_F(AppShimHostTest, TestNoLaunchNow) { - apps::AppShimHandler::RegisterHandler(kTestAppId, this); - LaunchApp(apps::APP_SHIM_LAUNCH_REGISTER_ONLY); - EXPECT_EQ(kTestAppId, - implicit_cast<apps::AppShimHandler::Host*>(host())->GetAppId()); - EXPECT_EQ(apps::APP_SHIM_LAUNCH_SUCCESS, GetLaunchResult()); - 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, TestFailLaunch) { - apps::AppShimHandler::RegisterHandler(kTestAppId, this); - launch_result_ = apps::APP_SHIM_LAUNCH_APP_NOT_FOUND; - LaunchApp(apps::APP_SHIM_LAUNCH_NORMAL); - EXPECT_EQ(apps::APP_SHIM_LAUNCH_APP_NOT_FOUND, GetLaunchResult()); - apps::AppShimHandler::RemoveHandler(kTestAppId); -} diff --git a/apps/app_shim/app_shim_host_manager_browsertest_mac.mm b/apps/app_shim/app_shim_host_manager_browsertest_mac.mm deleted file mode 100644 index 0ab7003..0000000 --- a/apps/app_shim/app_shim_host_manager_browsertest_mac.mm +++ /dev/null @@ -1,287 +0,0 @@ -// 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. - -#include "apps/app_shim/app_shim_host_manager_mac.h" - -#include <unistd.h> - -#include "apps/app_shim/app_shim_messages.h" -#include "apps/app_shim/test/app_shim_host_manager_test_api_mac.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/path_service.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/chrome_version_info.h" -#include "chrome/common/mac/app_mode_common.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "content/public/test/test_utils.h" -#include "ipc/ipc_channel_proxy.h" -#include "ipc/ipc_listener.h" -#include "ipc/ipc_message.h" - -namespace { - -const char kTestAppMode[] = "test_app"; - -// A test version of the AppShimController IPC client in chrome_main_app_mode. -class TestShimClient : public IPC::Listener { - public: - TestShimClient(); - virtual ~TestShimClient(); - - template <class T> - void Send(const T& message) { - channel_->Send(message); - } - - private: - // IPC::Listener overrides: - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - virtual void OnChannelError() OVERRIDE; - - base::Thread io_thread_; - scoped_ptr<IPC::ChannelProxy> channel_; - - DISALLOW_COPY_AND_ASSIGN(TestShimClient); -}; - -TestShimClient::TestShimClient() : io_thread_("TestShimClientIO") { - base::Thread::Options io_thread_options; - io_thread_options.message_loop_type = base::MessageLoop::TYPE_IO; - io_thread_.StartWithOptions(io_thread_options); - - base::FilePath user_data_dir; - CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)); - base::FilePath symlink_path = - user_data_dir.Append(app_mode::kAppShimSocketSymlinkName); - - base::FilePath socket_path; - CHECK(base::ReadSymbolicLink(symlink_path, &socket_path)); - app_mode::VerifySocketPermissions(socket_path); - - IPC::ChannelHandle handle(socket_path.value()); - channel_ = IPC::ChannelProxy::Create(handle, - IPC::Channel::MODE_NAMED_CLIENT, - this, - io_thread_.message_loop_proxy().get()); -} - -TestShimClient::~TestShimClient() {} - -bool TestShimClient::OnMessageReceived(const IPC::Message& message) { - return true; -} - -void TestShimClient::OnChannelError() { - // Client should not get any channel errors for the current set of tests. - PLOG(FATAL) << "ChannelError"; -} - -// Browser Test for AppShimHostManager to test IPC interactions across the -// UNIX domain socket. -class AppShimHostManagerBrowserTest : public InProcessBrowserTest, - public apps::AppShimHandler { - public: - AppShimHostManagerBrowserTest(); - virtual ~AppShimHostManagerBrowserTest(); - - protected: - // Wait for OnShimLaunch, then send a quit, and wait for the response. Used to - // test launch behavior. - void RunAndExitGracefully(); - - // InProcessBrowserTest overrides: - virtual void SetUpOnMainThread() OVERRIDE; - virtual void TearDownOnMainThread() OVERRIDE; - - // AppShimHandler overrides: - virtual void OnShimLaunch(apps::AppShimHandler::Host* host, - apps::AppShimLaunchType launch_type, - const std::vector<base::FilePath>& files) OVERRIDE; - virtual void OnShimClose(apps::AppShimHandler::Host* host) OVERRIDE {} - virtual void OnShimFocus(apps::AppShimHandler::Host* host, - apps::AppShimFocusType focus_type, - const std::vector<base::FilePath>& files) OVERRIDE {} - virtual void OnShimSetHidden(apps::AppShimHandler::Host* host, - bool hidden) OVERRIDE {} - virtual void OnShimQuit(apps::AppShimHandler::Host* host) OVERRIDE; - - scoped_ptr<TestShimClient> test_client_; - std::vector<base::FilePath> last_launch_files_; - apps::AppShimLaunchType last_launch_type_; - -private: - scoped_refptr<content::MessageLoopRunner> runner_; - - int launch_count_; - int quit_count_; - - DISALLOW_COPY_AND_ASSIGN(AppShimHostManagerBrowserTest); -}; - -AppShimHostManagerBrowserTest::AppShimHostManagerBrowserTest() - : last_launch_type_(apps::APP_SHIM_LAUNCH_NUM_TYPES), - launch_count_(0), - quit_count_(0) { -} - -AppShimHostManagerBrowserTest::~AppShimHostManagerBrowserTest() { -} - -void AppShimHostManagerBrowserTest::RunAndExitGracefully() { - runner_ = new content::MessageLoopRunner(); - EXPECT_EQ(0, launch_count_); - runner_->Run(); // Will stop in OnShimLaunch(). - EXPECT_EQ(1, launch_count_); - - runner_ = new content::MessageLoopRunner(); - test_client_->Send(new AppShimHostMsg_QuitApp); - EXPECT_EQ(0, quit_count_); - runner_->Run(); // Will stop in OnShimQuit(). - EXPECT_EQ(1, quit_count_); - - test_client_.reset(); -} - -void AppShimHostManagerBrowserTest::SetUpOnMainThread() { - // Can't do this in the constructor, it needs a BrowserProcess. - apps::AppShimHandler::RegisterHandler(kTestAppMode, this); -} - -void AppShimHostManagerBrowserTest::TearDownOnMainThread() { - apps::AppShimHandler::RemoveHandler(kTestAppMode); -} - -void AppShimHostManagerBrowserTest::OnShimLaunch( - apps::AppShimHandler::Host* host, - apps::AppShimLaunchType launch_type, - const std::vector<base::FilePath>& files) { - host->OnAppLaunchComplete(apps::APP_SHIM_LAUNCH_SUCCESS); - ++launch_count_; - last_launch_type_ = launch_type; - last_launch_files_ = files; - runner_->Quit(); -} - -void AppShimHostManagerBrowserTest::OnShimQuit( - apps::AppShimHandler::Host* host) { - ++quit_count_; - runner_->Quit(); -} - -// Test regular launch, which would ask Chrome to launch the app. -IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTest, LaunchNormal) { - test_client_.reset(new TestShimClient()); - test_client_->Send(new AppShimHostMsg_LaunchApp( - browser()->profile()->GetPath(), - kTestAppMode, - apps::APP_SHIM_LAUNCH_NORMAL, - std::vector<base::FilePath>())); - - RunAndExitGracefully(); - EXPECT_EQ(apps::APP_SHIM_LAUNCH_NORMAL, last_launch_type_); - EXPECT_TRUE(last_launch_files_.empty()); -} - -// Test register-only launch, used when Chrome has already launched the app. -IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTest, LaunchRegisterOnly) { - test_client_.reset(new TestShimClient()); - test_client_->Send(new AppShimHostMsg_LaunchApp( - browser()->profile()->GetPath(), - kTestAppMode, - apps::APP_SHIM_LAUNCH_REGISTER_ONLY, - std::vector<base::FilePath>())); - - RunAndExitGracefully(); - EXPECT_EQ(apps::APP_SHIM_LAUNCH_REGISTER_ONLY, last_launch_type_); - EXPECT_TRUE(last_launch_files_.empty()); -} - -// Ensure the domain socket can be created in a fresh user data dir. -IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTest, - PRE_ReCreate) { - test::AppShimHostManagerTestApi test_api( - g_browser_process->platform_part()->app_shim_host_manager()); - EXPECT_TRUE(test_api.acceptor()); -} - -// Ensure the domain socket can be re-created after a prior browser process has -// quit. -IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTest, - ReCreate) { - test::AppShimHostManagerTestApi test_api( - g_browser_process->platform_part()->app_shim_host_manager()); - EXPECT_TRUE(test_api.acceptor()); -} - -// Tests for the files created by AppShimHostManager. -class AppShimHostManagerBrowserTestSocketFiles - : public AppShimHostManagerBrowserTest { - public: - AppShimHostManagerBrowserTestSocketFiles() {} - - protected: - base::FilePath directory_in_tmp_; - base::FilePath symlink_path_; - base::FilePath version_path_; - - private: - virtual bool SetUpUserDataDirectory() OVERRIDE; - virtual void TearDownInProcessBrowserTestFixture() OVERRIDE; - - DISALLOW_COPY_AND_ASSIGN(AppShimHostManagerBrowserTestSocketFiles); -}; - -bool AppShimHostManagerBrowserTestSocketFiles::SetUpUserDataDirectory() { - // Create an existing symlink. It should be replaced by AppShimHostManager. - base::FilePath user_data_dir; - EXPECT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)); - symlink_path_ = user_data_dir.Append(app_mode::kAppShimSocketSymlinkName); - base::FilePath temp_dir; - PathService::Get(base::DIR_TEMP, &temp_dir); - EXPECT_TRUE(base::CreateSymbolicLink(temp_dir.Append("chrome-XXXXXX"), - symlink_path_)); - - // Create an invalid RunningChromeVersion file. - version_path_ = - user_data_dir.Append(app_mode::kRunningChromeVersionSymlinkName); - EXPECT_TRUE(base::CreateSymbolicLink(base::FilePath("invalid_version"), - version_path_)); - return AppShimHostManagerBrowserTest::SetUpUserDataDirectory(); -} - -void AppShimHostManagerBrowserTestSocketFiles:: - TearDownInProcessBrowserTestFixture() { - // Check that created files have been deleted. - EXPECT_FALSE(base::PathExists(directory_in_tmp_)); - EXPECT_FALSE(base::PathExists(symlink_path_)); - EXPECT_FALSE(base::PathExists(version_path_)); -} - -IN_PROC_BROWSER_TEST_F(AppShimHostManagerBrowserTestSocketFiles, - ReplacesSymlinkAndCleansUpFiles) { - // Get the directory created by AppShimHostManager. - test::AppShimHostManagerTestApi test_api( - g_browser_process->platform_part()->app_shim_host_manager()); - directory_in_tmp_ = test_api.directory_in_tmp(); - - // Check that socket files have been created. - EXPECT_TRUE(base::PathExists(directory_in_tmp_)); - EXPECT_TRUE(base::PathExists(symlink_path_)); - - // Check that the symlink has been replaced. - base::FilePath socket_path; - ASSERT_TRUE(base::ReadSymbolicLink(symlink_path_, &socket_path)); - EXPECT_EQ(app_mode::kAppShimSocketShortName, socket_path.BaseName().value()); - - // Check that the RunningChromeVersion file is correctly written. - base::FilePath version; - EXPECT_TRUE(base::ReadSymbolicLink(version_path_, &version)); - EXPECT_EQ(chrome::VersionInfo().Version(), version.value()); -} - -} // namespace diff --git a/apps/app_shim/app_shim_host_manager_mac.h b/apps/app_shim/app_shim_host_manager_mac.h deleted file mode 100644 index 037c4f2..0000000 --- a/apps/app_shim/app_shim_host_manager_mac.h +++ /dev/null @@ -1,73 +0,0 @@ -// 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_HOST_MANAGER_MAC_H_ -#define APPS_APP_SHIM_APP_SHIM_HOST_MANAGER_MAC_H_ - -#include "apps/app_shim/extension_app_shim_handler_mac.h" -#include "apps/app_shim/unix_domain_socket_acceptor.h" -#include "base/memory/ref_counted.h" -#include "content/public/browser/browser_thread.h" - -namespace base { -class FilePath; -} - -namespace test { -class AppShimHostManagerTestApi; -} - -// The AppShimHostManager receives connections from app shims on a UNIX -// socket (|acceptor_|) and creates a helper object to manage the connection. -class AppShimHostManager : public apps::UnixDomainSocketAcceptor::Delegate, - public base::RefCountedThreadSafe< - AppShimHostManager, - content::BrowserThread::DeleteOnUIThread> { - public: - AppShimHostManager(); - - // Init passes this AppShimHostManager to PostTask which requires it to have - // a non-zero refcount. Therefore, Init cannot be called in the constructor - // since the refcount is zero at that point. - void Init(); - - apps::ExtensionAppShimHandler* extension_app_shim_handler() { - return &extension_app_shim_handler_; - } - - private: - friend class base::RefCountedThreadSafe<AppShimHostManager>; - friend struct content::BrowserThread::DeleteOnThread< - content::BrowserThread::UI>; - friend class base::DeleteHelper<AppShimHostManager>; - friend class test::AppShimHostManagerTestApi; - virtual ~AppShimHostManager(); - - // UnixDomainSocketAcceptor::Delegate implementation. - virtual void OnClientConnected(const IPC::ChannelHandle& handle) OVERRIDE; - virtual void OnListenError() OVERRIDE; - - // The |acceptor_| must be created on a thread which allows blocking I/O, so - // part of the initialization of this class must be carried out on the file - // thread. - void InitOnFileThread(); - - // Called on the IO thread to begin listening for connections from app shims. - void ListenOnIOThread(); - - // The AppShimHostManager is only initialized if the Chrome process - // successfully took the singleton lock. This prevents subsequent processes - // from deleting existing app shim socket files. - bool did_init_; - - base::FilePath directory_in_tmp_; - - scoped_ptr<apps::UnixDomainSocketAcceptor> acceptor_; - - apps::ExtensionAppShimHandler extension_app_shim_handler_; - - DISALLOW_COPY_AND_ASSIGN(AppShimHostManager); -}; - -#endif // APPS_APP_SHIM_APP_SHIM_HOST_MANAGER_MAC_H_ diff --git a/apps/app_shim/app_shim_host_manager_mac.mm b/apps/app_shim/app_shim_host_manager_mac.mm deleted file mode 100644 index 6ea9ef1..0000000 --- a/apps/app_shim/app_shim_host_manager_mac.mm +++ /dev/null @@ -1,168 +0,0 @@ -// 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. - -#include "apps/app_shim/app_shim_host_manager_mac.h" - -#include <unistd.h> - -#include "apps/app_shim/app_shim_handler_mac.h" -#include "apps/app_shim/app_shim_host_mac.h" -#include "base/base64.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "base/path_service.h" -#include "base/sha1.h" -#include "base/strings/string_util.h" -#include "chrome/browser/browser_process.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/chrome_version_info.h" -#include "chrome/common/mac/app_mode_common.h" - -using content::BrowserThread; - -namespace { - -void CreateAppShimHost(const IPC::ChannelHandle& handle) { - // AppShimHost takes ownership of itself. - (new AppShimHost)->ServeChannel(handle); -} - -base::FilePath GetDirectoryInTmpTemplate(const base::FilePath& user_data_dir) { - base::FilePath temp_dir; - CHECK(PathService::Get(base::DIR_TEMP, &temp_dir)); - // Check that it's shorter than the IPC socket length (104) minus the - // intermediate folder ("/chrome-XXXXXX/") and kAppShimSocketShortName. - DCHECK_GT(83u, temp_dir.value().length()); - return temp_dir.Append("chrome-XXXXXX"); -} - -void DeleteSocketFiles(const base::FilePath& directory_in_tmp, - const base::FilePath& symlink_path, - const base::FilePath& version_path) { - // Delete in reverse order of creation. - if (!version_path.empty()) - base::DeleteFile(version_path, false); - if (!symlink_path.empty()) - base::DeleteFile(symlink_path, false); - if (!directory_in_tmp.empty()) - base::DeleteFile(directory_in_tmp, true); -} - -} // namespace - -AppShimHostManager::AppShimHostManager() - : did_init_(false) {} - -void AppShimHostManager::Init() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - DCHECK(!did_init_); - did_init_ = true; - apps::AppShimHandler::SetDefaultHandler(&extension_app_shim_handler_); - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, - base::Bind(&AppShimHostManager::InitOnFileThread, this)); -} - -AppShimHostManager::~AppShimHostManager() { - acceptor_.reset(); - if (!did_init_) - return; - - apps::AppShimHandler::SetDefaultHandler(NULL); - base::FilePath user_data_dir; - base::FilePath symlink_path; - base::FilePath version_path; - if (PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) { - symlink_path = user_data_dir.Append(app_mode::kAppShimSocketSymlinkName); - version_path = - user_data_dir.Append(app_mode::kRunningChromeVersionSymlinkName); - } - BrowserThread::PostTask( - BrowserThread::FILE, - FROM_HERE, - base::Bind( - &DeleteSocketFiles, directory_in_tmp_, symlink_path, version_path)); -} - -void AppShimHostManager::InitOnFileThread() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); - base::FilePath user_data_dir; - if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) - return; - - // The socket path must be shorter than 104 chars (IPC::kMaxSocketNameLength). - // To accommodate this, we use a short path in /tmp/ that is generated from a - // hash of the user data dir. - std::string directory_string = - GetDirectoryInTmpTemplate(user_data_dir).value(); - - // mkdtemp() replaces trailing X's randomly and creates the directory. - if (!mkdtemp(&directory_string[0])) { - PLOG(ERROR) << directory_string; - return; - } - - directory_in_tmp_ = base::FilePath(directory_string); - // Check that the directory was created with the correct permissions. - int dir_mode = 0; - if (!base::GetPosixFilePermissions(directory_in_tmp_, &dir_mode) || - dir_mode != base::FILE_PERMISSION_USER_MASK) { - NOTREACHED(); - return; - } - - // UnixDomainSocketAcceptor creates the socket immediately. - base::FilePath socket_path = - directory_in_tmp_.Append(app_mode::kAppShimSocketShortName); - acceptor_.reset(new apps::UnixDomainSocketAcceptor(socket_path, this)); - - // Create a symlink to the socket in the user data dir. This lets the shim - // process started from Finder find the actual socket path by following the - // symlink with ::readlink(). - base::FilePath symlink_path = - user_data_dir.Append(app_mode::kAppShimSocketSymlinkName); - base::DeleteFile(symlink_path, false); - base::CreateSymbolicLink(socket_path, symlink_path); - - // Create a symlink containing the current version string. This allows the - // shim to load the same framework version as the currently running Chrome - // process. - base::FilePath version_path = - user_data_dir.Append(app_mode::kRunningChromeVersionSymlinkName); - base::DeleteFile(version_path, false); - base::CreateSymbolicLink(base::FilePath(chrome::VersionInfo().Version()), - version_path); - - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&AppShimHostManager::ListenOnIOThread, this)); -} - -void AppShimHostManager::ListenOnIOThread() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - if (!acceptor_->Listen()) { - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&AppShimHostManager::OnListenError, this)); - } -} - -void AppShimHostManager::OnClientConnected( - const IPC::ChannelHandle& handle) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&CreateAppShimHost, handle)); -} - -void AppShimHostManager::OnListenError() { - // TODO(tapted): Set a timeout and attempt to reconstruct the channel. Until - // cases where the error could occur are better known, just reset the acceptor - // to allow failure to be communicated via the test API. - acceptor_.reset(); -} diff --git a/apps/app_shim/app_shim_interactive_uitest_mac.mm b/apps/app_shim/app_shim_interactive_uitest_mac.mm deleted file mode 100644 index 0519143..0000000 --- a/apps/app_shim/app_shim_interactive_uitest_mac.mm +++ /dev/null @@ -1,407 +0,0 @@ -// Copyright 2014 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. - -#import <Cocoa/Cocoa.h> -#include <vector> - -#include "apps/app_shim/app_shim_handler_mac.h" -#include "apps/app_shim/app_shim_host_manager_mac.h" -#include "apps/app_shim/extension_app_shim_handler_mac.h" -#include "apps/switches.h" -#include "base/auto_reset.h" -#include "base/callback.h" -#include "base/files/file_path_watcher.h" -#include "base/mac/foundation_util.h" -#include "base/mac/launch_services_util.h" -#include "base/mac/mac_util.h" -#include "base/mac/scoped_nsobject.h" -#include "base/path_service.h" -#include "base/process/launch.h" -#include "base/strings/sys_string_conversions.h" -#include "base/test/test_timeouts.h" -#include "chrome/browser/apps/app_browsertest_util.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/web_applications/web_app_mac.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/mac/app_mode_common.h" -#include "content/public/test/test_utils.h" -#include "extensions/browser/app_window/native_app_window.h" -#include "extensions/browser/extension_registry.h" -#include "extensions/test/extension_test_message_listener.h" -#import "ui/events/test/cocoa_test_event_utils.h" - -namespace { - -// General end-to-end test for app shims. -class AppShimInteractiveTest : public extensions::PlatformAppBrowserTest { - protected: - AppShimInteractiveTest() - : auto_reset_(&g_app_shims_allow_update_and_launch_in_tests, true) {} - - private: - // Temporarily enable app shims. - base::AutoReset<bool> auto_reset_; - - DISALLOW_COPY_AND_ASSIGN(AppShimInteractiveTest); -}; - -// Watches for changes to a file. This is designed to be used from the the UI -// thread. -class WindowedFilePathWatcher - : public base::RefCountedThreadSafe<WindowedFilePathWatcher> { - public: - WindowedFilePathWatcher(const base::FilePath& path) - : path_(path), observed_(false) { - content::BrowserThread::PostTask( - content::BrowserThread::FILE, - FROM_HERE, - base::Bind(&WindowedFilePathWatcher::Watch, this)); - } - - void Wait() { - if (observed_) - return; - - run_loop_.reset(new base::RunLoop); - run_loop_->Run(); - } - - protected: - friend class base::RefCountedThreadSafe<WindowedFilePathWatcher>; - virtual ~WindowedFilePathWatcher() {} - - void Watch() { - watcher_.reset(new base::FilePathWatcher); - watcher_->Watch(path_.DirName(), - false, - base::Bind(&WindowedFilePathWatcher::Observe, this)); - } - - void Observe(const base::FilePath& path, bool error) { - DCHECK(!error); - if (base::PathExists(path_)) { - watcher_.reset(); - content::BrowserThread::PostTask( - content::BrowserThread::UI, - FROM_HERE, - base::Bind(&WindowedFilePathWatcher::StopRunLoop, this)); - } - } - - void StopRunLoop() { - observed_ = true; - if (run_loop_.get()) - run_loop_->Quit(); - } - - private: - const base::FilePath path_; - scoped_ptr<base::FilePathWatcher> watcher_; - bool observed_; - scoped_ptr<base::RunLoop> run_loop_; - - DISALLOW_COPY_AND_ASSIGN(WindowedFilePathWatcher); -}; - -// Watches for an app shim to connect. -class WindowedAppShimLaunchObserver : public apps::AppShimHandler { - public: - WindowedAppShimLaunchObserver(const std::string& app_id) - : app_mode_id_(app_id), - observed_(false) { - apps::AppShimHandler::RegisterHandler(app_id, this); - } - - void Wait() { - if (observed_) - return; - - run_loop_.reset(new base::RunLoop); - run_loop_->Run(); - } - - // AppShimHandler overrides: - virtual void OnShimLaunch(Host* host, - apps::AppShimLaunchType launch_type, - const std::vector<base::FilePath>& files) OVERRIDE { - // Remove self and pass through to the default handler. - apps::AppShimHandler::RemoveHandler(app_mode_id_); - apps::AppShimHandler::GetForAppMode(app_mode_id_) - ->OnShimLaunch(host, launch_type, files); - observed_ = true; - if (run_loop_.get()) - run_loop_->Quit(); - } - virtual void OnShimClose(Host* host) OVERRIDE {} - virtual void OnShimFocus(Host* host, - apps::AppShimFocusType focus_type, - const std::vector<base::FilePath>& files) OVERRIDE {} - virtual void OnShimSetHidden(Host* host, bool hidden) OVERRIDE {} - virtual void OnShimQuit(Host* host) OVERRIDE {} - - private: - std::string app_mode_id_; - bool observed_; - scoped_ptr<base::RunLoop> run_loop_; - - DISALLOW_COPY_AND_ASSIGN(WindowedAppShimLaunchObserver); -}; - -NSString* GetBundleID(const base::FilePath& shim_path) { - base::FilePath plist_path = shim_path.Append("Contents").Append("Info.plist"); - NSMutableDictionary* plist = [NSMutableDictionary - dictionaryWithContentsOfFile:base::mac::FilePathToNSString(plist_path)]; - return [plist objectForKey:base::mac::CFToNSCast(kCFBundleIdentifierKey)]; -} - -bool HasAppShimHost(Profile* profile, const std::string& app_id) { - return g_browser_process->platform_part() - ->app_shim_host_manager() - ->extension_app_shim_handler() - ->FindHost(profile, app_id); -} - -} // namespace - -// Watches for NSNotifications from the shared workspace. -@interface WindowedNSNotificationObserver : NSObject { - @private - base::scoped_nsobject<NSString> bundleId_; - BOOL notificationReceived_; - scoped_ptr<base::RunLoop> runLoop_; -} - -- (id)initForNotification:(NSString*)name - andBundleId:(NSString*)bundleId; -- (void)observe:(NSNotification*)notification; -- (void)wait; -@end - -@implementation WindowedNSNotificationObserver - -- (id)initForNotification:(NSString*)name - andBundleId:(NSString*)bundleId { - if (self = [super init]) { - bundleId_.reset([[bundleId copy] retain]); - [[[NSWorkspace sharedWorkspace] notificationCenter] - addObserver:self - selector:@selector(observe:) - name:name - object:nil]; - } - return self; -} - -- (void)observe:(NSNotification*)notification { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - NSRunningApplication* application = - [[notification userInfo] objectForKey:NSWorkspaceApplicationKey]; - if (![[application bundleIdentifier] isEqualToString:bundleId_]) - return; - - [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self]; - notificationReceived_ = YES; - if (runLoop_.get()) - runLoop_->Quit(); -} - -- (void)wait { - if (notificationReceived_) - return; - - runLoop_.reset(new base::RunLoop); - runLoop_->Run(); -} - -@end - -namespace apps { - -// Shims require static libraries http://crbug.com/386024. -#if defined(COMPONENT_BUILD) -#define MAYBE_Launch DISABLED_Launch -#define MAYBE_RebuildShim DISABLED_RebuildShim -#else -#define MAYBE_Launch Launch -#define MAYBE_RebuildShim RebuildShim -#endif - -// Test that launching the shim for an app starts the app, and vice versa. -// These two cases are combined because the time to run the test is dominated -// by loading the extension and creating the shim. -IN_PROC_BROWSER_TEST_F(AppShimInteractiveTest, MAYBE_Launch) { - // Install the app. - const extensions::Extension* app = InstallPlatformApp("minimal"); - - // Use a WebAppShortcutCreator to get the path. - web_app::WebAppShortcutCreator shortcut_creator( - web_app::GetWebAppDataDirectory(profile()->GetPath(), app->id(), GURL()), - web_app::ShortcutInfoForExtensionAndProfile(app, profile()), - extensions::FileHandlersInfo()); - base::FilePath shim_path = shortcut_creator.GetInternalShortcutPath(); - EXPECT_FALSE(base::PathExists(shim_path)); - - // Create the internal app shim by simulating an app update. FilePathWatcher - // is used to wait for file operations on the shim to be finished before - // attempting to launch it. Since all of the file operations are done in the - // same event on the FILE thread, everything will be done by the time the - // watcher's callback is executed. - scoped_refptr<WindowedFilePathWatcher> file_watcher = - new WindowedFilePathWatcher(shim_path); - web_app::UpdateAllShortcuts(base::string16(), profile(), app); - file_watcher->Wait(); - ASSERT_TRUE(base::PathExists(shim_path)); - NSString* bundle_id = GetBundleID(shim_path); - - // Case 1: Launch the app, it should start the shim. - { - base::scoped_nsobject<WindowedNSNotificationObserver> ns_observer; - ns_observer.reset([[WindowedNSNotificationObserver alloc] - initForNotification:NSWorkspaceDidLaunchApplicationNotification - andBundleId:bundle_id]); - WindowedAppShimLaunchObserver observer(app->id()); - LaunchPlatformApp(app); - [ns_observer wait]; - observer.Wait(); - - EXPECT_TRUE(GetFirstAppWindow()); - EXPECT_TRUE(HasAppShimHost(profile(), app->id())); - - // Quitting the shim will eventually cause it to quit. It actually - // intercepts the -terminate, sends an AppShimHostMsg_QuitApp to Chrome, - // and returns NSTerminateLater. Chrome responds by closing all windows of - // the app. Once all windows are closed, Chrome closes the IPC channel, - // which causes the shim to actually terminate. - NSArray* running_shim = [NSRunningApplication - runningApplicationsWithBundleIdentifier:bundle_id]; - ASSERT_EQ(1u, [running_shim count]); - - ns_observer.reset([[WindowedNSNotificationObserver alloc] - initForNotification:NSWorkspaceDidTerminateApplicationNotification - andBundleId:bundle_id]); - [base::mac::ObjCCastStrict<NSRunningApplication>( - [running_shim objectAtIndex:0]) terminate]; - [ns_observer wait]; - - EXPECT_FALSE(GetFirstAppWindow()); - EXPECT_FALSE(HasAppShimHost(profile(), app->id())); - } - - // Case 2: Launch the shim, it should start the app. - { - ExtensionTestMessageListener launched_listener("Launched", false); - CommandLine shim_cmdline(CommandLine::NO_PROGRAM); - shim_cmdline.AppendSwitch(app_mode::kLaunchedForTest); - ProcessSerialNumber shim_psn; - ASSERT_TRUE(base::mac::OpenApplicationWithPath( - shim_path, shim_cmdline, kLSLaunchDefaults, &shim_psn)); - ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); - - ASSERT_TRUE(GetFirstAppWindow()); - EXPECT_TRUE(HasAppShimHost(profile(), app->id())); - - // If the window is closed, the shim should quit. - pid_t shim_pid; - EXPECT_EQ(noErr, GetProcessPID(&shim_psn, &shim_pid)); - GetFirstAppWindow()->GetBaseWindow()->Close(); - ASSERT_TRUE( - base::WaitForSingleProcess(shim_pid, TestTimeouts::action_timeout())); - - EXPECT_FALSE(GetFirstAppWindow()); - EXPECT_FALSE(HasAppShimHost(profile(), app->id())); - } -} - -#if defined(ARCH_CPU_64_BITS) - -// Tests that a 32 bit shim attempting to launch 64 bit Chrome will eventually -// be rebuilt. -IN_PROC_BROWSER_TEST_F(AppShimInteractiveTest, MAYBE_RebuildShim) { - // Get the 32 bit shim. - base::FilePath test_data_dir; - PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir); - base::FilePath shim_path_32 = - test_data_dir.Append("app_shim").Append("app_shim_32_bit.app"); - EXPECT_TRUE(base::PathExists(shim_path_32)); - - // Install test app. - const extensions::Extension* app = InstallPlatformApp("minimal"); - - // Use WebAppShortcutCreator to create a 64 bit shim. - web_app::WebAppShortcutCreator shortcut_creator( - web_app::GetWebAppDataDirectory(profile()->GetPath(), app->id(), GURL()), - web_app::ShortcutInfoForExtensionAndProfile(app, profile()), - extensions::FileHandlersInfo()); - shortcut_creator.UpdateShortcuts(); - base::FilePath shim_path = shortcut_creator.GetInternalShortcutPath(); - NSMutableDictionary* plist_64 = [NSMutableDictionary - dictionaryWithContentsOfFile:base::mac::FilePathToNSString( - shim_path.Append("Contents").Append("Info.plist"))]; - - // Copy 32 bit shim to where it's expected to be. - // CopyDirectory doesn't seem to work when copying and renaming in one go. - ASSERT_TRUE(base::DeleteFile(shim_path, true)); - ASSERT_TRUE(base::PathExists(shim_path.DirName())); - ASSERT_TRUE(base::CopyDirectory(shim_path_32, shim_path.DirName(), true)); - ASSERT_TRUE(base::Move(shim_path.DirName().Append(shim_path_32.BaseName()), - shim_path)); - ASSERT_TRUE(base::PathExists( - shim_path.Append("Contents").Append("MacOS").Append("app_mode_loader"))); - - // Fix up the plist so that it matches the installed test app. - NSString* plist_path = base::mac::FilePathToNSString( - shim_path.Append("Contents").Append("Info.plist")); - NSMutableDictionary* plist = - [NSMutableDictionary dictionaryWithContentsOfFile:plist_path]; - - NSArray* keys_to_copy = @[ - base::mac::CFToNSCast(kCFBundleIdentifierKey), - base::mac::CFToNSCast(kCFBundleNameKey), - app_mode::kCrAppModeShortcutIDKey, - app_mode::kCrAppModeUserDataDirKey, - app_mode::kBrowserBundleIDKey - ]; - for (NSString* key in keys_to_copy) { - [plist setObject:[plist_64 objectForKey:key] - forKey:key]; - } - [plist writeToFile:plist_path - atomically:YES]; - - base::mac::RemoveQuarantineAttribute(shim_path); - - // Launch the shim, it should start the app and ultimately connect over IPC. - // This actually happens in multiple launches of the shim: - // (1) The shim will fail and instead launch Chrome with --app-id so that the - // app starts. - // (2) Chrome launches the shim in response to an app starting, this time the - // shim launches Chrome with --app-shim-error, which causes Chrome to - // rebuild the shim. - // (3) After rebuilding, Chrome again launches the shim and expects it to - // behave normally. - ExtensionTestMessageListener launched_listener("Launched", false); - CommandLine shim_cmdline(CommandLine::NO_PROGRAM); - ASSERT_TRUE(base::mac::OpenApplicationWithPath( - shim_path, shim_cmdline, kLSLaunchDefaults, NULL)); - - // Wait for the app to start (1). At this point there is no shim host. - ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); - EXPECT_FALSE(HasAppShimHost(profile(), app->id())); - - // Wait for the rebuilt shim to connect (3). This does not race with the app - // starting (1) because Chrome only launches the shim (2) after the app - // starts. Then Chrome must handle --app-shim-error on the UI thread before - // the shim is rebuilt. - WindowedAppShimLaunchObserver(app->id()).Wait(); - - EXPECT_TRUE(GetFirstAppWindow()); - EXPECT_TRUE(HasAppShimHost(profile(), app->id())); -} - -#endif // defined(ARCH_CPU_64_BITS) - -} // namespace apps diff --git a/apps/app_shim/app_shim_launch.h b/apps/app_shim/app_shim_launch.h deleted file mode 100644 index 61f87da..0000000 --- a/apps/app_shim/app_shim_launch.h +++ /dev/null @@ -1,57 +0,0 @@ -// 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, - // Counter and end marker. - APP_SHIM_LAUNCH_NUM_TYPES -}; - -enum AppShimLaunchResult { - // App launched successfully. - APP_SHIM_LAUNCH_SUCCESS = 0, - // There is already a host registered for this app. - APP_SHIM_LAUNCH_DUPLICATE_HOST, - // The profile was not found. - APP_SHIM_LAUNCH_PROFILE_NOT_FOUND, - // The app was not found. - APP_SHIM_LAUNCH_APP_NOT_FOUND, - // Counter and end marker. - APP_SHIM_LAUNCH_NUM_RESULTS -}; - -enum AppShimFocusType { - // Just focus the app. - APP_SHIM_FOCUS_NORMAL = 0, - // Focus the app or launch it if it has no windows open. - APP_SHIM_FOCUS_REOPEN, - // Open the given file in the app. - APP_SHIM_FOCUS_OPEN_FILES, - // Counter and end marker. - APP_SHIM_FOCUS_NUM_TYPES -}; - -enum AppShimAttentionType { - // Removes any active attention request. - APP_SHIM_ATTENTION_CANCEL = 0, - // Bounces the shim in the dock briefly. - APP_SHIM_ATTENTION_INFORMATIONAL, - // Bounces the shim in the dock continuously. - APP_SHIM_ATTENTION_CRITICAL, - // Counter and end marker. - APP_SHIM_ATTENTION_NUM_TYPES -}; - -} // 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 deleted file mode 100644 index 4fcbbd8..0000000 --- a/apps/app_shim/app_shim_messages.h +++ /dev/null @@ -1,71 +0,0 @@ -// 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. - -// Multiply-included message file, hence no include guard. - -#include <string> -#include <vector> - -#include "apps/app_shim/app_shim_launch.h" -#include "base/files/file_path.h" -#include "ipc/ipc_message_macros.h" -#include "ipc/ipc_message_utils.h" -#include "ipc/param_traits_macros.h" - -#define IPC_MESSAGE_START AppShimMsgStart - -IPC_ENUM_TRAITS_MAX_VALUE(apps::AppShimLaunchType, - apps::APP_SHIM_LAUNCH_NUM_TYPES - 1) -IPC_ENUM_TRAITS_MAX_VALUE(apps::AppShimLaunchResult, - apps::APP_SHIM_LAUNCH_NUM_RESULTS - 1) -IPC_ENUM_TRAITS_MAX_VALUE(apps::AppShimFocusType, - apps::APP_SHIM_FOCUS_NUM_TYPES - 1) -IPC_ENUM_TRAITS_MAX_VALUE(apps::AppShimAttentionType, - apps::APP_SHIM_ATTENTION_NUM_TYPES - 1) - -// IMPORTANT: Since app shims could be running a newer framework version to the -// currently running Chrome, any changes to these IPCs must maintain the same -// order and format. I.e. Only add to the bottom, don't delete any. - -// Signals that a previous LaunchApp message has been processed, and lets the -// app shim process know whether it was registered successfully. -IPC_MESSAGE_CONTROL1(AppShimMsg_LaunchApp_Done, - apps::AppShimLaunchResult /* launch result */) - -// Instructs the shim to hide the app. -IPC_MESSAGE_CONTROL0(AppShimMsg_Hide) - -// Deprecated. Do not delete. -IPC_MESSAGE_CONTROL0(AppShimMsg_RequestUserAttention) - -// Signals to the main Chrome process that a shim has started. Indicates the -// profile and app_id that the shim should be associated with and whether to -// launch the app immediately. -IPC_MESSAGE_CONTROL4(AppShimHostMsg_LaunchApp, - base::FilePath /* profile dir */, - std::string /* app id */, - apps::AppShimLaunchType /* launch type */, - std::vector<base::FilePath> /* files */) - -// 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 -// response, Chrome brings the app's windows to the foreground, or relaunches -// if the focus type indicates a reopen and there are no open windows. -IPC_MESSAGE_CONTROL2(AppShimHostMsg_FocusApp, - apps::AppShimFocusType /* focus type */, - std::vector<base::FilePath> /* files */) - -// Sent when the app shim is hidden or unhidden. -IPC_MESSAGE_CONTROL1(AppShimHostMsg_SetAppHidden, - bool /* hidden */) - -// 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) - -// Instructs the shim to request or cancel user attention. -IPC_MESSAGE_CONTROL1(AppShimMsg_SetUserAttention, - apps::AppShimAttentionType /* attention_type */) diff --git a/apps/app_shim/app_shim_quit_interactive_uitest_mac.mm b/apps/app_shim/app_shim_quit_interactive_uitest_mac.mm deleted file mode 100644 index 04fdbdb..0000000 --- a/apps/app_shim/app_shim_quit_interactive_uitest_mac.mm +++ /dev/null @@ -1,132 +0,0 @@ -// 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. - -// Tests behavior when quitting apps with app shims. - -#import <Cocoa/Cocoa.h> -#include <vector> - -#include "apps/app_shim/app_shim_host_manager_mac.h" -#include "apps/app_shim/extension_app_shim_handler_mac.h" -#include "apps/switches.h" -#include "chrome/browser/apps/app_browsertest_util.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/browser_shutdown.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/test/base/interactive_test_utils.h" -#include "content/public/test/test_utils.h" -#include "extensions/browser/extension_registry.h" -#include "extensions/test/extension_test_message_listener.h" -#include "ui/events/test/cocoa_test_event_utils.h" - -using extensions::PlatformAppBrowserTest; - -namespace apps { - -namespace { - -class FakeHost : public apps::AppShimHandler::Host { - public: - FakeHost(const base::FilePath& profile_path, - const std::string& app_id, - ExtensionAppShimHandler* handler) - : profile_path_(profile_path), - app_id_(app_id), - handler_(handler) {} - - virtual void OnAppLaunchComplete(AppShimLaunchResult result) OVERRIDE {} - virtual void OnAppClosed() OVERRIDE { - handler_->OnShimClose(this); - } - virtual void OnAppHide() OVERRIDE {} - virtual void OnAppRequestUserAttention(AppShimAttentionType type) OVERRIDE {} - virtual base::FilePath GetProfilePath() const OVERRIDE { - return profile_path_; - } - virtual std::string GetAppId() const OVERRIDE { return app_id_; } - - private: - base::FilePath profile_path_; - std::string app_id_; - ExtensionAppShimHandler* handler_; - - DISALLOW_COPY_AND_ASSIGN(FakeHost); -}; - -// Starts an app without a browser window using --load_and_launch_app and -// --silent_launch. -class AppShimQuitTest : public PlatformAppBrowserTest { - protected: - AppShimQuitTest() {} - - void SetUpAppShim() { - ASSERT_EQ(0u, [[NSApp windows] count]); - ExtensionTestMessageListener launched_listener("Launched", false); - ASSERT_TRUE(launched_listener.WaitUntilSatisfied()); - ASSERT_EQ(1u, [[NSApp windows] count]); - - handler_ = g_browser_process->platform_part()->app_shim_host_manager()-> - extension_app_shim_handler(); - - // Attach a host for the app. - extensions::ExtensionRegistry* registry = - extensions::ExtensionRegistry::Get(profile()); - extension_id_ = - GetExtensionByPath(®istry->enabled_extensions(), app_path_)->id(); - host_.reset(new FakeHost(profile()->GetPath().BaseName(), - extension_id_, - handler_)); - handler_->OnShimLaunch(host_.get(), - APP_SHIM_LAUNCH_REGISTER_ONLY, - std::vector<base::FilePath>()); - EXPECT_EQ(host_.get(), handler_->FindHost(profile(), extension_id_)); - - // Focus the app window. - NSWindow* window = [[NSApp windows] objectAtIndex:0]; - EXPECT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(window)); - content::RunAllPendingInMessageLoop(); - } - - virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { - PlatformAppBrowserTest::SetUpCommandLine(command_line); - // Simulate an app shim initiated launch, i.e. launch app but not browser. - app_path_ = test_data_dir_ - .AppendASCII("platform_apps") - .AppendASCII("minimal"); - command_line->AppendSwitchNative(apps::kLoadAndLaunchApp, - app_path_.value()); - command_line->AppendSwitch(switches::kSilentLaunch); - } - - base::FilePath app_path_; - ExtensionAppShimHandler* handler_; - std::string extension_id_; - scoped_ptr<FakeHost> host_; - - DISALLOW_COPY_AND_ASSIGN(AppShimQuitTest); -}; - -} // namespace - -// Test that closing an app with Cmd+Q when no browsers have ever been open -// terminates Chrome. -IN_PROC_BROWSER_TEST_F(AppShimQuitTest, QuitWithKeyEvent) { - SetUpAppShim(); - - // Simulate a Cmd+Q event. - NSWindow* window = [[NSApp windows] objectAtIndex:0]; - NSEvent* event = cocoa_test_event_utils::KeyEventWithKeyCode( - 0, 'q', NSKeyDown, NSCommandKeyMask); - [window postEvent:event - atStart:NO]; - - // This will time out if the event above does not terminate Chrome. - content::RunMessageLoop(); - - EXPECT_FALSE(handler_->FindHost(profile(), extension_id_)); - EXPECT_TRUE(browser_shutdown::IsTryingToQuit()); -} - -} // namespace apps diff --git a/apps/app_shim/chrome_main_app_mode_mac.mm b/apps/app_shim/chrome_main_app_mode_mac.mm deleted file mode 100644 index 21e3fe2..0000000 --- a/apps/app_shim/chrome_main_app_mode_mac.mm +++ /dev/null @@ -1,693 +0,0 @@ -// 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. - -// On Mac, one can't make shortcuts with command-line arguments. Instead, we -// produce small app bundles which locate the Chromium framework and load it, -// passing the appropriate data. This is the entry point into the framework for -// those app bundles. - -#import <Cocoa/Cocoa.h> -#include <vector> - -#include "apps/app_shim/app_shim_messages.h" -#include "base/at_exit.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/logging.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_nsautorelease_pool.h" -#include "base/mac/scoped_nsobject.h" -#include "base/mac/sdk_forward_declarations.h" -#include "base/message_loop/message_loop.h" -#include "base/path_service.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/sys_string_conversions.h" -#include "base/threading/thread.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/mac/app_mode_common.h" -#include "grit/generated_resources.h" -#include "ipc/ipc_channel_proxy.h" -#include "ipc/ipc_listener.h" -#include "ipc/ipc_message.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" - -namespace { - -// Timeout in seconds to wait for a reply for the initial Apple Event. Note that -// kAEDefaultTimeout on Mac is "about one minute" according to Apple's -// documentation, but is no longer supported for asynchronous Apple Events. -const int kPingChromeTimeoutSeconds = 60; - -const app_mode::ChromeAppModeInfo* g_info; -base::Thread* g_io_thread = NULL; - -} // namespace - -class AppShimController; - -// An application delegate to catch user interactions and send the appropriate -// IPC messages to Chrome. -@interface AppShimDelegate : NSObject<NSApplicationDelegate> { - @private - AppShimController* appShimController_; // Weak, initially NULL. - BOOL terminateNow_; - BOOL terminateRequested_; - std::vector<base::FilePath> filesToOpenAtStartup_; -} - -// The controller is initially NULL. Setting it indicates to the delegate that -// the controller has finished initialization. -- (void)setController:(AppShimController*)controller; - -// Gets files that were queued because the controller was not ready. -// Returns whether any FilePaths were added to |out|. -- (BOOL)getFilesToOpenAtStartup:(std::vector<base::FilePath>*)out; - -// If the controller is ready, this sends a FocusApp with the files to open. -// Otherwise, this adds the files to |filesToOpenAtStartup_|. -// Takes an array of NSString*. -- (void)openFiles:(NSArray*)filename; - -// Terminate immediately. This is necessary as we override terminate: to send -// a QuitApp message. -- (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 { - public: - AppShimController(); - virtual ~AppShimController(); - - // Called when the main Chrome process responds to the Apple Event ping that - // was sent, or when the ping fails (if |success| is false). - void OnPingChromeReply(bool success); - - // Called |kPingChromeTimeoutSeconds| after startup, to allow a timeout on the - // ping event to be detected. - void OnPingChromeTimeout(); - - // Connects to Chrome and sends a LaunchApp message. - void Init(); - - // Create a channel from |socket_path| and send a LaunchApp message. - void CreateChannelAndSendLaunchApp(const base::FilePath& socket_path); - - // Builds main menu bar items. - void SetUpMenu(); - - void SendSetAppHidden(bool hidden); - - void SendQuitApp(); - - // Called when the app is activated, e.g. by clicking on it in the dock, by - // dropping a file on the dock icon, or by Cmd+Tabbing to it. - // Returns whether the message was sent. - bool SendFocusApp(apps::AppShimFocusType focus_type, - const std::vector<base::FilePath>& files); - - private: - // IPC::Listener implemetation. - virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; - virtual void OnChannelError() OVERRIDE; - - // If Chrome failed to launch the app, |success| will be false and the app - // shim process should die. - void OnLaunchAppDone(apps::AppShimLaunchResult result); - - // Hide this app. - void OnHide(); - - // Requests user attention. - void OnRequestUserAttention(); - void OnSetUserAttention(apps::AppShimAttentionType attention_type); - - // Terminates the app shim process. - void Close(); - - base::FilePath user_data_dir_; - scoped_ptr<IPC::ChannelProxy> channel_; - base::scoped_nsobject<AppShimDelegate> delegate_; - bool launch_app_done_; - bool ping_chrome_reply_received_; - NSInteger attention_request_id_; - - DISALLOW_COPY_AND_ASSIGN(AppShimController); -}; - -AppShimController::AppShimController() - : delegate_([[AppShimDelegate alloc] init]), - launch_app_done_(false), - ping_chrome_reply_received_(false), - attention_request_id_(0) { - // Since AppShimController is created before the main message loop starts, - // NSApp will not be set, so use sharedApplication. - [[NSApplication sharedApplication] setDelegate:delegate_]; -} - -AppShimController::~AppShimController() { - // Un-set the delegate since NSApplication does not retain it. - [[NSApplication sharedApplication] setDelegate:nil]; -} - -void AppShimController::OnPingChromeReply(bool success) { - ping_chrome_reply_received_ = true; - if (!success) { - [NSApp terminate:nil]; - return; - } - - Init(); -} - -void AppShimController::OnPingChromeTimeout() { - if (!ping_chrome_reply_received_) - [NSApp terminate:nil]; -} - -void AppShimController::Init() { - DCHECK(g_io_thread); - - SetUpMenu(); - - // Chrome will relaunch shims when relaunching apps. - if (base::mac::IsOSLionOrLater()) - [NSApp disableRelaunchOnLogin]; - - // The user_data_dir for shims actually contains the app_data_path. - // I.e. <user_data_dir>/<profile_dir>/Web Applications/_crx_extensionid/ - user_data_dir_ = g_info->user_data_dir.DirName().DirName().DirName(); - CHECK(!user_data_dir_.empty()); - - base::FilePath symlink_path = - user_data_dir_.Append(app_mode::kAppShimSocketSymlinkName); - - base::FilePath socket_path; - if (!base::ReadSymbolicLink(symlink_path, &socket_path)) { - // The path in the user data dir is not a symlink, try connecting directly. - CreateChannelAndSendLaunchApp(symlink_path); - return; - } - - app_mode::VerifySocketPermissions(socket_path); - - CreateChannelAndSendLaunchApp(socket_path); -} - -void AppShimController::CreateChannelAndSendLaunchApp( - const base::FilePath& socket_path) { - IPC::ChannelHandle handle(socket_path.value()); - channel_ = IPC::ChannelProxy::Create(handle, - IPC::Channel::MODE_NAMED_CLIENT, - this, - g_io_thread->message_loop_proxy().get()); - - bool launched_by_chrome = - CommandLine::ForCurrentProcess()->HasSwitch( - app_mode::kLaunchedByChromeProcessId); - apps::AppShimLaunchType launch_type = launched_by_chrome ? - apps::APP_SHIM_LAUNCH_REGISTER_ONLY : apps::APP_SHIM_LAUNCH_NORMAL; - - [delegate_ setController:this]; - - std::vector<base::FilePath> files; - [delegate_ getFilesToOpenAtStartup:&files]; - - channel_->Send(new AppShimHostMsg_LaunchApp( - g_info->profile_dir, g_info->app_mode_id, launch_type, files)); -} - -void AppShimController::SetUpMenu() { - NSString* title = base::SysUTF16ToNSString(g_info->app_mode_name); - - // Create a main menu since [NSApp mainMenu] is nil. - base::scoped_nsobject<NSMenu> main_menu([[NSMenu alloc] initWithTitle:title]); - - // The title of the first item is replaced by OSX with the name of the app and - // bold styling. Create a dummy item for this and make it hidden. - NSMenuItem* dummy_item = [main_menu addItemWithTitle:title - action:nil - keyEquivalent:@""]; - base::scoped_nsobject<NSMenu> dummy_submenu( - [[NSMenu alloc] initWithTitle:title]); - [dummy_item setSubmenu:dummy_submenu]; - [dummy_item setHidden:YES]; - - // Construct an unbolded app menu, to match how it appears in the Chrome menu - // bar when the app is focused. - NSMenuItem* item = [main_menu addItemWithTitle:title - action:nil - keyEquivalent:@""]; - base::scoped_nsobject<NSMenu> submenu([[NSMenu alloc] initWithTitle:title]); - [item setSubmenu:submenu]; - - // Add a quit entry. - NSString* quit_localized_string = - l10n_util::GetNSStringF(IDS_EXIT_MAC, g_info->app_mode_name); - [submenu addItemWithTitle:quit_localized_string - action:@selector(terminate:) - keyEquivalent:@"q"]; - - // Add File, Edit, and Window menus. These are just here to make the - // transition smoother, i.e. from another application to the shim then to - // Chrome. - [main_menu addItemWithTitle:l10n_util::GetNSString(IDS_FILE_MENU_MAC) - action:nil - keyEquivalent:@""]; - [main_menu addItemWithTitle:l10n_util::GetNSString(IDS_EDIT_MENU_MAC) - action:nil - keyEquivalent:@""]; - [main_menu addItemWithTitle:l10n_util::GetNSString(IDS_WINDOW_MENU_MAC) - action:nil - keyEquivalent:@""]; - - [NSApp setMainMenu:main_menu]; -} - -void AppShimController::SendQuitApp() { - channel_->Send(new AppShimHostMsg_QuitApp); -} - -bool AppShimController::OnMessageReceived(const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(AppShimController, message) - IPC_MESSAGE_HANDLER(AppShimMsg_LaunchApp_Done, OnLaunchAppDone) - IPC_MESSAGE_HANDLER(AppShimMsg_Hide, OnHide) - IPC_MESSAGE_HANDLER(AppShimMsg_RequestUserAttention, OnRequestUserAttention) - IPC_MESSAGE_HANDLER(AppShimMsg_SetUserAttention, OnSetUserAttention) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - - return handled; -} - -void AppShimController::OnChannelError() { - Close(); -} - -void AppShimController::OnLaunchAppDone(apps::AppShimLaunchResult result) { - if (result != apps::APP_SHIM_LAUNCH_SUCCESS) { - Close(); - return; - } - - std::vector<base::FilePath> files; - if ([delegate_ getFilesToOpenAtStartup:&files]) - SendFocusApp(apps::APP_SHIM_FOCUS_OPEN_FILES, files); - - launch_app_done_ = true; -} - -void AppShimController::OnHide() { - [NSApp hide:nil]; -} - -void AppShimController::OnRequestUserAttention() { - OnSetUserAttention(apps::APP_SHIM_ATTENTION_INFORMATIONAL); -} - -void AppShimController::OnSetUserAttention( - apps::AppShimAttentionType attention_type) { - switch (attention_type) { - case apps::APP_SHIM_ATTENTION_CANCEL: - [NSApp cancelUserAttentionRequest:attention_request_id_]; - attention_request_id_ = 0; - break; - case apps::APP_SHIM_ATTENTION_CRITICAL: - attention_request_id_ = [NSApp requestUserAttention:NSCriticalRequest]; - break; - case apps::APP_SHIM_ATTENTION_INFORMATIONAL: - attention_request_id_ = - [NSApp requestUserAttention:NSInformationalRequest]; - break; - case apps::APP_SHIM_ATTENTION_NUM_TYPES: - NOTREACHED(); - } -} - -void AppShimController::Close() { - [delegate_ terminateNow]; -} - -bool AppShimController::SendFocusApp(apps::AppShimFocusType focus_type, - const std::vector<base::FilePath>& files) { - if (launch_app_done_) { - channel_->Send(new AppShimHostMsg_FocusApp(focus_type, files)); - return true; - } - - return false; -} - -void AppShimController::SendSetAppHidden(bool hidden) { - channel_->Send(new AppShimHostMsg_SetAppHidden(hidden)); -} - -@implementation AppShimDelegate - -- (BOOL)getFilesToOpenAtStartup:(std::vector<base::FilePath>*)out { - if (filesToOpenAtStartup_.empty()) - return NO; - - out->insert(out->end(), - filesToOpenAtStartup_.begin(), - filesToOpenAtStartup_.end()); - filesToOpenAtStartup_.clear(); - return YES; -} - -- (void)setController:(AppShimController*)controller { - appShimController_ = controller; -} - -- (void)openFiles:(NSArray*)filenames { - std::vector<base::FilePath> filePaths; - for (NSString* filename in filenames) - filePaths.push_back(base::mac::NSStringToFilePath(filename)); - - // If the AppShimController is ready, try to send a FocusApp. If that fails, - // (e.g. if launching has not finished), enqueue the files. - if (appShimController_ && - appShimController_->SendFocusApp(apps::APP_SHIM_FOCUS_OPEN_FILES, - filePaths)) { - return; - } - - filesToOpenAtStartup_.insert(filesToOpenAtStartup_.end(), - filePaths.begin(), - filePaths.end()); -} - -- (BOOL)application:(NSApplication*)app - openFile:(NSString*)filename { - [self openFiles:@[filename]]; - return YES; -} - -- (void)application:(NSApplication*)app - openFiles:(NSArray*)filenames { - [self openFiles:filenames]; - [app replyToOpenOrPrint:NSApplicationDelegateReplySuccess]; -} - -- (BOOL)applicationOpenUntitledFile:(NSApplication*)app { - if (appShimController_) { - return appShimController_->SendFocusApp(apps::APP_SHIM_FOCUS_REOPEN, - std::vector<base::FilePath>()); - } - - return NO; -} - -- (void)applicationWillBecomeActive:(NSNotification*)notification { - if (appShimController_) { - appShimController_->SendFocusApp(apps::APP_SHIM_FOCUS_NORMAL, - std::vector<base::FilePath>()); - } -} - -- (NSApplicationTerminateReply) - applicationShouldTerminate:(NSApplication*)sender { - if (terminateNow_ || !appShimController_) - return NSTerminateNow; - - appShimController_->SendQuitApp(); - // Wait for the channel to close before terminating. - terminateRequested_ = YES; - return NSTerminateLater; -} - -- (void)applicationWillHide:(NSNotification*)notification { - if (appShimController_) - appShimController_->SendSetAppHidden(true); -} - -- (void)applicationWillUnhide:(NSNotification*)notification { - if (appShimController_) - appShimController_->SendSetAppHidden(false); -} - -- (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 -// and call a callback when the reply returns. -// -// This is used to 'ping' the main Chrome process -- once Chrome has sent back -// an Apple Event reply, it's guaranteed that it has opened the IPC channel -// that the app shim will connect to. -@interface ReplyEventHandler : NSObject { - base::Callback<void(bool)> onReply_; - AEDesc replyEvent_; -} -// Sends an Apple Event to the process identified by |psn|, and calls |replyFn| -// when the reply is received. Internally this creates a ReplyEventHandler, -// which will delete itself once the reply event has been received. -+ (void)pingProcess:(const ProcessSerialNumber&)psn - andCall:(base::Callback<void(bool)>)replyFn; -@end - -@interface ReplyEventHandler (PrivateMethods) -// Initialise the reply event handler. Doesn't register any handlers until -// |-pingProcess:| is called. |replyFn| is the function to be called when the -// Apple Event reply arrives. -- (id)initWithCallback:(base::Callback<void(bool)>)replyFn; - -// Sends an Apple Event ping to the process identified by |psn| and registers -// to listen for a reply. -- (void)pingProcess:(const ProcessSerialNumber&)psn; - -// Called when a response is received from the target process for the ping sent -// by |-pingProcess:|. -- (void)message:(NSAppleEventDescriptor*)event - withReply:(NSAppleEventDescriptor*)reply; - -// Calls |onReply_|, passing it |success| to specify whether the ping was -// successful. -- (void)closeWithSuccess:(bool)success; -@end - -@implementation ReplyEventHandler -+ (void)pingProcess:(const ProcessSerialNumber&)psn - andCall:(base::Callback<void(bool)>)replyFn { - // The object will release itself when the reply arrives, or possibly earlier - // if an unrecoverable error occurs. - ReplyEventHandler* handler = - [[ReplyEventHandler alloc] initWithCallback:replyFn]; - [handler pingProcess:psn]; -} -@end - -@implementation ReplyEventHandler (PrivateMethods) -- (id)initWithCallback:(base::Callback<void(bool)>)replyFn { - if ((self = [super init])) { - onReply_ = replyFn; - } - return self; -} - -- (void)pingProcess:(const ProcessSerialNumber&)psn { - // Register the reply listener. - NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; - [em setEventHandler:self - andSelector:@selector(message:withReply:) - forEventClass:'aevt' - andEventID:'ansr']; - // Craft the Apple Event to send. - NSAppleEventDescriptor* target = [NSAppleEventDescriptor - descriptorWithDescriptorType:typeProcessSerialNumber - bytes:&psn - length:sizeof(psn)]; - NSAppleEventDescriptor* initial_event = - [NSAppleEventDescriptor - appleEventWithEventClass:app_mode::kAEChromeAppClass - eventID:app_mode::kAEChromeAppPing - targetDescriptor:target - returnID:kAutoGenerateReturnID - transactionID:kAnyTransactionID]; - - // Note that AESendMessage effectively ignores kAEDefaultTimeout, because this - // call does not pass kAEWantReceipt (which is deprecated and unsupported on - // Mac). Instead, rely on OnPingChromeTimeout(). - OSStatus status = AESendMessage( - [initial_event aeDesc], &replyEvent_, kAEQueueReply, kAEDefaultTimeout); - if (status != noErr) { - OSSTATUS_LOG(ERROR, status) << "AESendMessage"; - [self closeWithSuccess:false]; - } -} - -- (void)message:(NSAppleEventDescriptor*)event - withReply:(NSAppleEventDescriptor*)reply { - [self closeWithSuccess:true]; -} - -- (void)closeWithSuccess:(bool)success { - onReply_.Run(success); - NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; - [em removeEventHandlerForEventClass:'aevt' andEventID:'ansr']; - [self release]; -} -@end - -//----------------------------------------------------------------------------- - -extern "C" { - -// |ChromeAppModeStart()| is the point of entry into the framework from the app -// mode loader. -__attribute__((visibility("default"))) -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(); - - if (info->major_version < app_mode::kCurrentChromeAppModeInfoMajorVersion) { - RAW_LOG(ERROR, "App Mode Loader too old."); - return 1; - } - if (info->major_version > app_mode::kCurrentChromeAppModeInfoMajorVersion) { - RAW_LOG(ERROR, "Browser Framework too old to load App Shortcut."); - return 1; - } - - g_info = info; - - // Set bundle paths. This loads the bundles. - base::mac::SetOverrideOuterBundlePath(g_info->chrome_outer_bundle_path); - base::mac::SetOverrideFrameworkBundlePath( - g_info->chrome_versioned_path.Append(chrome::kFrameworkName)); - - // Calculate the preferred locale used by Chrome. - // We can't use l10n_util::OverrideLocaleWithCocoaLocale() because it calls - // [base::mac::OuterBundle() preferredLocalizations] which gets localizations - // from the bundle of the running app (i.e. it is equivalent to - // [[NSBundle mainBundle] preferredLocalizations]) instead of the target - // bundle. - NSArray* preferred_languages = [NSLocale preferredLanguages]; - NSArray* supported_languages = [base::mac::OuterBundle() localizations]; - std::string preferred_localization; - for (NSString* language in preferred_languages) { - if ([supported_languages containsObject:language]) { - preferred_localization = base::SysNSStringToUTF8(language); - break; - } - } - std::string locale = l10n_util::NormalizeLocale( - l10n_util::GetApplicationLocale(preferred_localization)); - - // Load localized strings. - ui::ResourceBundle::InitSharedInstanceWithLocale( - locale, NULL, ui::ResourceBundle::DO_NOT_LOAD_COMMON_RESOURCES); - - // Launch the IO thread. - base::Thread::Options io_thread_options; - io_thread_options.message_loop_type = base::MessageLoop::TYPE_IO; - base::Thread *io_thread = new base::Thread("CrAppShimIO"); - io_thread->StartWithOptions(io_thread_options); - g_io_thread = io_thread; - - // Find already running instances of Chrome. - pid_t pid = -1; - std::string chrome_process_id = CommandLine::ForCurrentProcess()-> - GetSwitchValueASCII(app_mode::kLaunchedByChromeProcessId); - if (!chrome_process_id.empty()) { - if (!base::StringToInt(chrome_process_id, &pid)) - LOG(FATAL) << "Invalid PID: " << chrome_process_id; - } else { - NSString* chrome_bundle_id = [base::mac::OuterBundle() bundleIdentifier]; - NSArray* existing_chrome = [NSRunningApplication - runningApplicationsWithBundleIdentifier:chrome_bundle_id]; - if ([existing_chrome count] > 0) - pid = [[existing_chrome objectAtIndex:0] processIdentifier]; - } - - AppShimController controller; - base::MessageLoopForUI main_message_loop; - main_message_loop.set_thread_name("MainThread"); - base::PlatformThread::SetName("CrAppShimMain"); - - // In tests, launching Chrome does nothing, and we won't get a ping response, - // so just assume the socket exists. - if (pid == -1 && - !CommandLine::ForCurrentProcess()->HasSwitch( - app_mode::kLaunchedForTest)) { - // Launch Chrome if it isn't already running. - ProcessSerialNumber psn; - CommandLine command_line(CommandLine::NO_PROGRAM); - command_line.AppendSwitch(switches::kSilentLaunch); - - // If the shim is the app launcher, pass --show-app-list when starting a new - // Chrome process to inform startup codepaths and load the correct profile. - if (info->app_mode_id == app_mode::kAppListModeId) { - command_line.AppendSwitch(switches::kShowAppList); - } else { - command_line.AppendSwitchPath(switches::kProfileDirectory, - info->profile_dir); - } - - bool success = - base::mac::OpenApplicationWithPath(base::mac::OuterBundlePath(), - command_line, - kLSLaunchDefaults, - &psn); - if (!success) - return 1; - - base::Callback<void(bool)> on_ping_chrome_reply = - base::Bind(&AppShimController::OnPingChromeReply, - base::Unretained(&controller)); - - // This code abuses the fact that Apple Events sent before the process is - // fully initialized don't receive a reply until its run loop starts. Once - // the reply is received, Chrome will have opened its IPC port, guaranteed. - [ReplyEventHandler pingProcess:psn - andCall:on_ping_chrome_reply]; - - main_message_loop.PostDelayedTask( - FROM_HERE, - base::Bind(&AppShimController::OnPingChromeTimeout, - base::Unretained(&controller)), - base::TimeDelta::FromSeconds(kPingChromeTimeoutSeconds)); - } else { - // Chrome already running. Proceed to init. This could still fail if Chrome - // is still starting up or shutting down, but the process will exit quickly, - // which is preferable to waiting for the Apple Event to timeout after one - // minute. - main_message_loop.PostTask( - FROM_HERE, - base::Bind(&AppShimController::Init, - base::Unretained(&controller))); - } - - main_message_loop.Run(); - return 0; -} diff --git a/apps/app_shim/extension_app_shim_handler_mac.cc b/apps/app_shim/extension_app_shim_handler_mac.cc deleted file mode 100644 index 8e90324..0000000 --- a/apps/app_shim/extension_app_shim_handler_mac.cc +++ /dev/null @@ -1,557 +0,0 @@ -// 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. - -#include "apps/app_shim/extension_app_shim_handler_mac.h" - -#include "apps/app_lifetime_monitor_factory.h" -#include "apps/app_shim/app_shim_host_manager_mac.h" -#include "apps/app_shim/app_shim_messages.h" -#include "apps/launcher.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/ui/extensions/extension_enable_flow.h" -#include "chrome/browser/ui/extensions/extension_enable_flow_delegate.h" -#include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h" -#include "chrome/browser/web_applications/web_app_mac.h" -#include "chrome/common/extensions/extension_constants.h" -#include "components/crx_file/id_util.h" -#include "content/public/browser/notification_details.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_source.h" -#include "extensions/browser/app_window/app_window.h" -#include "extensions/browser/app_window/app_window_registry.h" -#include "extensions/browser/app_window/native_app_window.h" -#include "extensions/browser/extension_host.h" -#include "extensions/browser/extension_registry.h" -#include "ui/base/cocoa/focus_window_set.h" - -using extensions::AppWindow; -using extensions::AppWindowRegistry; -using extensions::ExtensionRegistry; - -namespace { - -typedef AppWindowRegistry::AppWindowList AppWindowList; - -void ProfileLoadedCallback(base::Callback<void(Profile*)> callback, - Profile* profile, - Profile::CreateStatus status) { - if (status == Profile::CREATE_STATUS_INITIALIZED) { - callback.Run(profile); - return; - } - - // This should never get an error since it only loads existing profiles. - DCHECK_EQ(Profile::CREATE_STATUS_CREATED, status); -} - -void SetAppHidden(Profile* profile, const std::string& app_id, bool hidden) { - AppWindowList windows = - AppWindowRegistry::Get(profile)->GetAppWindowsForApp(app_id); - for (AppWindowList::const_reverse_iterator it = windows.rbegin(); - it != windows.rend(); - ++it) { - if (hidden) - (*it)->GetBaseWindow()->HideWithApp(); - else - (*it)->GetBaseWindow()->ShowWithApp(); - } -} - -bool FocusWindows(const AppWindowList& windows) { - if (windows.empty()) - return false; - - std::set<gfx::NativeWindow> native_windows; - for (AppWindowList::const_iterator it = windows.begin(); it != windows.end(); - ++it) { - native_windows.insert((*it)->GetNativeWindow()); - } - // Allow workspace switching. For the browser process, we can reasonably rely - // on OS X to switch spaces for us and honor relevant user settings. But shims - // don't have windows, so we have to do it ourselves. - ui::FocusWindowSet(native_windows); - return true; -} - -// Attempts to launch a packaged app, prompting the user to enable it if -// necessary. The prompt is shown in its own window. -// This class manages its own lifetime. -class EnableViaPrompt : public ExtensionEnableFlowDelegate { - public: - EnableViaPrompt(Profile* profile, - const std::string& extension_id, - const base::Callback<void()>& callback) - : profile_(profile), - extension_id_(extension_id), - callback_(callback) { - } - - virtual ~EnableViaPrompt() { - } - - void Run() { - flow_.reset(new ExtensionEnableFlow(profile_, extension_id_, this)); - flow_->StartForCurrentlyNonexistentWindow( - base::Callback<gfx::NativeWindow(void)>()); - } - - private: - // ExtensionEnableFlowDelegate overrides. - virtual void ExtensionEnableFlowFinished() OVERRIDE { - callback_.Run(); - delete this; - } - - virtual void ExtensionEnableFlowAborted(bool user_initiated) OVERRIDE { - callback_.Run(); - delete this; - } - - Profile* profile_; - std::string extension_id_; - base::Callback<void()> callback_; - scoped_ptr<ExtensionEnableFlow> flow_; - - DISALLOW_COPY_AND_ASSIGN(EnableViaPrompt); -}; - -} // namespace - -namespace apps { - -bool ExtensionAppShimHandler::Delegate::ProfileExistsForPath( - const base::FilePath& path) { - ProfileManager* profile_manager = g_browser_process->profile_manager(); - // 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 full_path = profile_manager->user_data_dir().Append(path); - ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); - return cache.GetIndexOfProfileWithPath(full_path) != std::string::npos; -} - -Profile* ExtensionAppShimHandler::Delegate::ProfileForPath( - const base::FilePath& path) { - ProfileManager* profile_manager = g_browser_process->profile_manager(); - base::FilePath full_path = profile_manager->user_data_dir().Append(path); - Profile* profile = profile_manager->GetProfileByPath(full_path); - - // Use IsValidProfile to check if the profile has been created. - return profile && profile_manager->IsValidProfile(profile) ? profile : NULL; -} - -void ExtensionAppShimHandler::Delegate::LoadProfileAsync( - const base::FilePath& path, - base::Callback<void(Profile*)> callback) { - ProfileManager* profile_manager = g_browser_process->profile_manager(); - base::FilePath full_path = profile_manager->user_data_dir().Append(path); - profile_manager->CreateProfileAsync( - full_path, - base::Bind(&ProfileLoadedCallback, callback), - base::string16(), base::string16(), std::string()); -} - -AppWindowList ExtensionAppShimHandler::Delegate::GetWindows( - Profile* profile, - const std::string& extension_id) { - return AppWindowRegistry::Get(profile)->GetAppWindowsForApp(extension_id); -} - -const extensions::Extension* -ExtensionAppShimHandler::Delegate::GetAppExtension( - Profile* profile, - const std::string& extension_id) { - ExtensionRegistry* registry = ExtensionRegistry::Get(profile); - const extensions::Extension* extension = - registry->GetExtensionById(extension_id, ExtensionRegistry::ENABLED); - return extension && extension->is_platform_app() ? extension : NULL; -} - -void ExtensionAppShimHandler::Delegate::EnableExtension( - Profile* profile, - const std::string& extension_id, - const base::Callback<void()>& callback) { - (new EnableViaPrompt(profile, extension_id, callback))->Run(); -} - -void ExtensionAppShimHandler::Delegate::LaunchApp( - Profile* profile, - const extensions::Extension* extension, - const std::vector<base::FilePath>& files) { - CoreAppLauncherHandler::RecordAppLaunchType( - extension_misc::APP_LAUNCH_CMD_LINE_APP, extension->GetType()); - if (files.empty()) { - apps::LaunchPlatformApp(profile, extension); - } else { - for (std::vector<base::FilePath>::const_iterator it = files.begin(); - it != files.end(); ++it) { - apps::LaunchPlatformAppWithPath(profile, extension, *it); - } - } -} - -void ExtensionAppShimHandler::Delegate::LaunchShim( - Profile* profile, - const extensions::Extension* extension) { - web_app::MaybeLaunchShortcut( - web_app::ShortcutInfoForExtensionAndProfile(extension, profile)); -} - -void ExtensionAppShimHandler::Delegate::MaybeTerminate() { - AppShimHandler::MaybeTerminate(); -} - -ExtensionAppShimHandler::ExtensionAppShimHandler() - : delegate_(new Delegate), - weak_factory_(this) { - // This is instantiated in BrowserProcessImpl::PreMainMessageLoopRun with - // AppShimHostManager. Since PROFILE_CREATED is not fired until - // ProfileManager::GetLastUsedProfile/GetLastOpenedProfiles, this should catch - // notifications for all profiles. - registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, - content::NotificationService::AllBrowserContextsAndSources()); - registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, - content::NotificationService::AllBrowserContextsAndSources()); -} - -ExtensionAppShimHandler::~ExtensionAppShimHandler() {} - -AppShimHandler::Host* ExtensionAppShimHandler::FindHost( - Profile* profile, - const std::string& app_id) { - HostMap::iterator it = hosts_.find(make_pair(profile, app_id)); - return it == hosts_.end() ? NULL : it->second; -} - -// static -void ExtensionAppShimHandler::QuitAppForWindow(AppWindow* app_window) { - ExtensionAppShimHandler* handler = GetInstance(); - Host* host = handler->FindHost( - Profile::FromBrowserContext(app_window->browser_context()), - app_window->extension_id()); - if (host) { - handler->OnShimQuit(host); - } else { - // App shims might be disabled or the shim is still starting up. - AppWindowRegistry::Get( - Profile::FromBrowserContext(app_window->browser_context())) - ->CloseAllAppWindowsForApp(app_window->extension_id()); - } -} - -void ExtensionAppShimHandler::HideAppForWindow(AppWindow* app_window) { - ExtensionAppShimHandler* handler = GetInstance(); - Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); - Host* host = handler->FindHost(profile, app_window->extension_id()); - if (host) - host->OnAppHide(); - else - SetAppHidden(profile, app_window->extension_id(), true); -} - -void ExtensionAppShimHandler::FocusAppForWindow(AppWindow* app_window) { - ExtensionAppShimHandler* handler = GetInstance(); - Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); - const std::string& app_id = app_window->extension_id(); - Host* host = handler->FindHost(profile, app_id); - if (host) { - handler->OnShimFocus(host, - APP_SHIM_FOCUS_NORMAL, - std::vector<base::FilePath>()); - } else { - FocusWindows(AppWindowRegistry::Get(profile)->GetAppWindowsForApp(app_id)); - } -} - -// static -bool ExtensionAppShimHandler::ActivateAndRequestUserAttentionForWindow( - AppWindow* app_window) { - ExtensionAppShimHandler* handler = GetInstance(); - Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); - Host* host = handler->FindHost(profile, app_window->extension_id()); - if (host) { - // Bring the window to the front without showing it. - AppWindowRegistry::Get(profile)->AppWindowActivated(app_window); - host->OnAppRequestUserAttention(APP_SHIM_ATTENTION_INFORMATIONAL); - return true; - } else { - // Just show the app. - SetAppHidden(profile, app_window->extension_id(), false); - return false; - } -} - -// static -void ExtensionAppShimHandler::RequestUserAttentionForWindow( - AppWindow* app_window, - AppShimAttentionType attention_type) { - ExtensionAppShimHandler* handler = GetInstance(); - Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); - Host* host = handler->FindHost(profile, app_window->extension_id()); - if (host) - host->OnAppRequestUserAttention(attention_type); -} - -// static -void ExtensionAppShimHandler::OnChromeWillHide() { - // Send OnAppHide to all the shims so that they go into the hidden state. - // This is necessary so that when the shim is next focused, it will know to - // unhide. - ExtensionAppShimHandler* handler = GetInstance(); - for (HostMap::iterator it = handler->hosts_.begin(); - it != handler->hosts_.end(); - ++it) { - it->second->OnAppHide(); - } -} - -void ExtensionAppShimHandler::OnShimLaunch( - Host* host, - AppShimLaunchType launch_type, - const std::vector<base::FilePath>& files) { - const std::string& app_id = host->GetAppId(); - DCHECK(crx_file::id_util::IdIsValid(app_id)); - - const base::FilePath& profile_path = host->GetProfilePath(); - DCHECK(!profile_path.empty()); - - if (!delegate_->ProfileExistsForPath(profile_path)) { - // User may have deleted the profile this shim was originally created for. - // TODO(jackhou): Add some UI for this case and remove the LOG. - LOG(ERROR) << "Requested directory is not a known profile '" - << profile_path.value() << "'."; - host->OnAppLaunchComplete(APP_SHIM_LAUNCH_PROFILE_NOT_FOUND); - return; - } - - Profile* profile = delegate_->ProfileForPath(profile_path); - - if (profile) { - OnProfileLoaded(host, launch_type, files, profile); - return; - } - - // If the profile is not loaded, this must have been a launch by the shim. - // Load the profile asynchronously, the host will be registered in - // OnProfileLoaded. - DCHECK_EQ(APP_SHIM_LAUNCH_NORMAL, launch_type); - delegate_->LoadProfileAsync( - profile_path, - base::Bind(&ExtensionAppShimHandler::OnProfileLoaded, - weak_factory_.GetWeakPtr(), - host, launch_type, files)); - - // Return now. OnAppLaunchComplete will be called when the app is activated. -} - -// static -ExtensionAppShimHandler* ExtensionAppShimHandler::GetInstance() { - return g_browser_process->platform_part() - ->app_shim_host_manager() - ->extension_app_shim_handler(); -} - -void ExtensionAppShimHandler::OnProfileLoaded( - Host* host, - AppShimLaunchType launch_type, - const std::vector<base::FilePath>& files, - Profile* profile) { - const std::string& app_id = host->GetAppId(); - - // The first host to claim this (profile, app_id) becomes the main host. - // For any others, focus or relaunch the app. - if (!hosts_.insert(make_pair(make_pair(profile, app_id), host)).second) { - OnShimFocus(host, - launch_type == APP_SHIM_LAUNCH_NORMAL ? - APP_SHIM_FOCUS_REOPEN : APP_SHIM_FOCUS_NORMAL, - files); - host->OnAppLaunchComplete(APP_SHIM_LAUNCH_DUPLICATE_HOST); - return; - } - - if (launch_type != APP_SHIM_LAUNCH_NORMAL) { - host->OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS); - return; - } - - // 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 - // life within a certain window. - const extensions::Extension* extension = - delegate_->GetAppExtension(profile, app_id); - if (extension) { - delegate_->LaunchApp(profile, extension, files); - return; - } - - delegate_->EnableExtension( - profile, app_id, - base::Bind(&ExtensionAppShimHandler::OnExtensionEnabled, - weak_factory_.GetWeakPtr(), - host->GetProfilePath(), app_id, files)); -} - -void ExtensionAppShimHandler::OnExtensionEnabled( - const base::FilePath& profile_path, - const std::string& app_id, - const std::vector<base::FilePath>& files) { - Profile* profile = delegate_->ProfileForPath(profile_path); - if (!profile) - return; - - const extensions::Extension* extension = - delegate_->GetAppExtension(profile, app_id); - if (!extension || !delegate_->ProfileExistsForPath(profile_path)) { - // If !extension, the extension doesn't exist, or was not re-enabled. - // If the profile doesn't exist, it may have been deleted during the enable - // prompt. In this case, NOTIFICATION_PROFILE_DESTROYED may not be fired - // until later, so respond to the host now. - Host* host = FindHost(profile, app_id); - if (host) - host->OnAppLaunchComplete(APP_SHIM_LAUNCH_APP_NOT_FOUND); - return; - } - - delegate_->LaunchApp(profile, extension, files); -} - - -void ExtensionAppShimHandler::OnShimClose(Host* host) { - // This might be called when shutting down. Don't try to look up the profile - // since profile_manager might not be around. - for (HostMap::iterator it = hosts_.begin(); it != hosts_.end(); ) { - HostMap::iterator current = it++; - if (current->second == host) - hosts_.erase(current); - } -} - -void ExtensionAppShimHandler::OnShimFocus( - Host* host, - AppShimFocusType focus_type, - const std::vector<base::FilePath>& files) { - DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); - Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); - - const AppWindowList windows = - delegate_->GetWindows(profile, host->GetAppId()); - bool windows_focused = FocusWindows(windows); - - if (focus_type == APP_SHIM_FOCUS_NORMAL || - (focus_type == APP_SHIM_FOCUS_REOPEN && windows_focused)) { - return; - } - - const extensions::Extension* extension = - delegate_->GetAppExtension(profile, host->GetAppId()); - if (extension) { - delegate_->LaunchApp(profile, extension, files); - } else { - // Extensions may have been uninstalled or disabled since the shim - // started. - host->OnAppClosed(); - } -} - -void ExtensionAppShimHandler::OnShimSetHidden(Host* host, bool hidden) { - DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); - Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); - - SetAppHidden(profile, host->GetAppId(), hidden); -} - -void ExtensionAppShimHandler::OnShimQuit(Host* host) { - DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); - Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); - - const std::string& app_id = host->GetAppId(); - const AppWindowList windows = delegate_->GetWindows(profile, app_id); - for (AppWindowRegistry::const_iterator it = windows.begin(); - it != windows.end(); - ++it) { - (*it)->GetBaseWindow()->Close(); - } - // Once the last window closes, flow will end up in OnAppDeactivated via - // AppLifetimeMonitor. -} - -void ExtensionAppShimHandler::set_delegate(Delegate* delegate) { - delegate_.reset(delegate); -} - -void ExtensionAppShimHandler::Observe( - int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - Profile* profile = content::Source<Profile>(source).ptr(); - if (profile->IsOffTheRecord()) - return; - - switch (type) { - case chrome::NOTIFICATION_PROFILE_CREATED: { - AppLifetimeMonitorFactory::GetForProfile(profile)->AddObserver(this); - break; - } - case chrome::NOTIFICATION_PROFILE_DESTROYED: { - AppLifetimeMonitorFactory::GetForProfile(profile)->RemoveObserver(this); - // Shut down every shim associated with this profile. - for (HostMap::iterator it = hosts_.begin(); it != hosts_.end(); ) { - // Increment the iterator first as OnAppClosed may call back to - // OnShimClose and invalidate the iterator. - HostMap::iterator current = it++; - if (profile->IsSameProfile(current->first.first)) { - Host* host = current->second; - host->OnAppClosed(); - } - } - break; - } - default: { - NOTREACHED(); // Unexpected notification. - break; - } - } -} - -void ExtensionAppShimHandler::OnAppStart(Profile* profile, - const std::string& app_id) {} - -void ExtensionAppShimHandler::OnAppActivated(Profile* profile, - const std::string& app_id) { - const extensions::Extension* extension = - delegate_->GetAppExtension(profile, app_id); - if (!extension) - return; - - Host* host = FindHost(profile, app_id); - if (host) { - host->OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS); - OnShimFocus(host, APP_SHIM_FOCUS_NORMAL, std::vector<base::FilePath>()); - return; - } - - delegate_->LaunchShim(profile, extension); -} - -void ExtensionAppShimHandler::OnAppDeactivated(Profile* profile, - const std::string& app_id) { - Host* host = FindHost(profile, app_id); - if (host) - host->OnAppClosed(); - - if (hosts_.empty()) - delegate_->MaybeTerminate(); -} - -void ExtensionAppShimHandler::OnAppStop(Profile* profile, - const std::string& app_id) {} - -void ExtensionAppShimHandler::OnChromeTerminating() {} - -} // namespace apps diff --git a/apps/app_shim/extension_app_shim_handler_mac.h b/apps/app_shim/extension_app_shim_handler_mac.h deleted file mode 100644 index 6bebb04..0000000 --- a/apps/app_shim/extension_app_shim_handler_mac.h +++ /dev/null @@ -1,159 +0,0 @@ -// 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_EXTENSION_APP_SHIM_HANDLER_MAC_H_ -#define APPS_APP_SHIM_EXTENSION_APP_SHIM_HANDLER_MAC_H_ - -#include <map> -#include <string> -#include <vector> - -#include "apps/app_lifetime_monitor.h" -#include "apps/app_shim/app_shim_handler_mac.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" -#include "extensions/browser/app_window/app_window_registry.h" - -class Profile; - -namespace base { -class FilePath; -} - -namespace content { -class WebContents; -} - -namespace extensions { -class AppWindow; -class Extension; -} - -namespace apps { - -// This app shim handler that handles events for app shims that correspond to an -// extension. -class ExtensionAppShimHandler : public AppShimHandler, - public content::NotificationObserver, - public AppLifetimeMonitor::Observer { - public: - class Delegate { - public: - virtual ~Delegate() {} - - virtual bool ProfileExistsForPath(const base::FilePath& path); - virtual Profile* ProfileForPath(const base::FilePath& path); - virtual void LoadProfileAsync(const base::FilePath& path, - base::Callback<void(Profile*)> callback); - - virtual extensions::AppWindowRegistry::AppWindowList GetWindows( - Profile* profile, - const std::string& extension_id); - - virtual const extensions::Extension* GetAppExtension( - Profile* profile, const std::string& extension_id); - virtual void EnableExtension(Profile* profile, - const std::string& extension_id, - const base::Callback<void()>& callback); - virtual void LaunchApp(Profile* profile, - const extensions::Extension* extension, - const std::vector<base::FilePath>& files); - virtual void LaunchShim(Profile* profile, - const extensions::Extension* extension); - - virtual void MaybeTerminate(); - }; - - ExtensionAppShimHandler(); - virtual ~ExtensionAppShimHandler(); - - AppShimHandler::Host* FindHost(Profile* profile, const std::string& app_id); - - static void QuitAppForWindow(extensions::AppWindow* app_window); - - static void HideAppForWindow(extensions::AppWindow* app_window); - - static void FocusAppForWindow(extensions::AppWindow* app_window); - - // Brings the window to the front without showing it and instructs the shim to - // request user attention. If there is no shim, show the app and return false. - static bool ActivateAndRequestUserAttentionForWindow( - extensions::AppWindow* app_window); - - // Instructs the shim to request user attention. Returns false if there is no - // shim for this window. - static void RequestUserAttentionForWindow( - extensions::AppWindow* app_window, - AppShimAttentionType attention_type); - - // Called by AppControllerMac when Chrome hides. - static void OnChromeWillHide(); - - // AppShimHandler overrides: - virtual void OnShimLaunch(Host* host, - AppShimLaunchType launch_type, - const std::vector<base::FilePath>& files) OVERRIDE; - virtual void OnShimClose(Host* host) OVERRIDE; - virtual void OnShimFocus(Host* host, - AppShimFocusType focus_type, - const std::vector<base::FilePath>& files) OVERRIDE; - virtual void OnShimSetHidden(Host* host, bool hidden) OVERRIDE; - virtual void OnShimQuit(Host* host) OVERRIDE; - - // AppLifetimeMonitor::Observer overrides: - virtual void OnAppStart(Profile* profile, const std::string& app_id) OVERRIDE; - virtual void OnAppActivated(Profile* profile, - const std::string& app_id) OVERRIDE; - virtual void OnAppDeactivated(Profile* profile, - const std::string& app_id) OVERRIDE; - virtual void OnAppStop(Profile* profile, const std::string& app_id) OVERRIDE; - virtual void OnChromeTerminating() OVERRIDE; - - // content::NotificationObserver overrides: - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) OVERRIDE; - - protected: - typedef std::map<std::pair<Profile*, std::string>, AppShimHandler::Host*> - HostMap; - - // Exposed for testing. - void set_delegate(Delegate* delegate); - HostMap& hosts() { return hosts_; } - content::NotificationRegistrar& registrar() { return registrar_; } - - private: - // Helper function to get the instance on the browser process. - static ExtensionAppShimHandler* GetInstance(); - - // This is passed to Delegate::LoadProfileAsync for shim-initiated launches - // where the profile was not yet loaded. - void OnProfileLoaded(Host* host, - AppShimLaunchType launch_type, - const std::vector<base::FilePath>& files, - Profile* profile); - - // This is passed to Delegate::EnableViaPrompt for shim-initiated launches - // where the extension is disabled. - void OnExtensionEnabled(const base::FilePath& profile_path, - const std::string& app_id, - const std::vector<base::FilePath>& files); - - scoped_ptr<Delegate> delegate_; - - HostMap hosts_; - - content::NotificationRegistrar registrar_; - - base::WeakPtrFactory<ExtensionAppShimHandler> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(ExtensionAppShimHandler); -}; - -} // namespace apps - -#endif // APPS_APP_SHIM_EXTENSION_APP_SHIM_HANDLER_MAC_H_ diff --git a/apps/app_shim/extension_app_shim_handler_mac_unittest.cc b/apps/app_shim/extension_app_shim_handler_mac_unittest.cc deleted file mode 100644 index 27791d9..0000000 --- a/apps/app_shim/extension_app_shim_handler_mac_unittest.cc +++ /dev/null @@ -1,396 +0,0 @@ -// 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. - -#include "apps/app_shim/extension_app_shim_handler_mac.h" - -#include <vector> - -#include "apps/app_shim/app_shim_host_mac.h" -#include "base/memory/scoped_ptr.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/test/base/testing_profile.h" -#include "content/public/browser/notification_service.h" -#include "extensions/common/extension.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace apps { - -using extensions::Extension; -typedef extensions::AppWindowRegistry::AppWindowList AppWindowList; - -using ::testing::_; -using ::testing::Invoke; -using ::testing::Return; -using ::testing::WithArgs; - -class MockDelegate : public ExtensionAppShimHandler::Delegate { - public: - virtual ~MockDelegate() {} - - MOCK_METHOD1(ProfileExistsForPath, bool(const base::FilePath&)); - MOCK_METHOD1(ProfileForPath, Profile*(const base::FilePath&)); - MOCK_METHOD2(LoadProfileAsync, - void(const base::FilePath&, - base::Callback<void(Profile*)>)); - - MOCK_METHOD2(GetWindows, AppWindowList(Profile*, const std::string&)); - - MOCK_METHOD2(GetAppExtension, const Extension*(Profile*, const std::string&)); - MOCK_METHOD3(EnableExtension, void(Profile*, - const std::string&, - const base::Callback<void()>&)); - MOCK_METHOD3(LaunchApp, - void(Profile*, - const Extension*, - const std::vector<base::FilePath>&)); - MOCK_METHOD2(LaunchShim, void(Profile*, const Extension*)); - - MOCK_METHOD0(MaybeTerminate, void()); - - void CaptureLoadProfileCallback( - const base::FilePath& path, - base::Callback<void(Profile*)> callback) { - callbacks_[path] = callback; - } - - bool RunLoadProfileCallback( - const base::FilePath& path, - Profile* profile) { - callbacks_[path].Run(profile); - return callbacks_.erase(path); - } - - void RunCallback(const base::Callback<void()>& callback) { - callback.Run(); - } - - private: - std::map<base::FilePath, - base::Callback<void(Profile*)> > callbacks_; -}; - -class TestingExtensionAppShimHandler : public ExtensionAppShimHandler { - public: - TestingExtensionAppShimHandler(Delegate* delegate) { - set_delegate(delegate); - } - virtual ~TestingExtensionAppShimHandler() {} - - MOCK_METHOD3(OnShimFocus, - void(Host* host, - AppShimFocusType, - const std::vector<base::FilePath>& files)); - - void RealOnShimFocus(Host* host, - AppShimFocusType focus_type, - const std::vector<base::FilePath>& files) { - ExtensionAppShimHandler::OnShimFocus(host, focus_type, files); - } - - AppShimHandler::Host* FindHost(Profile* profile, - const std::string& app_id) { - HostMap::const_iterator it = hosts().find(make_pair(profile, app_id)); - return it == hosts().end() ? NULL : it->second; - } - - content::NotificationRegistrar& GetRegistrar() { return registrar(); } - - private: - DISALLOW_COPY_AND_ASSIGN(TestingExtensionAppShimHandler); -}; - -const char kTestAppIdA[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; -const char kTestAppIdB[] = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; - -class FakeHost : public apps::AppShimHandler::Host { - public: - FakeHost(const base::FilePath& profile_path, - const std::string& app_id, - TestingExtensionAppShimHandler* handler) - : profile_path_(profile_path), - app_id_(app_id), - handler_(handler), - close_count_(0) {} - - MOCK_METHOD1(OnAppLaunchComplete, void(AppShimLaunchResult)); - - virtual void OnAppClosed() OVERRIDE { - handler_->OnShimClose(this); - ++close_count_; - } - virtual void OnAppHide() OVERRIDE {} - virtual void OnAppRequestUserAttention(AppShimAttentionType type) OVERRIDE {} - virtual base::FilePath GetProfilePath() const OVERRIDE { - return profile_path_; - } - virtual std::string GetAppId() const OVERRIDE { return app_id_; } - - int close_count() { return close_count_; } - - private: - base::FilePath profile_path_; - std::string app_id_; - TestingExtensionAppShimHandler* handler_; - int close_count_; - - DISALLOW_COPY_AND_ASSIGN(FakeHost); -}; - -class ExtensionAppShimHandlerTest : public testing::Test { - protected: - ExtensionAppShimHandlerTest() - : delegate_(new MockDelegate), - handler_(new TestingExtensionAppShimHandler(delegate_)), - profile_path_a_("Profile A"), - profile_path_b_("Profile B"), - host_aa_(profile_path_a_, kTestAppIdA, handler_.get()), - host_ab_(profile_path_a_, kTestAppIdB, handler_.get()), - host_bb_(profile_path_b_, kTestAppIdB, handler_.get()), - host_aa_duplicate_(profile_path_a_, kTestAppIdA, handler_.get()) { - base::FilePath extension_path("/fake/path"); - base::DictionaryValue manifest; - manifest.SetString("name", "Fake Name"); - manifest.SetString("version", "1"); - std::string error; - extension_a_ = Extension::Create( - extension_path, extensions::Manifest::INTERNAL, manifest, - Extension::NO_FLAGS, kTestAppIdA, &error); - EXPECT_TRUE(extension_a_.get()) << error; - - extension_b_ = Extension::Create( - extension_path, extensions::Manifest::INTERNAL, manifest, - Extension::NO_FLAGS, kTestAppIdB, &error); - EXPECT_TRUE(extension_b_.get()) << error; - - EXPECT_CALL(*delegate_, ProfileExistsForPath(profile_path_a_)) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*delegate_, ProfileForPath(profile_path_a_)) - .WillRepeatedly(Return(&profile_a_)); - EXPECT_CALL(*delegate_, ProfileExistsForPath(profile_path_b_)) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*delegate_, ProfileForPath(profile_path_b_)) - .WillRepeatedly(Return(&profile_b_)); - - // In most tests, we don't care about the result of GetWindows, it just - // needs to be non-empty. - AppWindowList app_window_list; - app_window_list.push_back(static_cast<extensions::AppWindow*>(NULL)); - EXPECT_CALL(*delegate_, GetWindows(_, _)) - .WillRepeatedly(Return(app_window_list)); - - EXPECT_CALL(*delegate_, GetAppExtension(_, kTestAppIdA)) - .WillRepeatedly(Return(extension_a_.get())); - EXPECT_CALL(*delegate_, GetAppExtension(_, kTestAppIdB)) - .WillRepeatedly(Return(extension_b_.get())); - EXPECT_CALL(*delegate_, LaunchApp(_, _, _)) - .WillRepeatedly(Return()); - } - - void NormalLaunch(AppShimHandler::Host* host) { - handler_->OnShimLaunch(host, - APP_SHIM_LAUNCH_NORMAL, - std::vector<base::FilePath>()); - } - - void RegisterOnlyLaunch(AppShimHandler::Host* host) { - handler_->OnShimLaunch(host, - APP_SHIM_LAUNCH_REGISTER_ONLY, - std::vector<base::FilePath>()); - } - - MockDelegate* delegate_; - scoped_ptr<TestingExtensionAppShimHandler> handler_; - base::FilePath profile_path_a_; - base::FilePath profile_path_b_; - TestingProfile profile_a_; - TestingProfile profile_b_; - FakeHost host_aa_; - FakeHost host_ab_; - FakeHost host_bb_; - FakeHost host_aa_duplicate_; - scoped_refptr<Extension> extension_a_; - scoped_refptr<Extension> extension_b_; - - private: - DISALLOW_COPY_AND_ASSIGN(ExtensionAppShimHandlerTest); -}; - -TEST_F(ExtensionAppShimHandlerTest, LaunchProfileNotFound) { - // Bad profile path. - EXPECT_CALL(*delegate_, ProfileExistsForPath(profile_path_a_)) - .WillOnce(Return(false)) - .WillRepeatedly(Return(true)); - EXPECT_CALL(host_aa_, OnAppLaunchComplete(APP_SHIM_LAUNCH_PROFILE_NOT_FOUND)); - NormalLaunch(&host_aa_); -} - -TEST_F(ExtensionAppShimHandlerTest, LaunchAppNotFound) { - // App not found. - EXPECT_CALL(*delegate_, GetAppExtension(&profile_a_, kTestAppIdA)) - .WillRepeatedly(Return(static_cast<const Extension*>(NULL))); - EXPECT_CALL(*delegate_, EnableExtension(&profile_a_, kTestAppIdA, _)) - .WillOnce(WithArgs<2>(Invoke(delegate_, &MockDelegate::RunCallback))); - EXPECT_CALL(host_aa_, OnAppLaunchComplete(APP_SHIM_LAUNCH_APP_NOT_FOUND)); - NormalLaunch(&host_aa_); -} - -TEST_F(ExtensionAppShimHandlerTest, LaunchAppNotEnabled) { - // App not found. - EXPECT_CALL(*delegate_, GetAppExtension(&profile_a_, kTestAppIdA)) - .WillOnce(Return(static_cast<const Extension*>(NULL))) - .WillRepeatedly(Return(extension_a_.get())); - EXPECT_CALL(*delegate_, EnableExtension(&profile_a_, kTestAppIdA, _)) - .WillOnce(WithArgs<2>(Invoke(delegate_, &MockDelegate::RunCallback))); - NormalLaunch(&host_aa_); -} - -TEST_F(ExtensionAppShimHandlerTest, LaunchAndCloseShim) { - // Normal startup. - NormalLaunch(&host_aa_); - EXPECT_EQ(&host_aa_, handler_->FindHost(&profile_a_, kTestAppIdA)); - - NormalLaunch(&host_ab_); - EXPECT_EQ(&host_ab_, handler_->FindHost(&profile_a_, kTestAppIdB)); - - std::vector<base::FilePath> some_file(1, base::FilePath("some_file")); - EXPECT_CALL(*delegate_, - LaunchApp(&profile_b_, extension_b_.get(), some_file)); - handler_->OnShimLaunch(&host_bb_, APP_SHIM_LAUNCH_NORMAL, some_file); - EXPECT_EQ(&host_bb_, handler_->FindHost(&profile_b_, kTestAppIdB)); - - // Activation when there is a registered shim finishes launch with success and - // focuses the app. - EXPECT_CALL(host_aa_, OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS)); - EXPECT_CALL(*handler_, OnShimFocus(&host_aa_, APP_SHIM_FOCUS_NORMAL, _)); - handler_->OnAppActivated(&profile_a_, kTestAppIdA); - - // Starting and closing a second host just focuses the app. - EXPECT_CALL(*handler_, OnShimFocus(&host_aa_duplicate_, - APP_SHIM_FOCUS_REOPEN, - some_file)); - EXPECT_CALL(host_aa_duplicate_, - OnAppLaunchComplete(APP_SHIM_LAUNCH_DUPLICATE_HOST)); - handler_->OnShimLaunch(&host_aa_duplicate_, - APP_SHIM_LAUNCH_NORMAL, - some_file); - EXPECT_EQ(&host_aa_, handler_->FindHost(&profile_a_, kTestAppIdA)); - handler_->OnShimClose(&host_aa_duplicate_); - EXPECT_EQ(&host_aa_, handler_->FindHost(&profile_a_, kTestAppIdA)); - - // Normal close. - handler_->OnShimClose(&host_aa_); - EXPECT_FALSE(handler_->FindHost(&profile_a_, kTestAppIdA)); - - // Closing the second host afterward does nothing. - handler_->OnShimClose(&host_aa_duplicate_); - EXPECT_FALSE(handler_->FindHost(&profile_a_, kTestAppIdA)); -} - -TEST_F(ExtensionAppShimHandlerTest, AppLifetime) { - // When the app activates, if there is no shim, start one. - EXPECT_CALL(*delegate_, LaunchShim(&profile_a_, extension_a_.get())); - handler_->OnAppActivated(&profile_a_, kTestAppIdA); - - // Normal shim launch adds an entry in the map. - // App should not be launched here, but return success to the shim. - EXPECT_CALL(*delegate_, - LaunchApp(&profile_a_, extension_a_.get(), _)) - .Times(0); - EXPECT_CALL(host_aa_, OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS)); - RegisterOnlyLaunch(&host_aa_); - EXPECT_EQ(&host_aa_, handler_->FindHost(&profile_a_, kTestAppIdA)); - - // Return no app windows for OnShimFocus and OnShimQuit. - AppWindowList app_window_list; - EXPECT_CALL(*delegate_, GetWindows(&profile_a_, kTestAppIdA)) - .WillRepeatedly(Return(app_window_list)); - - // Non-reopen focus does nothing. - EXPECT_CALL(*handler_, OnShimFocus(&host_aa_, APP_SHIM_FOCUS_NORMAL, _)) - .WillOnce(Invoke(handler_.get(), - &TestingExtensionAppShimHandler::RealOnShimFocus)); - EXPECT_CALL(*delegate_, - LaunchApp(&profile_a_, extension_a_.get(), _)) - .Times(0); - handler_->OnShimFocus(&host_aa_, - APP_SHIM_FOCUS_NORMAL, - std::vector<base::FilePath>()); - - // Reopen focus launches the app. - EXPECT_CALL(*handler_, OnShimFocus(&host_aa_, APP_SHIM_FOCUS_REOPEN, _)) - .WillOnce(Invoke(handler_.get(), - &TestingExtensionAppShimHandler::RealOnShimFocus)); - std::vector<base::FilePath> some_file(1, base::FilePath("some_file")); - EXPECT_CALL(*delegate_, - LaunchApp(&profile_a_, extension_a_.get(), some_file)); - handler_->OnShimFocus(&host_aa_, APP_SHIM_FOCUS_REOPEN, some_file); - - // Quit just closes all the windows. This tests that it doesn't terminate, - // but we expect closing all windows triggers a OnAppDeactivated from - // AppLifetimeMonitor. - handler_->OnShimQuit(&host_aa_); - - // Closing all windows closes the shim and checks if Chrome should be - // terminated. - EXPECT_CALL(*delegate_, MaybeTerminate()) - .WillOnce(Return()); - handler_->OnAppDeactivated(&profile_a_, kTestAppIdA); - EXPECT_EQ(1, host_aa_.close_count()); -} - -TEST_F(ExtensionAppShimHandlerTest, MaybeTerminate) { - // Launch shims, adding entries in the map. - EXPECT_CALL(host_aa_, OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS)); - RegisterOnlyLaunch(&host_aa_); - EXPECT_EQ(&host_aa_, handler_->FindHost(&profile_a_, kTestAppIdA)); - - EXPECT_CALL(host_ab_, OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS)); - RegisterOnlyLaunch(&host_ab_); - EXPECT_EQ(&host_ab_, handler_->FindHost(&profile_a_, kTestAppIdB)); - - // Return empty window list. - AppWindowList app_window_list; - EXPECT_CALL(*delegate_, GetWindows(_, _)) - .WillRepeatedly(Return(app_window_list)); - - // Quitting when there's another shim should not terminate. - EXPECT_CALL(*delegate_, MaybeTerminate()) - .Times(0); - handler_->OnAppDeactivated(&profile_a_, kTestAppIdA); - - // Quitting when it's the last shim should terminate. - EXPECT_CALL(*delegate_, MaybeTerminate()); - handler_->OnAppDeactivated(&profile_a_, kTestAppIdB); -} - -TEST_F(ExtensionAppShimHandlerTest, RegisterOnly) { - // For an APP_SHIM_LAUNCH_REGISTER_ONLY, don't launch the app. - EXPECT_CALL(*delegate_, LaunchApp(_, _, _)) - .Times(0); - EXPECT_CALL(host_aa_, OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS)); - RegisterOnlyLaunch(&host_aa_); - EXPECT_TRUE(handler_->FindHost(&profile_a_, kTestAppIdA)); - - // Close the shim, removing the entry in the map. - handler_->OnShimClose(&host_aa_); - EXPECT_FALSE(handler_->FindHost(&profile_a_, kTestAppIdA)); -} - -TEST_F(ExtensionAppShimHandlerTest, LoadProfile) { - // If the profile is not loaded when an OnShimLaunch arrives, return false - // and load the profile asynchronously. Launch the app when the profile is - // ready. - EXPECT_CALL(*delegate_, ProfileForPath(profile_path_a_)) - .WillOnce(Return(static_cast<Profile*>(NULL))) - .WillRepeatedly(Return(&profile_a_)); - EXPECT_CALL(*delegate_, LoadProfileAsync(profile_path_a_, _)) - .WillOnce(Invoke(delegate_, &MockDelegate::CaptureLoadProfileCallback)); - NormalLaunch(&host_aa_); - EXPECT_FALSE(handler_->FindHost(&profile_a_, kTestAppIdA)); - delegate_->RunLoadProfileCallback(profile_path_a_, &profile_a_); - EXPECT_TRUE(handler_->FindHost(&profile_a_, kTestAppIdA)); -} - -} // namespace apps diff --git a/apps/app_shim/test/app_shim_host_manager_test_api_mac.cc b/apps/app_shim/test/app_shim_host_manager_test_api_mac.cc deleted file mode 100644 index 6fbdd8c..0000000 --- a/apps/app_shim/test/app_shim_host_manager_test_api_mac.cc +++ /dev/null @@ -1,26 +0,0 @@ -// 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. - -#include "apps/app_shim/test/app_shim_host_manager_test_api_mac.h" - -#include "apps/app_shim/app_shim_host_manager_mac.h" -#include "base/files/file_path.h" - -namespace test { - -AppShimHostManagerTestApi::AppShimHostManagerTestApi( - AppShimHostManager* host_manager) - : host_manager_(host_manager) { - DCHECK(host_manager_); -} - -apps::UnixDomainSocketAcceptor* AppShimHostManagerTestApi::acceptor() { - return host_manager_->acceptor_.get(); -} - -const base::FilePath& AppShimHostManagerTestApi::directory_in_tmp() { - return host_manager_->directory_in_tmp_; -} - -} // namespace test diff --git a/apps/app_shim/test/app_shim_host_manager_test_api_mac.h b/apps/app_shim/test/app_shim_host_manager_test_api_mac.h deleted file mode 100644 index b42e389..0000000 --- a/apps/app_shim/test/app_shim_host_manager_test_api_mac.h +++ /dev/null @@ -1,38 +0,0 @@ -// 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_TEST_APP_SHIM_HOST_MANAGER_TEST_API_MAC_H -#define APPS_APP_SHIM_TEST_APP_SHIM_HOST_MANAGER_TEST_API_MAC_H - -#include "base/basictypes.h" - -class AppShimHostManager; - -namespace base { -class FilePath; -} - -namespace apps { -class UnixDomainSocketAcceptor; -} - -namespace test { - -class AppShimHostManagerTestApi { - public: - explicit AppShimHostManagerTestApi(AppShimHostManager* host_manager); - - apps::UnixDomainSocketAcceptor* acceptor(); - - const base::FilePath& directory_in_tmp(); - - private: - AppShimHostManager* host_manager_; // Not owned. - - DISALLOW_COPY_AND_ASSIGN(AppShimHostManagerTestApi); -}; - -} // namespace test - -#endif // APPS_APP_SHIM_TEST_APP_SHIM_HOST_MANAGER_TEST_API_MAC_H diff --git a/apps/app_shim/unix_domain_socket_acceptor.cc b/apps/app_shim/unix_domain_socket_acceptor.cc deleted file mode 100644 index f5cda65..0000000 --- a/apps/app_shim/unix_domain_socket_acceptor.cc +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2014 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. - -#include "apps/app_shim/unix_domain_socket_acceptor.h" - -#include "base/files/file_util.h" -#include "base/files/scoped_file.h" -#include "base/logging.h" -#include "ipc/unix_domain_socket_util.h" - -namespace apps { - -UnixDomainSocketAcceptor::UnixDomainSocketAcceptor(const base::FilePath& path, - Delegate* delegate) - : path_(path), delegate_(delegate), listen_fd_(-1) { - DCHECK(delegate_); - CreateSocket(); -} - -UnixDomainSocketAcceptor::~UnixDomainSocketAcceptor() { - Close(); -} - -bool UnixDomainSocketAcceptor::CreateSocket() { - DCHECK(listen_fd_ < 0); - - // Create the socket. - return IPC::CreateServerUnixDomainSocket(path_, &listen_fd_); -} - -bool UnixDomainSocketAcceptor::Listen() { - if (listen_fd_ < 0) - return false; - - // Watch the fd for connections, and turn any connections into - // active sockets. - base::MessageLoopForIO::current()->WatchFileDescriptor( - listen_fd_, - true, - base::MessageLoopForIO::WATCH_READ, - &server_listen_connection_watcher_, - this); - return true; -} - -// Called by libevent when we can read from the fd without blocking. -void UnixDomainSocketAcceptor::OnFileCanReadWithoutBlocking(int fd) { - DCHECK(fd == listen_fd_); - int new_fd = -1; - if (!IPC::ServerAcceptConnection(listen_fd_, &new_fd)) { - Close(); - delegate_->OnListenError(); - return; - } - base::ScopedFD scoped_fd(new_fd); - - if (!scoped_fd.is_valid()) { - // The accept() failed, but not in such a way that the factory needs to be - // shut down. - return; - } - - // Verify that the IPC channel peer is running as the same user. - if (!IPC::IsPeerAuthorized(scoped_fd.get())) - return; - - IPC::ChannelHandle handle(std::string(), - base::FileDescriptor(scoped_fd.release(), true)); - delegate_->OnClientConnected(handle); -} - -void UnixDomainSocketAcceptor::OnFileCanWriteWithoutBlocking(int fd) { - NOTREACHED() << "Listen fd should never be writable."; -} - -void UnixDomainSocketAcceptor::Close() { - if (listen_fd_ < 0) - return; - if (IGNORE_EINTR(close(listen_fd_)) < 0) - PLOG(ERROR) << "close"; - listen_fd_ = -1; - if (unlink(path_.value().c_str()) < 0) - PLOG(ERROR) << "unlink"; - - // Unregister libevent for the listening socket and close it. - server_listen_connection_watcher_.StopWatchingFileDescriptor(); -} - -} // namespace apps diff --git a/apps/app_shim/unix_domain_socket_acceptor.h b/apps/app_shim/unix_domain_socket_acceptor.h deleted file mode 100644 index 64ee306..0000000 --- a/apps/app_shim/unix_domain_socket_acceptor.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2014 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_UNIX_DOMAIN_SOCKET_ACCEPTOR_H_ -#define APPS_APP_SHIM_UNIX_DOMAIN_SOCKET_ACCEPTOR_H_ - -#include "base/files/file_path.h" -#include "base/message_loop/message_loop.h" -#include "ipc/ipc_channel_handle.h" - -namespace apps { - -// A UnixDomainSocketAcceptor listens on a UNIX domain socket. When a -// client connects to the socket, it accept()s the connection and -// passes the new FD to the delegate. The delegate is then responsible -// for creating a new IPC::Channel for the FD. -class UnixDomainSocketAcceptor : public base::MessageLoopForIO::Watcher { - public: - class Delegate { - public: - // Called when a client connects to the factory. It is the delegate's - // responsibility to create an IPC::Channel for the handle, or else close - // the file descriptor contained therein. - virtual void OnClientConnected(const IPC::ChannelHandle& handle) = 0; - - // Called when an error occurs and the channel is closed. - virtual void OnListenError() = 0; - }; - - UnixDomainSocketAcceptor(const base::FilePath& path, Delegate* delegate); - - virtual ~UnixDomainSocketAcceptor(); - - // Call this to start listening on the socket. - bool Listen(); - - // Close and unlink the socket, and stop accepting connections. - void Close(); - - private: - bool CreateSocket(); - virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE; - virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE; - - base::MessageLoopForIO::FileDescriptorWatcher - server_listen_connection_watcher_; - base::FilePath path_; - Delegate* delegate_; - int listen_fd_; - - DISALLOW_COPY_AND_ASSIGN(UnixDomainSocketAcceptor); -}; - -} // namespace apps - -#endif // APPS_APP_SHIM_UNIX_DOMAIN_SOCKET_ACCEPTOR_H_ |