summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2013-05-15 11:34:50 +0100
committerTorne (Richard Coles) <torne@google.com>2013-05-15 11:34:50 +0100
commita93a17c8d99d686bd4a1511e5504e5e6cc9fcadf (patch)
tree2fc96923f36ddec68fee218d79dd407c28fa46f8 /apps
parent770489ea635fbf896c1ace4db0d08d6981a2db8b (diff)
downloadchromium_org-a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf.tar.gz
Merge from Chromium at DEPS revision r200144
This commit was generated by merge_to_master.py. Change-Id: I85f3a249ae157fd8253431215fb2dfcd12ee9bf3
Diffstat (limited to 'apps')
-rw-r--r--apps/app_shim/app_shim_handler_mac.cc70
-rw-r--r--apps/app_shim/app_shim_handler_mac.h54
-rw-r--r--apps/app_shim/app_shim_host_mac.cc41
-rw-r--r--apps/app_shim/app_shim_host_mac.h12
-rw-r--r--apps/app_shim/app_shim_host_mac_unittest.cc71
-rw-r--r--apps/apps.gypi2
6 files changed, 225 insertions, 25 deletions
diff --git a/apps/app_shim/app_shim_handler_mac.cc b/apps/app_shim/app_shim_handler_mac.cc
new file mode 100644
index 0000000000..18cca92426
--- /dev/null
+++ b/apps/app_shim/app_shim_handler_mac.cc
@@ -0,0 +1,70 @@
+// 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/logging.h"
+#include "base/memory/singleton.h"
+
+namespace apps {
+
+namespace {
+
+class AppShimHandlerRegistry {
+ 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 NULL;
+ }
+
+ 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;
+ }
+
+ private:
+ friend struct DefaultSingletonTraits<AppShimHandlerRegistry>;
+ typedef std::map<std::string, AppShimHandler*> HandlerMap;
+
+ AppShimHandlerRegistry() {}
+ ~AppShimHandlerRegistry() {}
+
+ HandlerMap handlers_;
+
+ 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);
+}
+
+} // namespace apps
diff --git a/apps/app_shim/app_shim_handler_mac.h b/apps/app_shim/app_shim_handler_mac.h
new file mode 100644
index 0000000000..6a694c0a0a
--- /dev/null
+++ b/apps/app_shim/app_shim_handler_mac.h
@@ -0,0 +1,54 @@
+// 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>
+
+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 closed in the browser process.
+ virtual void OnAppClosed() = 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|, or NULL if none
+ // is registered.
+ static AppShimHandler* GetForAppMode(const std::string& app_mode_id);
+
+ // Invoked by the shim host when the shim process is launched. The handler
+ // must return true if successful, or false to indicate back to the shim
+ // process that it should close.
+ virtual bool OnShimLaunch(Host* host) = 0;
+
+ // 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.
+ virtual void OnShimFocus(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
index b2d577f3d5..bfe28f9ac4 100644
--- a/apps/app_shim/app_shim_host_mac.cc
+++ b/apps/app_shim/app_shim_host_mac.cc
@@ -4,6 +4,7 @@
#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"
@@ -26,6 +27,9 @@ AppShimHost::AppShimHost()
AppShimHost::~AppShimHost() {
DCHECK(CalledOnValidThread());
+ apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
+ if (handler)
+ handler->OnShimClose(this);
}
void AppShimHost::ServeChannel(const IPC::ChannelHandle& handle) {
@@ -47,6 +51,10 @@ bool AppShimHost::OnMessageReceived(const IPC::Message& message) {
return handled;
}
+void AppShimHost::OnChannelError() {
+ Close();
+}
+
bool AppShimHost::Send(IPC::Message* message) {
DCHECK(channel_.get());
return channel_->Send(message);
@@ -54,12 +62,21 @@ bool AppShimHost::Send(IPC::Message* message) {
void AppShimHost::OnLaunchApp(std::string profile_dir, std::string app_id) {
DCHECK(CalledOnValidThread());
- bool success = LaunchAppImpl(profile_dir, app_id);
+ app_id_ = app_id;
+ apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
+ bool success =
+ handler ? handler->OnShimLaunch(this) : LaunchAppImpl(profile_dir);
Send(new AppShimMsg_LaunchApp_Done(success));
}
void AppShimHost::OnFocus() {
DCHECK(CalledOnValidThread());
+ apps::AppShimHandler* handler = apps::AppShimHandler::GetForAppMode(app_id_);
+ if (handler) {
+ handler->OnShimFocus(this);
+ return;
+ }
+
if (!profile_)
return;
extensions::ShellWindowRegistry* registry =
@@ -75,14 +92,13 @@ void AppShimHost::OnFocus() {
ui::FocusWindowSet(native_windows);
}
-bool AppShimHost::LaunchAppImpl(const std::string& profile_dir,
- const std::string& app_id) {
+bool AppShimHost::LaunchAppImpl(const std::string& profile_dir) {
DCHECK(CalledOnValidThread());
if (profile_) {
// Only one app launch message per channel.
return false;
}
- if (!extensions::Extension::IdIsValid(app_id)) {
+ if (!extensions::Extension::IdIsValid(app_id_)) {
LOG(ERROR) << "Bad app ID from app shim launch message.";
return false;
}
@@ -90,12 +106,10 @@ bool AppShimHost::LaunchAppImpl(const std::string& profile_dir,
if (!profile)
return false;
- if (!LaunchApp(profile, app_id))
+ if (!LaunchApp(profile))
return false;
profile_ = profile;
- app_id_ = app_id;
-
registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
content::Source<Profile>(profile_));
return true;
@@ -112,7 +126,8 @@ Profile* AppShimHost::FetchProfileForDirectory(const std::string& profile_dir) {
// This ensures that the given profile path is acutally a profile that we
// already know about.
if (cache.GetIndexOfProfileWithPath(path) == std::string::npos) {
- LOG(ERROR) << "Requested directory is not a known profile.";
+ LOG(ERROR) << "Requested directory is not a known profile '"
+ << profile_dir << "'.";
return NULL;
}
Profile* profile = profileManager->GetProfile(path);
@@ -123,17 +138,17 @@ Profile* AppShimHost::FetchProfileForDirectory(const std::string& profile_dir) {
return profile;
}
-bool AppShimHost::LaunchApp(Profile* profile, const std::string& app_id) {
+bool AppShimHost::LaunchApp(Profile* profile) {
extensions::ExtensionSystem* extension_system =
extensions::ExtensionSystem::Get(profile);
ExtensionServiceInterface* extension_service =
extension_system->extension_service();
const extensions::Extension* extension =
extension_service->GetExtensionById(
- app_id, false);
+ app_id_, false);
if (!extension) {
LOG(ERROR) << "Attempted to launch nonexistent app with id '"
- << app_id << "'.";
+ << app_id_ << "'.";
return false;
}
// TODO(jeremya): Handle the case that launching the app fails. Probably we
@@ -167,6 +182,10 @@ void AppShimHost::Observe(int type,
}
}
+void AppShimHost::OnAppClosed() {
+ Close();
+}
+
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
index fbfd0fa257..438832ce22 100644
--- a/apps/app_shim/app_shim_host_mac.h
+++ b/apps/app_shim/app_shim_host_mac.h
@@ -7,6 +7,7 @@
#include <string>
+#include "apps/app_shim/app_shim_handler_mac.h"
#include "base/memory/scoped_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "content/public/browser/notification_observer.h"
@@ -28,6 +29,7 @@ class Message;
// connected to the app shim is closed.
class AppShimHost : public IPC::Listener,
public IPC::Sender,
+ public apps::AppShimHandler::Host,
public content::NotificationObserver,
public base::NonThreadSafe {
public:
@@ -39,16 +41,17 @@ class AppShimHost : public IPC::Listener,
// listening for messages on it.
void ServeChannel(const IPC::ChannelHandle& handle);
+ protected:
const std::string& app_id() const { return app_id_; }
const Profile* profile() const { return profile_; }
- protected:
// Used internally; virtual so they can be mocked for testing.
virtual Profile* FetchProfileForDirectory(const std::string& profile_dir);
- virtual bool LaunchApp(Profile* profile, const std::string& app_id);
+ virtual bool LaunchApp(Profile* profile);
// 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;
@@ -65,7 +68,7 @@ class AppShimHost : public IPC::Listener,
// Cmd+Tabbed to it.)
void OnFocus();
- bool LaunchAppImpl(const std::string& profile_dir, const std::string& app_id);
+ bool LaunchAppImpl(const std::string& profile_dir);
// The AppShimHost listens to the NOTIFICATION_EXTENSION_HOST_DESTROYED
// message to detect when the app closes. When that happens, the AppShimHost
@@ -74,6 +77,9 @@ class AppShimHost : public IPC::Listener,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
+ // apps::AppShimHandler::Host override:
+ virtual void OnAppClosed() OVERRIDE;
+
// Closes the channel and destroys the AppShimHost.
void Close();
diff --git a/apps/app_shim/app_shim_host_mac_unittest.cc b/apps/app_shim/app_shim_host_mac_unittest.cc
index 802c8e917f..476b2ceb43 100644
--- a/apps/app_shim/app_shim_host_mac_unittest.cc
+++ b/apps/app_shim/app_shim_host_mac_unittest.cc
@@ -10,6 +10,8 @@
#include "ipc/ipc_message.h"
#include "testing/gtest/include/gtest/gtest.h"
+namespace {
+
class TestingAppShimHost : public AppShimHost {
public:
explicit TestingAppShimHost(Profile* profile);
@@ -29,13 +31,21 @@ class TestingAppShimHost : public AppShimHost {
fails_launch_ = fails_launch;
}
+ const std::string& GetAppId() const {
+ return app_id();
+ }
+
+ const Profile* GetProfile() const {
+ return profile();
+ }
+
protected:
virtual Profile* FetchProfileForDirectory(const std::string& profile_dir)
OVERRIDE;
- virtual bool LaunchApp(Profile* profile, const std::string& app_id) OVERRIDE;
-
+ virtual bool LaunchApp(Profile* profile) OVERRIDE;
virtual bool Send(IPC::Message* message) OVERRIDE;
+ private:
Profile* test_profile_;
bool fails_profile_;
bool fails_launch_;
@@ -67,13 +77,15 @@ Profile* TestingAppShimHost::FetchProfileForDirectory(
return fails_profile_ ? NULL : test_profile_;
}
-bool TestingAppShimHost::LaunchApp(
- Profile* profile, const std::string& app_id) {
+bool TestingAppShimHost::LaunchApp(Profile* profile) {
return !fails_launch_;
}
-class AppShimHostTest : public testing::Test {
+class AppShimHostTest : public testing::Test,
+ public apps::AppShimHandler {
public:
+ AppShimHostTest() : launch_count_(0), close_count_(0), focus_count_(0) {}
+
TestingAppShimHost* host() { return host_.get(); }
TestingProfile* profile() { return profile_.get(); }
@@ -86,6 +98,23 @@ class AppShimHostTest : public testing::Test {
return param.a;
}
+ void SimulateDisconnect() {
+ implicit_cast<IPC::Listener*>(host_.release())->OnChannelError();
+ }
+
+ protected:
+ virtual bool OnShimLaunch(Host* host) OVERRIDE {
+ ++launch_count_;
+ return true;
+ }
+
+ virtual void OnShimClose(Host* host) OVERRIDE { ++close_count_; }
+ virtual void OnShimFocus(Host* host) OVERRIDE { ++focus_count_; }
+
+ int launch_count_;
+ int close_count_;
+ int focus_count_;
+
private:
virtual void SetUp() OVERRIDE {
profile_.reset(new TestingProfile);
@@ -94,24 +123,45 @@ class AppShimHostTest : public testing::Test {
scoped_ptr<TestingAppShimHost> host_;
scoped_ptr<TestingProfile> profile_;
+
+ DISALLOW_COPY_AND_ASSIGN(AppShimHostTest);
};
-static const std::string kTestAppId = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
-static const std::string kTestProfileDir = "Default";
+const char kTestAppId[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+const char kTestProfileDir[] = "Default";
+
+} // namespace
TEST_F(AppShimHostTest, TestLaunchApp) {
host()->ReceiveMessage(
new AppShimHostMsg_LaunchApp(kTestProfileDir, kTestAppId));
- ASSERT_EQ(kTestAppId, host()->app_id());
- ASSERT_EQ(profile(), host()->profile());
+ ASSERT_EQ(kTestAppId, host()->GetAppId());
+ ASSERT_EQ(profile(), host()->GetProfile());
ASSERT_TRUE(LaunchWasSuccessful());
}
+TEST_F(AppShimHostTest, TestLaunchAppWithHandler) {
+ apps::AppShimHandler::RegisterHandler(kTestAppId, this);
+ EXPECT_TRUE(host()->ReceiveMessage(
+ new AppShimHostMsg_LaunchApp(kTestProfileDir, kTestAppId)));
+ EXPECT_EQ(kTestAppId, host()->GetAppId());
+ EXPECT_TRUE(LaunchWasSuccessful());
+ EXPECT_EQ(1, launch_count_);
+ EXPECT_EQ(0, focus_count_);
+ EXPECT_EQ(0, close_count_);
+
+ EXPECT_TRUE(host()->ReceiveMessage(new AppShimHostMsg_FocusApp()));
+ EXPECT_EQ(1, focus_count_);
+
+ SimulateDisconnect();
+ EXPECT_EQ(1, close_count_);
+ apps::AppShimHandler::RemoveHandler(kTestAppId);
+}
+
TEST_F(AppShimHostTest, TestFailProfile) {
host()->set_fails_profile(true);
host()->ReceiveMessage(
new AppShimHostMsg_LaunchApp(kTestProfileDir, kTestAppId));
- ASSERT_TRUE(host()->app_id().empty());
ASSERT_FALSE(LaunchWasSuccessful());
}
@@ -119,6 +169,5 @@ TEST_F(AppShimHostTest, TestFailLaunch) {
host()->set_fails_launch(true);
host()->ReceiveMessage(
new AppShimHostMsg_LaunchApp(kTestProfileDir, kTestAppId));
- ASSERT_TRUE(host()->app_id().empty());
ASSERT_FALSE(LaunchWasSuccessful());
}
diff --git a/apps/apps.gypi b/apps/apps.gypi
index 5553a51f74..4867f73349 100644
--- a/apps/apps.gypi
+++ b/apps/apps.gypi
@@ -30,6 +30,8 @@
'app_restore_service.h',
'app_restore_service_factory.cc',
'app_restore_service_factory.h',
+ 'app_shim/app_shim_handler_mac.cc',
+ 'app_shim/app_shim_handler_mac.h',
'app_shim/app_shim_host_mac.cc',
'app_shim/app_shim_host_mac.h',
'app_shim/app_shim_host_manager_mac.h',