summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authormvanouwerkerk <mvanouwerkerk@chromium.org>2015-07-28 04:07:21 -0700
committerCommit bot <commit-bot@chromium.org>2015-07-28 11:08:22 +0000
commit807bd3387a67e6a07f841de88976131818c07a34 (patch)
tree9eab8b8bac538af39b845a52414326d7a512536e /chrome
parentd200aa5aa473831ffd7fa0ab903a9dafc9c28efc (diff)
downloadchromium_src-807bd3387a67e6a07f841de88976131818c07a34.zip
chromium_src-807bd3387a67e6a07f841de88976131818c07a34.tar.gz
chromium_src-807bd3387a67e6a07f841de88976131818c07a34.tar.bz2
Use ServiceIPCServer::MessageHandler in CloudPrintMessageHandler.
* Moves cloud print IPC message handling from ServiceIPCServer to CloudPrintMessageHandler * Removes the last 4 uses of g_service_process from ServiceIPCServer. * Add unit test for ServiceIPCServer BUG=402456 Review URL: https://codereview.chromium.org/1249513003 Cr-Commit-Position: refs/heads/master@{#340664}
Diffstat (limited to 'chrome')
-rw-r--r--chrome/chrome.gyp2
-rw-r--r--chrome/chrome_tests_unit.gypi1
-rw-r--r--chrome/service/BUILD.gn2
-rw-r--r--chrome/service/cloud_print/cloud_print_message_handler.cc65
-rw-r--r--chrome/service/cloud_print/cloud_print_message_handler.h54
-rw-r--r--chrome/service/cloud_print/cloud_print_proxy.h6
-rw-r--r--chrome/service/service_ipc_server.cc50
-rw-r--r--chrome/service/service_ipc_server.h27
-rw-r--r--chrome/service/service_ipc_server_unittest.cc263
-rw-r--r--chrome/service/service_process.cc5
-rw-r--r--chrome/service/service_process.h10
11 files changed, 434 insertions, 51 deletions
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 6a8a870..f0a1c64 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -741,6 +741,8 @@
'service/cloud_print/cloud_print_auth.h',
'service/cloud_print/cloud_print_connector.cc',
'service/cloud_print/cloud_print_connector.h',
+ 'service/cloud_print/cloud_print_message_handler.cc',
+ 'service/cloud_print/cloud_print_message_handler.h',
'service/cloud_print/cloud_print_proxy.cc',
'service/cloud_print/cloud_print_proxy.h',
'service/cloud_print/cloud_print_proxy_backend.cc',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index 741c181..3a42dce 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -1093,6 +1093,7 @@
'service/cloud_print/connector_settings_unittest.cc',
'service/cloud_print/printer_job_handler_unittest.cc',
'service/cloud_print/printer_job_queue_handler_unittest.cc',
+ 'service/service_ipc_server_unittest.cc',
'service/service_process_prefs_unittest.cc',
],
'chrome_unit_tests_captive_portal_sources': [
diff --git a/chrome/service/BUILD.gn b/chrome/service/BUILD.gn
index fe26068..99960b3 100644
--- a/chrome/service/BUILD.gn
+++ b/chrome/service/BUILD.gn
@@ -12,6 +12,8 @@ static_library("service") {
"cloud_print/cloud_print_auth.h",
"cloud_print/cloud_print_connector.cc",
"cloud_print/cloud_print_connector.h",
+ "cloud_print/cloud_print_message_handler.cc",
+ "cloud_print/cloud_print_message_handler.h",
"cloud_print/cloud_print_proxy.cc",
"cloud_print/cloud_print_proxy.h",
"cloud_print/cloud_print_proxy_backend.cc",
diff --git a/chrome/service/cloud_print/cloud_print_message_handler.cc b/chrome/service/cloud_print/cloud_print_message_handler.cc
new file mode 100644
index 0000000..babcad7
--- /dev/null
+++ b/chrome/service/cloud_print/cloud_print_message_handler.cc
@@ -0,0 +1,65 @@
+// Copyright 2015 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 "chrome/service/cloud_print/cloud_print_message_handler.h"
+
+#include <vector>
+
+#include "chrome/common/service_messages.h"
+#include "ipc/ipc_sender.h"
+
+namespace cloud_print {
+
+CloudPrintMessageHandler::CloudPrintMessageHandler(
+ IPC::Sender* ipc_sender,
+ CloudPrintProxy::Provider* proxy_provider)
+ : ipc_sender_(ipc_sender), proxy_provider_(proxy_provider) {
+ DCHECK(ipc_sender);
+ DCHECK(proxy_provider);
+}
+
+CloudPrintMessageHandler::~CloudPrintMessageHandler() {
+}
+
+bool CloudPrintMessageHandler::HandleMessage(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(CloudPrintMessageHandler, message)
+ IPC_MESSAGE_HANDLER(ServiceMsg_EnableCloudPrintProxyWithRobot,
+ OnEnableCloudPrintProxyWithRobot)
+ IPC_MESSAGE_HANDLER(ServiceMsg_DisableCloudPrintProxy,
+ OnDisableCloudPrintProxy)
+ IPC_MESSAGE_HANDLER(ServiceMsg_GetCloudPrintProxyInfo,
+ OnGetCloudPrintProxyInfo)
+ IPC_MESSAGE_HANDLER(ServiceMsg_GetPrinters, OnGetPrinters)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void CloudPrintMessageHandler::OnEnableCloudPrintProxyWithRobot(
+ const std::string& robot_auth_code,
+ const std::string& robot_email,
+ const std::string& user_email,
+ const base::DictionaryValue& user_settings) {
+ proxy_provider_->GetCloudPrintProxy()->EnableForUserWithRobot(
+ robot_auth_code, robot_email, user_email, user_settings);
+}
+
+void CloudPrintMessageHandler::OnGetCloudPrintProxyInfo() {
+ CloudPrintProxyInfo info;
+ proxy_provider_->GetCloudPrintProxy()->GetProxyInfo(&info);
+ ipc_sender_->Send(new ServiceHostMsg_CloudPrintProxy_Info(info));
+}
+
+void CloudPrintMessageHandler::OnGetPrinters() {
+ std::vector<std::string> printers;
+ proxy_provider_->GetCloudPrintProxy()->GetPrinters(&printers);
+ ipc_sender_->Send(new ServiceHostMsg_Printers(printers));
+}
+
+void CloudPrintMessageHandler::OnDisableCloudPrintProxy() {
+ proxy_provider_->GetCloudPrintProxy()->UnregisterPrintersAndDisableForUser();
+}
+
+} // namespace cloud_print
diff --git a/chrome/service/cloud_print/cloud_print_message_handler.h b/chrome/service/cloud_print/cloud_print_message_handler.h
new file mode 100644
index 0000000..1a1cb13
--- /dev/null
+++ b/chrome/service/cloud_print/cloud_print_message_handler.h
@@ -0,0 +1,54 @@
+// Copyright 2015 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 CHROME_SERVICE_CLOUD_PRINT_CLOUD_PRINT_MESSAGE_HANDLER_H_
+#define CHROME_SERVICE_CLOUD_PRINT_CLOUD_PRINT_MESSAGE_HANDLER_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "chrome/service/cloud_print/cloud_print_proxy.h"
+#include "chrome/service/service_ipc_server.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace IPC {
+class Message;
+class Sender;
+}
+
+namespace cloud_print {
+
+// Handles IPC messages for Cloud Print. Lives on the main thread.
+class CloudPrintMessageHandler : public ServiceIPCServer::MessageHandler {
+ public:
+ CloudPrintMessageHandler(IPC::Sender* ipc_sender,
+ CloudPrintProxy::Provider* proxy_provider);
+ ~CloudPrintMessageHandler() override;
+
+ // ServiceIPCServer::MessageHandler implementation.
+ bool HandleMessage(const IPC::Message& message) override;
+
+ private:
+ // IPC message handlers.
+ void OnEnableCloudPrintProxyWithRobot(
+ const std::string& robot_auth_code,
+ const std::string& robot_email,
+ const std::string& user_email,
+ const base::DictionaryValue& user_settings);
+ void OnGetCloudPrintProxyInfo();
+ void OnGetPrinters();
+ void OnDisableCloudPrintProxy();
+
+ IPC::Sender* ipc_sender_; // Owned by our owner.
+ CloudPrintProxy::Provider* proxy_provider_; // Owned by our owner.
+
+ DISALLOW_COPY_AND_ASSIGN(CloudPrintMessageHandler);
+};
+
+} // namespace cloud_print
+
+#endif // CHROME_SERVICE_CLOUD_PRINT_CLOUD_PRINT_MESSAGE_HANDLER_H_
diff --git a/chrome/service/cloud_print/cloud_print_proxy.h b/chrome/service/cloud_print/cloud_print_proxy.h
index 8df887b..d25d4fd 100644
--- a/chrome/service/cloud_print/cloud_print_proxy.h
+++ b/chrome/service/cloud_print/cloud_print_proxy.h
@@ -36,6 +36,12 @@ class CloudPrintProxy : public CloudPrintProxyFrontend,
CloudPrintProxy();
~CloudPrintProxy() override;
+ // Provides a CloudPrintProxy instance, which may be lazily instantiated.
+ class Provider {
+ public:
+ virtual CloudPrintProxy* GetCloudPrintProxy() = 0;
+ };
+
// Initializes the object. This should be called every time an object of this
// class is constructed.
void Initialize(ServiceProcessPrefs* service_prefs, Client* client);
diff --git a/chrome/service/service_ipc_server.cc b/chrome/service/service_ipc_server.cc
index 59a5908..6bd7a73 100644
--- a/chrome/service/service_ipc_server.cc
+++ b/chrome/service/service_ipc_server.cc
@@ -6,8 +6,6 @@
#include "base/metrics/histogram_delta_serialization.h"
#include "chrome/common/service_messages.h"
-#include "chrome/service/cloud_print/cloud_print_proxy.h"
-#include "chrome/service/service_process.h"
#include "ipc/ipc_logging.h"
ServiceIPCServer::ServiceIPCServer(
@@ -87,6 +85,10 @@ bool ServiceIPCServer::Send(IPC::Message* msg) {
return channel_->Send(msg);
}
+void ServiceIPCServer::AddMessageHandler(scoped_ptr<MessageHandler> handler) {
+ message_handlers_.push_back(handler.release());
+}
+
bool ServiceIPCServer::OnMessageReceived(const IPC::Message& msg) {
bool handled = true;
// When we get a message, always mark the IPC client as connected. The
@@ -95,34 +97,23 @@ bool ServiceIPCServer::OnMessageReceived(const IPC::Message& msg) {
// again on subsequent connections.
ipc_client_connected_ = true;
IPC_BEGIN_MESSAGE_MAP(ServiceIPCServer, msg)
- IPC_MESSAGE_HANDLER(ServiceMsg_EnableCloudPrintProxyWithRobot,
- OnEnableCloudPrintProxyWithRobot)
- IPC_MESSAGE_HANDLER(ServiceMsg_DisableCloudPrintProxy,
- OnDisableCloudPrintProxy)
- IPC_MESSAGE_HANDLER(ServiceMsg_GetCloudPrintProxyInfo,
- OnGetCloudPrintProxyInfo)
IPC_MESSAGE_HANDLER(ServiceMsg_GetHistograms, OnGetHistograms)
- IPC_MESSAGE_HANDLER(ServiceMsg_GetPrinters, OnGetPrinters)
IPC_MESSAGE_HANDLER(ServiceMsg_Shutdown, OnShutdown);
IPC_MESSAGE_HANDLER(ServiceMsg_UpdateAvailable, OnUpdateAvailable);
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
- return handled;
-}
-void ServiceIPCServer::OnEnableCloudPrintProxyWithRobot(
- const std::string& robot_auth_code,
- const std::string& robot_email,
- const std::string& user_email,
- const base::DictionaryValue& user_settings) {
- g_service_process->GetCloudPrintProxy()->EnableForUserWithRobot(
- robot_auth_code, robot_email, user_email, user_settings);
-}
+ if (!handled) {
+ // Make a copy of the handlers to prevent modification during iteration.
+ std::vector<MessageHandler*> temp_handlers = message_handlers_.get();
+ for (const auto& handler : temp_handlers) {
+ handled = handler->HandleMessage(msg);
+ if (handled)
+ break;
+ }
+ }
-void ServiceIPCServer::OnGetCloudPrintProxyInfo() {
- cloud_print::CloudPrintProxyInfo info;
- g_service_process->GetCloudPrintProxy()->GetProxyInfo(&info);
- channel_->Send(new ServiceHostMsg_CloudPrintProxy_Info(info));
+ return handled;
}
void ServiceIPCServer::OnGetHistograms() {
@@ -135,19 +126,6 @@ void ServiceIPCServer::OnGetHistograms() {
channel_->Send(new ServiceHostMsg_Histograms(deltas));
}
-void ServiceIPCServer::OnGetPrinters() {
- std::vector<std::string> printers;
- g_service_process->GetCloudPrintProxy()->GetPrinters(&printers);
- channel_->Send(new ServiceHostMsg_Printers(printers));
-}
-
-void ServiceIPCServer::OnDisableCloudPrintProxy() {
- // User disabled CloudPrint proxy explicitly. Delete printers
- // registered from this proxy and disable proxy.
- g_service_process->GetCloudPrintProxy()->
- UnregisterPrintersAndDisableForUser();
-}
-
void ServiceIPCServer::OnShutdown() {
client_->OnShutdown();
}
diff --git a/chrome/service/service_ipc_server.h b/chrome/service/service_ipc_server.h
index 878020c..4ad4b72 100644
--- a/chrome/service/service_ipc_server.h
+++ b/chrome/service/service_ipc_server.h
@@ -5,10 +5,10 @@
#ifndef CHROME_SERVICE_SERVICE_IPC_SERVER_H_
#define CHROME_SERVICE_SERVICE_IPC_SERVER_H_
-#include <string>
#include <vector>
#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sync_channel.h"
@@ -16,7 +16,6 @@
namespace base {
-class DictionaryValue;
class HistogramDeltaSerialization;
class WaitableEvent;
@@ -25,6 +24,13 @@ class WaitableEvent;
// This class handles IPC commands for the service process.
class ServiceIPCServer : public IPC::Listener, public IPC::Sender {
public:
+ class MessageHandler {
+ public:
+ virtual ~MessageHandler() {}
+ // Must return true if the message is handled.
+ virtual bool HandleMessage(const IPC::Message& message) = 0;
+ };
+
class Client {
public:
virtual ~Client() {}
@@ -52,9 +58,16 @@ class ServiceIPCServer : public IPC::Listener, public IPC::Sender {
// IPC::Sender implementation.
bool Send(IPC::Message* msg) override;
+ // Registers a MessageHandler with the ServiceIPCServer. When an IPC message
+ // is received that is not handled by the ServiceIPCServer itself, the
+ // handlers will be called to handle the message in first-add first-call order
+ // until it is handled or there are no more handlers.
+ void AddMessageHandler(scoped_ptr<MessageHandler> handler);
+
bool is_ipc_client_connected() const { return ipc_client_connected_; }
private:
+ friend class ServiceIPCServerTest;
friend class MockServiceIPCServer;
// IPC::Listener implementation.
@@ -63,16 +76,7 @@ class ServiceIPCServer : public IPC::Listener, public IPC::Sender {
void OnChannelError() override;
// IPC message handlers.
- void OnEnableCloudPrintProxyWithRobot(
- const std::string& robot_auth_code,
- const std::string& robot_email,
- const std::string& user_email,
- const base::DictionaryValue& user_settings);
- void OnGetCloudPrintProxyInfo();
void OnGetHistograms();
- void OnGetPrinters();
- void OnDisableCloudPrintProxy();
-
void OnShutdown();
void OnUpdateAvailable();
@@ -84,6 +88,7 @@ class ServiceIPCServer : public IPC::Listener, public IPC::Sender {
IPC::ChannelHandle channel_handle_;
scoped_ptr<IPC::SyncChannel> channel_;
base::WaitableEvent* shutdown_event_;
+ ScopedVector<MessageHandler> message_handlers_;
// Indicates whether an IPC client is currently connected to the channel.
bool ipc_client_connected_;
diff --git a/chrome/service/service_ipc_server_unittest.cc b/chrome/service/service_ipc_server_unittest.cc
new file mode 100644
index 0000000..efeea79
--- /dev/null
+++ b/chrome/service/service_ipc_server_unittest.cc
@@ -0,0 +1,263 @@
+// Copyright 2015 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 "chrome/service/service_ipc_server.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "chrome/common/service_messages.h"
+#include "ipc/ipc_channel.h"
+#include "ipc/ipc_channel_handle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+void PumpCurrentLoop() {
+ base::MessageLoop::ScopedNestableTaskAllower nestable_task_allower(
+ base::MessageLoop::current());
+ base::RunLoop().RunUntilIdle();
+}
+
+class FakeServiceIPCServerClient : public ServiceIPCServer::Client {
+ public:
+ FakeServiceIPCServerClient() {}
+ ~FakeServiceIPCServerClient() override {}
+ void OnShutdown() override;
+ void OnUpdateAvailable() override;
+ bool OnIPCClientDisconnect() override;
+
+ int shutdown_calls = 0;
+ int update_available_calls = 0;
+ int ipc_client_disconnect_calls = 0;
+};
+
+void FakeServiceIPCServerClient::OnShutdown() {
+ shutdown_calls++;
+}
+
+void FakeServiceIPCServerClient::OnUpdateAvailable() {
+ update_available_calls++;
+}
+
+bool FakeServiceIPCServerClient::OnIPCClientDisconnect() {
+ ipc_client_disconnect_calls++;
+
+ // Always return true to indicate the server must continue listening for new
+ // connections.
+ return true;
+}
+
+class FakeChannelListener : public IPC::Listener {
+ public:
+ FakeChannelListener() {}
+ ~FakeChannelListener() override {}
+ bool OnMessageReceived(const IPC::Message& message) override { return true; }
+};
+
+class FakeMessageHandler : public ServiceIPCServer::MessageHandler {
+ public:
+ explicit FakeMessageHandler(bool should_handle);
+ bool HandleMessage(const IPC::Message& message) override;
+ bool should_handle_;
+ int handle_message_calls_;
+};
+
+FakeMessageHandler::FakeMessageHandler(bool should_handle)
+ : should_handle_(should_handle), handle_message_calls_(0) {
+}
+
+bool FakeMessageHandler::HandleMessage(const IPC::Message& message) {
+ handle_message_calls_++;
+ return should_handle_;
+}
+
+} // namespace
+
+class ServiceIPCServerTest : public ::testing::Test {
+ public:
+ ServiceIPCServerTest();
+ ~ServiceIPCServerTest() override {}
+ void SetUp() override;
+ void TearDown() override;
+ void PumpLoops();
+
+ // Simulates the browser process connecting to the service process.
+ void ConnectClientChannel();
+
+ // Simulates the browser process shutting down.
+ void DestroyClientChannel();
+
+ // Sends |message| to the ServiceIPCServer.
+ void SendToServiceProcess(IPC::Message* message);
+
+ IPC::SyncChannel* GetServerChannel() {
+ return server_->channel_.get();
+ }
+
+ protected:
+ FakeServiceIPCServerClient service_process_client_;
+ IPC::ChannelHandle channel_handle_;
+ base::MessageLoopForUI main_message_loop_;
+ base::Thread io_thread_;
+ base::WaitableEvent shutdown_event_;
+ scoped_ptr<ServiceIPCServer> server_;
+ FakeChannelListener client_process_channel_listener_;
+ scoped_ptr<IPC::SyncChannel> client_process_channel_;
+};
+
+ServiceIPCServerTest::ServiceIPCServerTest()
+ : channel_handle_(IPC::Channel::GenerateUniqueRandomChannelID()),
+ io_thread_("ServiceIPCServerTest IO"),
+ shutdown_event_(true /* manual_reset */, false /* initially_signaled */) {
+}
+
+void ServiceIPCServerTest::SetUp() {
+ base::Thread::Options options;
+ options.message_loop_type = base::MessageLoop::TYPE_IO;
+ ASSERT_TRUE(io_thread_.StartWithOptions(options));
+
+ server_.reset(new ServiceIPCServer(&service_process_client_,
+ io_thread_.task_runner(),
+ channel_handle_,
+ &shutdown_event_));
+ server_->Init();
+}
+
+void ServiceIPCServerTest::TearDown() {
+ // Close the ipc channels to prevent memory leaks.
+ if (client_process_channel_) {
+ client_process_channel_->Close();
+ PumpLoops();
+ }
+ if (GetServerChannel()) {
+ GetServerChannel()->Close();
+ PumpLoops();
+ }
+ io_thread_.Stop();
+}
+
+void ServiceIPCServerTest::PumpLoops() {
+ base::RunLoop run_loop;
+ io_thread_.task_runner()->PostTaskAndReply(FROM_HERE,
+ base::Bind(&PumpCurrentLoop),
+ run_loop.QuitClosure());
+ run_loop.Run();
+ PumpCurrentLoop();
+}
+
+void ServiceIPCServerTest::ConnectClientChannel() {
+ client_process_channel_ = IPC::SyncChannel::Create(
+ channel_handle_,
+ IPC::Channel::MODE_NAMED_CLIENT,
+ &client_process_channel_listener_,
+ io_thread_.task_runner(),
+ true /* create_pipe_now */,
+ &shutdown_event_);
+ PumpLoops();
+}
+
+void ServiceIPCServerTest::DestroyClientChannel() {
+ client_process_channel_.reset();
+ PumpLoops();
+}
+
+void ServiceIPCServerTest::SendToServiceProcess(IPC::Message* message) {
+ client_process_channel_->Send(message);
+ PumpLoops();
+}
+
+TEST_F(ServiceIPCServerTest, ConnectDisconnectReconnect) {
+ // Initially there is no ipc client connected.
+ ASSERT_FALSE(server_->is_ipc_client_connected());
+
+ // When a channel is connected the server is notified via OnChannelConnected.
+ ConnectClientChannel();
+ ASSERT_TRUE(server_->is_ipc_client_connected());
+
+ // When the channel is destroyed the server is notified via OnChannelError.
+ // In turn, the server notifies its service process client.
+ DestroyClientChannel();
+ ASSERT_FALSE(server_->is_ipc_client_connected());
+ ASSERT_EQ(1, service_process_client_.ipc_client_disconnect_calls);
+
+ // On Windows only, the server recreates its channel in OnChannelError, if the
+ // service process client tells it to continue listening. On other platforms
+ // the channel is reused for subsequent reconnects by the client process. This
+ // means however that OnChannelConnected is not called again and the server is
+ // only aware of being connected once an IPC message is received.
+ ConnectClientChannel();
+#if defined(OS_WIN)
+ ASSERT_TRUE(server_->is_ipc_client_connected());
+#else
+ ASSERT_FALSE(server_->is_ipc_client_connected());
+#endif
+ SendToServiceProcess(new ServiceMsg_UpdateAvailable());
+ ASSERT_TRUE(server_->is_ipc_client_connected());
+
+ // Destroy the client process channel again to verify the
+ // ServiceIPCServer::Client is notified again. This means that unlike
+ // OnChannelConnected, OnChannelError is called more than once.
+ DestroyClientChannel();
+ ASSERT_FALSE(server_->is_ipc_client_connected());
+ ASSERT_EQ(2, service_process_client_.ipc_client_disconnect_calls);
+}
+
+TEST_F(ServiceIPCServerTest, Shutdown) {
+ ConnectClientChannel();
+ ASSERT_TRUE(server_->is_ipc_client_connected());
+
+ // When a shutdown message is received, the ServiceIPCServer::Client is
+ // notified.
+ SendToServiceProcess(new ServiceMsg_Shutdown());
+ ASSERT_EQ(1, service_process_client_.shutdown_calls);
+}
+
+TEST_F(ServiceIPCServerTest, UpdateAvailable) {
+ ConnectClientChannel();
+ ASSERT_TRUE(server_->is_ipc_client_connected());
+
+ // When a product update message is received, the ServiceIPCServer::Client is
+ // notified.
+ SendToServiceProcess(new ServiceMsg_UpdateAvailable());
+ ASSERT_EQ(1, service_process_client_.update_available_calls);
+}
+
+TEST_F(ServiceIPCServerTest, SingleMessageHandler) {
+ ConnectClientChannel();
+ ASSERT_TRUE(server_->is_ipc_client_connected());
+
+ // Verify that a message handler is offered messages not handled by the server
+ // itself.
+ FakeMessageHandler* handler =
+ new FakeMessageHandler(true /* should_handle */);
+ server_->AddMessageHandler(make_scoped_ptr(handler));
+ SendToServiceProcess(new ServiceMsg_DisableCloudPrintProxy());
+ ASSERT_EQ(1, handler->handle_message_calls_);
+}
+
+TEST_F(ServiceIPCServerTest, MultipleMessageHandlers) {
+ ConnectClientChannel();
+ ASSERT_TRUE(server_->is_ipc_client_connected());
+
+ // If there are multiple handlers they are offered the message in order of
+ // being added until it is handled.
+ FakeMessageHandler* handler1 =
+ new FakeMessageHandler(false /* should_handle */);
+ server_->AddMessageHandler(make_scoped_ptr(handler1));
+ FakeMessageHandler* handler2 =
+ new FakeMessageHandler(true /* should_handle */);
+ server_->AddMessageHandler(make_scoped_ptr(handler2));
+ FakeMessageHandler* handler3 =
+ new FakeMessageHandler(true /* should_handle */);
+ server_->AddMessageHandler(make_scoped_ptr(handler3));
+ SendToServiceProcess(new ServiceMsg_DisableCloudPrintProxy());
+ ASSERT_EQ(1, handler1->handle_message_calls_);
+ ASSERT_EQ(1, handler2->handle_message_calls_);
+ ASSERT_EQ(0, handler3->handle_message_calls_);
+}
diff --git a/chrome/service/service_process.cc b/chrome/service/service_process.cc
index 3ba883f..6b126c5a6 100644
--- a/chrome/service/service_process.cc
+++ b/chrome/service/service_process.cc
@@ -18,7 +18,9 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/synchronization/waitable_event.h"
#include "base/thread_task_runner_handle.h"
+#include "base/threading/sequenced_worker_pool.h"
#include "base/values.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
@@ -28,6 +30,7 @@
#include "chrome/common/service_process_util.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
+#include "chrome/service/cloud_print/cloud_print_message_handler.h"
#include "chrome/service/cloud_print/cloud_print_proxy.h"
#include "chrome/service/net/service_url_request_context_getter.h"
#include "chrome/service/service_process_prefs.h"
@@ -193,6 +196,8 @@ bool ServiceProcess::Initialize(base::MessageLoopForUI* message_loop,
io_task_runner(),
service_process_state_->GetServiceProcessChannel(),
&shutdown_event_));
+ ipc_server_->AddMessageHandler(make_scoped_ptr(
+ new cloud_print::CloudPrintMessageHandler(ipc_server_.get(), this)));
ipc_server_->Init();
// After the IPC server has started we signal that the service process is
diff --git a/chrome/service/service_process.h b/chrome/service/service_process.h
index 13f1518..0c398ca 100644
--- a/chrome/service/service_process.h
+++ b/chrome/service/service_process.h
@@ -10,9 +10,7 @@
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread.h"
-#include "base/synchronization/waitable_event.h"
#include "chrome/service/cloud_print/cloud_print_proxy.h"
#include "chrome/service/service_ipc_server.h"
@@ -22,6 +20,8 @@ class ServiceProcessState;
namespace base {
class CommandLine;
+class SequencedWorkerPool;
+class WaitableEvent;
}
namespace net {
@@ -33,7 +33,8 @@ class NetworkChangeNotifier;
// ServiceProcess Design Notes
// https://sites.google.com/a/chromium.org/dev/developers/design-documents/service-processes
class ServiceProcess : public ServiceIPCServer::Client,
- public cloud_print::CloudPrintProxy::Client {
+ public cloud_print::CloudPrintProxy::Client,
+ public cloud_print::CloudPrintProxy::Provider {
public:
ServiceProcess();
~ServiceProcess() override;
@@ -76,7 +77,8 @@ class ServiceProcess : public ServiceIPCServer::Client,
void OnUpdateAvailable() override;
bool OnIPCClientDisconnect() override;
- cloud_print::CloudPrintProxy* GetCloudPrintProxy();
+ // CloudPrintProxy::Provider implementation.
+ cloud_print::CloudPrintProxy* GetCloudPrintProxy() override;
// CloudPrintProxy::Client implementation.
void OnCloudPrintProxyEnabled(bool persist_state) override;