Avoid crashing when going back/forward to debug URLs on a sad WebUI tab.
[chromium-blink-merge.git] / chrome / service / service_ipc_server.cc
blob6bd7a73c1b8eebf1d3bc78e12833b257f8cb15e7
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/service/service_ipc_server.h"
7 #include "base/metrics/histogram_delta_serialization.h"
8 #include "chrome/common/service_messages.h"
9 #include "ipc/ipc_logging.h"
11 ServiceIPCServer::ServiceIPCServer(
12 Client* client,
13 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
14 const IPC::ChannelHandle& channel_handle,
15 base::WaitableEvent* shutdown_event)
16 : client_(client),
17 io_task_runner_(io_task_runner),
18 channel_handle_(channel_handle),
19 shutdown_event_(shutdown_event),
20 ipc_client_connected_(false) {
21 DCHECK(client);
22 DCHECK(shutdown_event);
25 bool ServiceIPCServer::Init() {
26 #ifdef IPC_MESSAGE_LOG_ENABLED
27 IPC::Logging::GetInstance()->SetIPCSender(this);
28 #endif
29 CreateChannel();
30 return true;
33 void ServiceIPCServer::CreateChannel() {
34 channel_.reset(); // Tear down the existing channel, if any.
35 channel_ = IPC::SyncChannel::Create(
36 channel_handle_,
37 IPC::Channel::MODE_NAMED_SERVER,
38 this /* listener */,
39 io_task_runner_,
40 true /* create_pipe_now */,
41 shutdown_event_);
44 ServiceIPCServer::~ServiceIPCServer() {
45 #ifdef IPC_MESSAGE_LOG_ENABLED
46 IPC::Logging::GetInstance()->SetIPCSender(NULL);
47 #endif
50 void ServiceIPCServer::OnChannelConnected(int32 peer_pid) {
51 DCHECK(!ipc_client_connected_);
52 ipc_client_connected_ = true;
55 void ServiceIPCServer::OnChannelError() {
56 // When an IPC client (typically a browser process) disconnects, the pipe is
57 // closed and we get an OnChannelError. If we want to keep servicing requests,
58 // we will recreate the channel if necessary.
59 bool client_was_connected = ipc_client_connected_;
60 ipc_client_connected_ = false;
61 if (client_was_connected) {
62 if (client_->OnIPCClientDisconnect()) {
63 #if defined(OS_WIN)
64 // On Windows, once an error on a named pipe occurs, the named pipe is no
65 // longer valid and must be re-created. This is not the case on Mac or
66 // Linux.
67 CreateChannel();
68 #endif
70 } else {
71 // If the client was never even connected we had an error connecting.
72 if (!ipc_client_connected_) {
73 LOG(ERROR) << "Unable to open service ipc channel "
74 << "named: " << channel_handle_.name;
79 bool ServiceIPCServer::Send(IPC::Message* msg) {
80 if (!channel_.get()) {
81 delete msg;
82 return false;
85 return channel_->Send(msg);
88 void ServiceIPCServer::AddMessageHandler(scoped_ptr<MessageHandler> handler) {
89 message_handlers_.push_back(handler.release());
92 bool ServiceIPCServer::OnMessageReceived(const IPC::Message& msg) {
93 bool handled = true;
94 // When we get a message, always mark the IPC client as connected. The
95 // ChannelProxy::Context is only letting OnChannelConnected get called once,
96 // so on Mac and Linux, we never would set ipc_client_connected_ to true
97 // again on subsequent connections.
98 ipc_client_connected_ = true;
99 IPC_BEGIN_MESSAGE_MAP(ServiceIPCServer, msg)
100 IPC_MESSAGE_HANDLER(ServiceMsg_GetHistograms, OnGetHistograms)
101 IPC_MESSAGE_HANDLER(ServiceMsg_Shutdown, OnShutdown);
102 IPC_MESSAGE_HANDLER(ServiceMsg_UpdateAvailable, OnUpdateAvailable);
103 IPC_MESSAGE_UNHANDLED(handled = false)
104 IPC_END_MESSAGE_MAP()
106 if (!handled) {
107 // Make a copy of the handlers to prevent modification during iteration.
108 std::vector<MessageHandler*> temp_handlers = message_handlers_.get();
109 for (const auto& handler : temp_handlers) {
110 handled = handler->HandleMessage(msg);
111 if (handled)
112 break;
116 return handled;
119 void ServiceIPCServer::OnGetHistograms() {
120 if (!histogram_delta_serializer_) {
121 histogram_delta_serializer_.reset(
122 new base::HistogramDeltaSerialization("ServiceProcess"));
124 std::vector<std::string> deltas;
125 histogram_delta_serializer_->PrepareAndSerializeDeltas(&deltas);
126 channel_->Send(new ServiceHostMsg_Histograms(deltas));
129 void ServiceIPCServer::OnShutdown() {
130 client_->OnShutdown();
133 void ServiceIPCServer::OnUpdateAvailable() {
134 client_->OnUpdateAvailable();