diff options
author | mvanouwerkerk <mvanouwerkerk@chromium.org> | 2015-07-28 04:07:21 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-07-28 11:08:22 +0000 |
commit | 807bd3387a67e6a07f841de88976131818c07a34 (patch) | |
tree | 9eab8b8bac538af39b845a52414326d7a512536e /chrome | |
parent | d200aa5aa473831ffd7fa0ab903a9dafc9c28efc (diff) | |
download | chromium_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.gyp | 2 | ||||
-rw-r--r-- | chrome/chrome_tests_unit.gypi | 1 | ||||
-rw-r--r-- | chrome/service/BUILD.gn | 2 | ||||
-rw-r--r-- | chrome/service/cloud_print/cloud_print_message_handler.cc | 65 | ||||
-rw-r--r-- | chrome/service/cloud_print/cloud_print_message_handler.h | 54 | ||||
-rw-r--r-- | chrome/service/cloud_print/cloud_print_proxy.h | 6 | ||||
-rw-r--r-- | chrome/service/service_ipc_server.cc | 50 | ||||
-rw-r--r-- | chrome/service/service_ipc_server.h | 27 | ||||
-rw-r--r-- | chrome/service/service_ipc_server_unittest.cc | 263 | ||||
-rw-r--r-- | chrome/service/service_process.cc | 5 | ||||
-rw-r--r-- | chrome/service/service_process.h | 10 |
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; |