- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / service / service_ipc_server.cc
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_.reset(new IPC::SyncChannel(
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_Shutdown, OnShutdown);
104     IPC_MESSAGE_HANDLER(ServiceMsg_UpdateAvailable, OnUpdateAvailable);
105     IPC_MESSAGE_UNHANDLED(handled = false)
106   IPC_END_MESSAGE_MAP()
107   return handled;
108 }
109
110 void ServiceIPCServer::OnEnableCloudPrintProxyWithRobot(
111     const std::string& robot_auth_code,
112     const std::string& robot_email,
113     const std::string& user_email,
114     const base::DictionaryValue& user_settings) {
115   g_service_process->GetCloudPrintProxy()->EnableForUserWithRobot(
116       robot_auth_code, robot_email, user_email, user_settings);
117 }
118
119 void ServiceIPCServer::OnGetCloudPrintProxyInfo() {
120   cloud_print::CloudPrintProxyInfo info;
121   g_service_process->GetCloudPrintProxy()->GetProxyInfo(&info);
122   channel_->Send(new ServiceHostMsg_CloudPrintProxy_Info(info));
123 }
124
125 void ServiceIPCServer::OnGetHistograms() {
126   if (!histogram_delta_serializer_) {
127     histogram_delta_serializer_.reset(
128         new base::HistogramDeltaSerialization("ServiceProcess"));
129   }
130   std::vector<std::string> deltas;
131   histogram_delta_serializer_->PrepareAndSerializeDeltas(&deltas);
132   channel_->Send(new ServiceHostMsg_Histograms(deltas));
133 }
134
135 void ServiceIPCServer::OnDisableCloudPrintProxy() {
136   // User disabled CloudPrint proxy explicitly. Delete printers
137   // registered from this proxy and disable proxy.
138   g_service_process->GetCloudPrintProxy()->
139       UnregisterPrintersAndDisableForUser();
140 }
141
142 void ServiceIPCServer::OnShutdown() {
143   g_service_process->Shutdown();
144 }
145
146 void ServiceIPCServer::OnUpdateAvailable() {
147   g_service_process->SetUpdateAvailable();
148 }
149