Home | History | Annotate | Download | only in service
      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.
      4 
      5 #include "chrome/service/service_ipc_server.h"
      6 
      7 #include "base/metrics/histogram_delta_serialization.h"
      8 #include "chrome/common/service_messages.h"
      9 #include "chrome/service/cloud_print/cloud_print_proxy.h"
     10 #include "chrome/service/service_process.h"
     11 #include "ipc/ipc_logging.h"
     12 
     13 ServiceIPCServer::ServiceIPCServer(const IPC::ChannelHandle& channel_handle)
     14     : channel_handle_(channel_handle), client_connected_(false) {
     15 }
     16 
     17 bool ServiceIPCServer::Init() {
     18 #ifdef IPC_MESSAGE_LOG_ENABLED
     19   IPC::Logging::GetInstance()->SetIPCSender(this);
     20 #endif
     21   sync_message_filter_ =
     22       new IPC::SyncMessageFilter(g_service_process->shutdown_event());
     23   CreateChannel();
     24   return true;
     25 }
     26 
     27 void ServiceIPCServer::CreateChannel() {
     28   channel_.reset(NULL); // Tear down the existing channel, if any.
     29   channel_ = IPC::SyncChannel::Create(
     30       channel_handle_,
     31       IPC::Channel::MODE_NAMED_SERVER,
     32       this,
     33       g_service_process->io_thread()->message_loop_proxy().get(),
     34       true,
     35       g_service_process->shutdown_event());
     36   DCHECK(sync_message_filter_.get());
     37   channel_->AddFilter(sync_message_filter_.get());
     38 }
     39 
     40 ServiceIPCServer::~ServiceIPCServer() {
     41 #ifdef IPC_MESSAGE_LOG_ENABLED
     42   IPC::Logging::GetInstance()->SetIPCSender(NULL);
     43 #endif
     44 
     45   channel_->RemoveFilter(sync_message_filter_.get());
     46 }
     47 
     48 void ServiceIPCServer::OnChannelConnected(int32 peer_pid) {
     49   DCHECK(!client_connected_);
     50   client_connected_ = true;
     51 }
     52 
     53 void ServiceIPCServer::OnChannelError() {
     54   // When a client (typically a browser process) disconnects, the pipe is
     55   // closed and we get an OnChannelError. Since we want to keep servicing
     56   // client requests, we will recreate the channel.
     57   bool client_was_connected = client_connected_;
     58   client_connected_ = false;
     59   // TODO(sanjeevr): Instead of invoking the service process for such handlers,
     60   // define a Client interface that the ServiceProcess can implement.
     61   if (client_was_connected) {
     62     if (g_service_process->HandleClientDisconnect()) {
     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
     69     }
     70   } else {
     71     // If the client was never even connected we had an error connecting.
     72     if (!client_connected_) {
     73       LOG(ERROR) << "Unable to open service ipc channel "
     74                  << "named: " << channel_handle_.name;
     75     }
     76   }
     77 }
     78 
     79 bool ServiceIPCServer::Send(IPC::Message* msg) {
     80   if (!channel_.get()) {
     81     delete msg;
     82     return false;
     83   }
     84 
     85   return channel_->Send(msg);
     86 }
     87 
     88 bool ServiceIPCServer::OnMessageReceived(const IPC::Message& msg) {
     89   bool handled = true;
     90   // When we get a message, always mark the client as connected. The
     91   // ChannelProxy::Context is only letting OnChannelConnected get called once,
     92   // so on the Mac and Linux, we never would set client_connected_ to true
     93   // again on subsequent connections.
     94   client_connected_ = true;
     95   IPC_BEGIN_MESSAGE_MAP(ServiceIPCServer, msg)
     96     IPC_MESSAGE_HANDLER(ServiceMsg_EnableCloudPrintProxyWithRobot,
     97                         OnEnableCloudPrintProxyWithRobot)
     98     IPC_MESSAGE_HANDLER(ServiceMsg_DisableCloudPrintProxy,
     99                         OnDisableCloudPrintProxy)
    100     IPC_MESSAGE_HANDLER(ServiceMsg_GetCloudPrintProxyInfo,
    101                         OnGetCloudPrintProxyInfo)
    102     IPC_MESSAGE_HANDLER(ServiceMsg_GetHistograms, OnGetHistograms)
    103     IPC_MESSAGE_HANDLER(ServiceMsg_GetPrinters, OnGetPrinters)
    104     IPC_MESSAGE_HANDLER(ServiceMsg_Shutdown, OnShutdown);
    105     IPC_MESSAGE_HANDLER(ServiceMsg_UpdateAvailable, OnUpdateAvailable);
    106     IPC_MESSAGE_UNHANDLED(handled = false)
    107   IPC_END_MESSAGE_MAP()
    108   return handled;
    109 }
    110 
    111 void ServiceIPCServer::OnEnableCloudPrintProxyWithRobot(
    112     const std::string& robot_auth_code,
    113     const std::string& robot_email,
    114     const std::string& user_email,
    115     const base::DictionaryValue& user_settings) {
    116   g_service_process->GetCloudPrintProxy()->EnableForUserWithRobot(
    117       robot_auth_code, robot_email, user_email, user_settings);
    118 }
    119 
    120 void ServiceIPCServer::OnGetCloudPrintProxyInfo() {
    121   cloud_print::CloudPrintProxyInfo info;
    122   g_service_process->GetCloudPrintProxy()->GetProxyInfo(&info);
    123   channel_->Send(new ServiceHostMsg_CloudPrintProxy_Info(info));
    124 }
    125 
    126 void ServiceIPCServer::OnGetHistograms() {
    127   if (!histogram_delta_serializer_) {
    128     histogram_delta_serializer_.reset(
    129         new base::HistogramDeltaSerialization("ServiceProcess"));
    130   }
    131   std::vector<std::string> deltas;
    132   histogram_delta_serializer_->PrepareAndSerializeDeltas(&deltas);
    133   channel_->Send(new ServiceHostMsg_Histograms(deltas));
    134 }
    135 
    136 void ServiceIPCServer::OnGetPrinters() {
    137   std::vector<std::string> printers;
    138   g_service_process->GetCloudPrintProxy()->GetPrinters(&printers);
    139   channel_->Send(new ServiceHostMsg_Printers(printers));
    140 }
    141 
    142 void ServiceIPCServer::OnDisableCloudPrintProxy() {
    143   // User disabled CloudPrint proxy explicitly. Delete printers
    144   // registered from this proxy and disable proxy.
    145   g_service_process->GetCloudPrintProxy()->
    146       UnregisterPrintersAndDisableForUser();
    147 }
    148 
    149 void ServiceIPCServer::OnShutdown() {
    150   g_service_process->Shutdown();
    151 }
    152 
    153 void ServiceIPCServer::OnUpdateAvailable() {
    154   g_service_process->SetUpdateAvailable();
    155 }
    156 
    157