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