15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/service_ipc_server.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
71e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/metrics/histogram_delta_serialization.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/service_messages.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/cloud_print/cloud_print_proxy.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/service_process.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_logging.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ServiceIPCServer::ServiceIPCServer(const IPC::ChannelHandle& channel_handle)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : channel_handle_(channel_handle), client_connected_(false) {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ServiceIPCServer::Init() {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef IPC_MESSAGE_LOG_ENABLED
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC::Logging::GetInstance()->SetIPCSender(this);
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_message_filter_ =
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new IPC::SyncMessageFilter(g_service_process->shutdown_event());
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateChannel();
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ServiceIPCServer::CreateChannel() {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_.reset(NULL); // Tear down the existing channel, if any.
2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  channel_ = IPC::SyncChannel::Create(
307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      channel_handle_,
317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      IPC::Channel::MODE_NAMED_SERVER,
327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      this,
337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      g_service_process->io_thread()->message_loop_proxy().get(),
347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      true,
3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      g_service_process->shutdown_event());
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(sync_message_filter_.get());
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_->AddFilter(sync_message_filter_.get());
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ServiceIPCServer::~ServiceIPCServer() {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef IPC_MESSAGE_LOG_ENABLED
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC::Logging::GetInstance()->SetIPCSender(NULL);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_->RemoveFilter(sync_message_filter_.get());
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ServiceIPCServer::OnChannelConnected(int32 peer_pid) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!client_connected_);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_connected_ = true;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ServiceIPCServer::OnChannelError() {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When a client (typically a browser process) disconnects, the pipe is
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // closed and we get an OnChannelError. Since we want to keep servicing
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // client requests, we will recreate the channel.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool client_was_connected = client_connected_;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_connected_ = false;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(sanjeevr): Instead of invoking the service process for such handlers,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // define a Client interface that the ServiceProcess can implement.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (client_was_connected) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (g_service_process->HandleClientDisconnect()) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // On Windows, once an error on a named pipe occurs, the named pipe is no
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // longer valid and must be re-created. This is not the case on Mac or
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Linux.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateChannel();
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the client was never even connected we had an error connecting.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!client_connected_) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Unable to open service ipc channel "
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << "named: " << channel_handle_.name;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ServiceIPCServer::Send(IPC::Message* msg) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!channel_.get()) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete msg;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return channel_->Send(msg);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ServiceIPCServer::OnMessageReceived(const IPC::Message& msg) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handled = true;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When we get a message, always mark the client as connected. The
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ChannelProxy::Context is only letting OnChannelConnected get called once,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so on the Mac and Linux, we never would set client_connected_ to true
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // again on subsequent connections.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_connected_ = true;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(ServiceIPCServer, msg)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ServiceMsg_EnableCloudPrintProxyWithRobot,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnEnableCloudPrintProxyWithRobot)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ServiceMsg_DisableCloudPrintProxy,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnDisableCloudPrintProxy)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ServiceMsg_GetCloudPrintProxyInfo,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnGetCloudPrintProxyInfo)
1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ServiceMsg_GetHistograms, OnGetHistograms)
103effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    IPC_MESSAGE_HANDLER(ServiceMsg_GetPrinters, OnGetPrinters)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ServiceMsg_Shutdown, OnShutdown);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(ServiceMsg_UpdateAvailable, OnUpdateAvailable);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return handled;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ServiceIPCServer::OnEnableCloudPrintProxyWithRobot(
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& robot_auth_code,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& robot_email,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& user_email,
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& user_settings) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_service_process->GetCloudPrintProxy()->EnableForUserWithRobot(
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      robot_auth_code, robot_email, user_email, user_settings);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ServiceIPCServer::OnGetCloudPrintProxyInfo() {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cloud_print::CloudPrintProxyInfo info;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_service_process->GetCloudPrintProxy()->GetProxyInfo(&info);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  channel_->Send(new ServiceHostMsg_CloudPrintProxy_Info(info));
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ServiceIPCServer::OnGetHistograms() {
1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!histogram_delta_serializer_) {
1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    histogram_delta_serializer_.reset(
1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        new base::HistogramDeltaSerialization("ServiceProcess"));
1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::vector<std::string> deltas;
1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  histogram_delta_serializer_->PrepareAndSerializeDeltas(&deltas);
1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  channel_->Send(new ServiceHostMsg_Histograms(deltas));
1341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
136effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ServiceIPCServer::OnGetPrinters() {
137effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  std::vector<std::string> printers;
138effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  g_service_process->GetCloudPrintProxy()->GetPrinters(&printers);
139effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  channel_->Send(new ServiceHostMsg_Printers(printers));
140effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
141effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ServiceIPCServer::OnDisableCloudPrintProxy() {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // User disabled CloudPrint proxy explicitly. Delete printers
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // registered from this proxy and disable proxy.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_service_process->GetCloudPrintProxy()->
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UnregisterPrintersAndDisableForUser();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ServiceIPCServer::OnShutdown() {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_service_process->Shutdown();
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ServiceIPCServer::OnUpdateAvailable() {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_service_process->SetUpdateAvailable();
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
157