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