Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/service/service_ipc_server.h" | 5 #include "chrome/service/service_ipc_server.h" |
| 6 | 6 |
| 7 #include <utility> | |
| 8 | |
| 7 #include "base/bind.h" | 9 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 9 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
| 10 #include "base/message_loop/message_loop.h" | 12 #include "base/message_loop/message_loop.h" |
| 11 #include "base/run_loop.h" | 13 #include "base/run_loop.h" |
| 12 #include "base/single_thread_task_runner.h" | 14 #include "base/single_thread_task_runner.h" |
| 13 #include "base/synchronization/waitable_event.h" | 15 #include "base/synchronization/waitable_event.h" |
| 14 #include "base/threading/thread.h" | 16 #include "base/threading/thread.h" |
| 15 #include "build/build_config.h" | 17 #include "build/build_config.h" |
| 16 #include "chrome/common/service_messages.h" | 18 #include "chrome/common/service_messages.h" |
| 17 #include "ipc/ipc_channel.h" | 19 #include "ipc/ipc_channel.h" |
| 18 #include "ipc/ipc_channel_handle.h" | 20 #include "ipc/ipc_channel_handle.h" |
| 21 #include "ipc/ipc_channel_mojo.h" | |
| 22 #include "mojo/public/cpp/system/message_pipe.h" | |
| 19 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
| 20 | 24 |
| 21 namespace { | 25 namespace { |
| 22 | 26 |
| 23 void PumpCurrentLoop() { | 27 void PumpCurrentLoop() { |
| 24 base::MessageLoop::ScopedNestableTaskAllower nestable_task_allower( | 28 base::MessageLoop::ScopedNestableTaskAllower nestable_task_allower( |
| 25 base::MessageLoop::current()); | 29 base::MessageLoop::current()); |
| 26 base::RunLoop().RunUntilIdle(); | 30 base::RunLoop().RunUntilIdle(); |
| 27 } | 31 } |
| 28 | 32 |
| 29 class FakeServiceIPCServerClient : public ServiceIPCServer::Client { | 33 class FakeServiceIPCServerClient : public ServiceIPCServer::Client { |
| 30 public: | 34 public: |
| 31 FakeServiceIPCServerClient() {} | 35 FakeServiceIPCServerClient() {} |
| 32 ~FakeServiceIPCServerClient() override {} | 36 ~FakeServiceIPCServerClient() override {} |
| 33 void OnShutdown() override; | 37 void OnShutdown() override; |
| 34 void OnUpdateAvailable() override; | 38 void OnUpdateAvailable() override; |
| 39 void OnStayAliveForTesting() override; | |
| 35 bool OnIPCClientDisconnect() override; | 40 bool OnIPCClientDisconnect() override; |
| 41 mojo::ScopedMessagePipeHandle CreateChannelMessagePipe() override; | |
| 36 | 42 |
| 37 int shutdown_calls = 0; | 43 int shutdown_calls = 0; |
| 38 int update_available_calls = 0; | 44 int update_available_calls = 0; |
| 39 int ipc_client_disconnect_calls = 0; | 45 int ipc_client_disconnect_calls = 0; |
| 46 mojo::ScopedMessagePipeHandle channel_handle; | |
|
Lei Zhang
2016/09/01 06:12:01
channel_handle_ ? Fix the over variables if you'd
Sam McNally
2016/09/01 06:58:45
Done.
| |
| 40 }; | 47 }; |
| 41 | 48 |
| 42 void FakeServiceIPCServerClient::OnShutdown() { | 49 void FakeServiceIPCServerClient::OnShutdown() { |
| 43 shutdown_calls++; | 50 shutdown_calls++; |
| 44 } | 51 } |
| 45 | 52 |
| 46 void FakeServiceIPCServerClient::OnUpdateAvailable() { | 53 void FakeServiceIPCServerClient::OnUpdateAvailable() { |
| 47 update_available_calls++; | 54 update_available_calls++; |
| 48 } | 55 } |
| 49 | 56 |
| 57 void FakeServiceIPCServerClient::OnStayAliveForTesting() {} | |
| 58 | |
| 50 bool FakeServiceIPCServerClient::OnIPCClientDisconnect() { | 59 bool FakeServiceIPCServerClient::OnIPCClientDisconnect() { |
| 51 ipc_client_disconnect_calls++; | 60 ipc_client_disconnect_calls++; |
| 52 | 61 |
| 53 // Always return true to indicate the server must continue listening for new | 62 // Always return true to indicate the server must continue listening for new |
| 54 // connections. | 63 // connections. |
| 55 return true; | 64 return true; |
| 56 } | 65 } |
| 57 | 66 |
| 67 mojo::ScopedMessagePipeHandle | |
| 68 FakeServiceIPCServerClient::CreateChannelMessagePipe() { | |
| 69 mojo::MessagePipe channel; | |
| 70 channel_handle = std::move(channel.handle0); | |
| 71 return std::move(channel.handle1); | |
| 72 } | |
| 73 | |
| 58 class FakeChannelListener : public IPC::Listener { | 74 class FakeChannelListener : public IPC::Listener { |
| 59 public: | 75 public: |
| 60 FakeChannelListener() {} | 76 FakeChannelListener() {} |
| 61 ~FakeChannelListener() override {} | 77 ~FakeChannelListener() override {} |
| 62 bool OnMessageReceived(const IPC::Message& message) override { return true; } | 78 bool OnMessageReceived(const IPC::Message& message) override { return true; } |
| 63 }; | 79 }; |
| 64 | 80 |
| 65 class FakeMessageHandler : public ServiceIPCServer::MessageHandler { | 81 class FakeMessageHandler : public ServiceIPCServer::MessageHandler { |
| 66 public: | 82 public: |
| 67 explicit FakeMessageHandler(bool should_handle); | 83 explicit FakeMessageHandler(bool should_handle); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 97 | 113 |
| 98 // Sends |message| to the ServiceIPCServer. | 114 // Sends |message| to the ServiceIPCServer. |
| 99 void SendToServiceProcess(IPC::Message* message); | 115 void SendToServiceProcess(IPC::Message* message); |
| 100 | 116 |
| 101 IPC::SyncChannel* GetServerChannel() { | 117 IPC::SyncChannel* GetServerChannel() { |
| 102 return server_->channel_.get(); | 118 return server_->channel_.get(); |
| 103 } | 119 } |
| 104 | 120 |
| 105 protected: | 121 protected: |
| 106 FakeServiceIPCServerClient service_process_client_; | 122 FakeServiceIPCServerClient service_process_client_; |
| 107 IPC::ChannelHandle channel_handle_; | |
| 108 base::MessageLoopForUI main_message_loop_; | 123 base::MessageLoopForUI main_message_loop_; |
| 109 base::Thread io_thread_; | 124 base::Thread io_thread_; |
| 110 base::WaitableEvent shutdown_event_; | 125 base::WaitableEvent shutdown_event_; |
| 111 std::unique_ptr<ServiceIPCServer> server_; | 126 std::unique_ptr<ServiceIPCServer> server_; |
| 112 FakeChannelListener client_process_channel_listener_; | 127 FakeChannelListener client_process_channel_listener_; |
| 113 std::unique_ptr<IPC::SyncChannel> client_process_channel_; | 128 std::unique_ptr<IPC::SyncChannel> client_process_channel_; |
| 114 }; | 129 }; |
| 115 | 130 |
| 116 ServiceIPCServerTest::ServiceIPCServerTest() | 131 ServiceIPCServerTest::ServiceIPCServerTest() |
| 117 : channel_handle_(IPC::Channel::GenerateUniqueRandomChannelID()), | 132 : io_thread_("ServiceIPCServerTest IO"), |
| 118 io_thread_("ServiceIPCServerTest IO"), | |
| 119 shutdown_event_(base::WaitableEvent::ResetPolicy::MANUAL, | 133 shutdown_event_(base::WaitableEvent::ResetPolicy::MANUAL, |
| 120 base::WaitableEvent::InitialState::NOT_SIGNALED) {} | 134 base::WaitableEvent::InitialState::NOT_SIGNALED) {} |
| 121 | 135 |
| 122 void ServiceIPCServerTest::SetUp() { | 136 void ServiceIPCServerTest::SetUp() { |
| 123 base::Thread::Options options; | 137 base::Thread::Options options; |
| 138 mojo::MessagePipe channel; | |
| 124 options.message_loop_type = base::MessageLoop::TYPE_IO; | 139 options.message_loop_type = base::MessageLoop::TYPE_IO; |
| 125 ASSERT_TRUE(io_thread_.StartWithOptions(options)); | 140 ASSERT_TRUE(io_thread_.StartWithOptions(options)); |
| 126 | 141 |
| 127 server_.reset(new ServiceIPCServer(&service_process_client_, | 142 server_.reset(new ServiceIPCServer(&service_process_client_, |
| 128 io_thread_.task_runner(), | 143 io_thread_.task_runner(), |
| 129 channel_handle_, | |
| 130 &shutdown_event_)); | 144 &shutdown_event_)); |
| 131 server_->Init(); | 145 server_->Init(); |
| 132 } | 146 } |
| 133 | 147 |
| 134 void ServiceIPCServerTest::TearDown() { | 148 void ServiceIPCServerTest::TearDown() { |
| 135 // Close the ipc channels to prevent memory leaks. | 149 // Close the ipc channels to prevent memory leaks. |
| 136 if (client_process_channel_) { | 150 if (client_process_channel_) { |
| 137 client_process_channel_->Close(); | 151 client_process_channel_->Close(); |
| 138 PumpLoops(); | 152 PumpLoops(); |
| 139 } | 153 } |
| 140 if (GetServerChannel()) { | 154 if (GetServerChannel()) { |
| 141 GetServerChannel()->Close(); | 155 GetServerChannel()->Close(); |
| 142 PumpLoops(); | 156 PumpLoops(); |
| 143 } | 157 } |
| 144 io_thread_.Stop(); | 158 io_thread_.Stop(); |
| 145 } | 159 } |
| 146 | 160 |
| 147 void ServiceIPCServerTest::PumpLoops() { | 161 void ServiceIPCServerTest::PumpLoops() { |
| 148 base::RunLoop run_loop; | 162 base::RunLoop run_loop; |
| 149 io_thread_.task_runner()->PostTaskAndReply(FROM_HERE, | 163 io_thread_.task_runner()->PostTaskAndReply(FROM_HERE, |
| 150 base::Bind(&PumpCurrentLoop), | 164 base::Bind(&PumpCurrentLoop), |
| 151 run_loop.QuitClosure()); | 165 run_loop.QuitClosure()); |
| 152 run_loop.Run(); | 166 run_loop.Run(); |
| 153 PumpCurrentLoop(); | 167 PumpCurrentLoop(); |
| 154 } | 168 } |
| 155 | 169 |
| 156 void ServiceIPCServerTest::ConnectClientChannel() { | 170 void ServiceIPCServerTest::ConnectClientChannel() { |
| 157 client_process_channel_ = IPC::SyncChannel::Create( | 171 client_process_channel_ = IPC::SyncChannel::Create( |
| 158 channel_handle_, | 172 IPC::ChannelMojo::CreateClientFactory( |
| 159 IPC::Channel::MODE_NAMED_CLIENT, | 173 std::move(service_process_client_.channel_handle), |
| 160 &client_process_channel_listener_, | 174 io_thread_.task_runner()), |
| 161 io_thread_.task_runner(), | 175 &client_process_channel_listener_, io_thread_.task_runner(), |
| 162 true /* create_pipe_now */, | 176 true /* create_pipe_now */, &shutdown_event_); |
| 163 &shutdown_event_); | |
| 164 PumpLoops(); | 177 PumpLoops(); |
| 165 } | 178 } |
| 166 | 179 |
| 167 void ServiceIPCServerTest::DestroyClientChannel() { | 180 void ServiceIPCServerTest::DestroyClientChannel() { |
| 168 client_process_channel_.reset(); | 181 client_process_channel_.reset(); |
| 169 PumpLoops(); | 182 PumpLoops(); |
| 170 } | 183 } |
| 171 | 184 |
| 172 void ServiceIPCServerTest::SendToServiceProcess(IPC::Message* message) { | 185 void ServiceIPCServerTest::SendToServiceProcess(IPC::Message* message) { |
| 173 client_process_channel_->Send(message); | 186 client_process_channel_->Send(message); |
| 174 PumpLoops(); | 187 PumpLoops(); |
| 175 } | 188 } |
| 176 | 189 |
| 177 TEST_F(ServiceIPCServerTest, ConnectDisconnectReconnect) { | 190 TEST_F(ServiceIPCServerTest, ConnectDisconnectReconnect) { |
| 178 // Initially there is no ipc client connected. | 191 // Initially there is no ipc client connected. |
| 179 ASSERT_FALSE(server_->is_ipc_client_connected()); | 192 ASSERT_FALSE(server_->is_ipc_client_connected()); |
| 180 | 193 |
| 181 // When a channel is connected the server is notified via OnChannelConnected. | 194 // When a channel is connected the server is notified via OnChannelConnected. |
| 182 ConnectClientChannel(); | 195 ConnectClientChannel(); |
| 183 ASSERT_TRUE(server_->is_ipc_client_connected()); | 196 ASSERT_TRUE(server_->is_ipc_client_connected()); |
| 184 | 197 |
| 185 // When the channel is destroyed the server is notified via OnChannelError. | 198 // When the channel is destroyed the server is notified via OnChannelError. |
| 186 // In turn, the server notifies its service process client. | 199 // In turn, the server notifies its service process client. |
| 187 DestroyClientChannel(); | 200 DestroyClientChannel(); |
| 188 ASSERT_FALSE(server_->is_ipc_client_connected()); | 201 ASSERT_FALSE(server_->is_ipc_client_connected()); |
| 189 ASSERT_EQ(1, service_process_client_.ipc_client_disconnect_calls); | 202 ASSERT_EQ(1, service_process_client_.ipc_client_disconnect_calls); |
| 190 | 203 |
| 191 // On Windows only, the server recreates its channel in OnChannelError, if the | |
| 192 // service process client tells it to continue listening. On other platforms | |
| 193 // the channel is reused for subsequent reconnects by the client process. This | |
| 194 // means however that OnChannelConnected is not called again and the server is | |
| 195 // only aware of being connected once an IPC message is received. | |
| 196 ConnectClientChannel(); | 204 ConnectClientChannel(); |
| 197 #if defined(OS_WIN) | |
| 198 ASSERT_TRUE(server_->is_ipc_client_connected()); | 205 ASSERT_TRUE(server_->is_ipc_client_connected()); |
| 199 #else | |
| 200 ASSERT_FALSE(server_->is_ipc_client_connected()); | |
| 201 #endif | |
| 202 SendToServiceProcess(new ServiceMsg_UpdateAvailable()); | 206 SendToServiceProcess(new ServiceMsg_UpdateAvailable()); |
| 203 ASSERT_TRUE(server_->is_ipc_client_connected()); | 207 ASSERT_TRUE(server_->is_ipc_client_connected()); |
| 204 | 208 |
| 205 // Destroy the client process channel again to verify the | 209 // Destroy the client process channel again to verify the |
| 206 // ServiceIPCServer::Client is notified again. This means that unlike | 210 // ServiceIPCServer::Client is notified again. This means that unlike |
| 207 // OnChannelConnected, OnChannelError is called more than once. | 211 // OnChannelConnected, OnChannelError is called more than once. |
| 208 DestroyClientChannel(); | 212 DestroyClientChannel(); |
| 209 ASSERT_FALSE(server_->is_ipc_client_connected()); | 213 ASSERT_FALSE(server_->is_ipc_client_connected()); |
| 210 ASSERT_EQ(2, service_process_client_.ipc_client_disconnect_calls); | 214 ASSERT_EQ(2, service_process_client_.ipc_client_disconnect_calls); |
| 211 } | 215 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 256 new FakeMessageHandler(true /* should_handle */); | 260 new FakeMessageHandler(true /* should_handle */); |
| 257 server_->AddMessageHandler(base::WrapUnique(handler2)); | 261 server_->AddMessageHandler(base::WrapUnique(handler2)); |
| 258 FakeMessageHandler* handler3 = | 262 FakeMessageHandler* handler3 = |
| 259 new FakeMessageHandler(true /* should_handle */); | 263 new FakeMessageHandler(true /* should_handle */); |
| 260 server_->AddMessageHandler(base::WrapUnique(handler3)); | 264 server_->AddMessageHandler(base::WrapUnique(handler3)); |
| 261 SendToServiceProcess(new ServiceMsg_DisableCloudPrintProxy()); | 265 SendToServiceProcess(new ServiceMsg_DisableCloudPrintProxy()); |
| 262 ASSERT_EQ(1, handler1->handle_message_calls_); | 266 ASSERT_EQ(1, handler1->handle_message_calls_); |
| 263 ASSERT_EQ(1, handler2->handle_message_calls_); | 267 ASSERT_EQ(1, handler2->handle_message_calls_); |
| 264 ASSERT_EQ(0, handler3->handle_message_calls_); | 268 ASSERT_EQ(0, handler3->handle_message_calls_); |
| 265 } | 269 } |
| OLD | NEW |