Give names to all utility processes.
[chromium-blink-merge.git] / chrome / browser / local_discovery / service_discovery_host_client.cc
blobf201ffbdc876f286a80554214afbc37e10e2f073
1 // Copyright 2013 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.
5 #include "chrome/browser/local_discovery/service_discovery_host_client.h"
7 #include "chrome/common/local_discovery/local_discovery_messages.h"
8 #include "chrome/grit/generated_resources.h"
9 #include "content/public/browser/browser_thread.h"
10 #include "content/public/browser/utility_process_host.h"
11 #include "net/dns/mdns_client.h"
12 #include "net/socket/socket_descriptor.h"
13 #include "ui/base/l10n/l10n_util.h"
15 #if defined(OS_POSIX)
16 #include <netinet/in.h>
17 #include "base/file_descriptor_posix.h"
18 #endif // OS_POSIX
20 namespace local_discovery {
22 using content::BrowserThread;
23 using content::UtilityProcessHost;
25 namespace {
27 #if defined(OS_POSIX)
28 SocketInfoList GetSocketsOnFileThread() {
29 net::InterfaceIndexFamilyList interfaces(net::GetMDnsInterfacesToBind());
30 SocketInfoList sockets;
31 for (size_t i = 0; i < interfaces.size(); ++i) {
32 DCHECK(interfaces[i].second == net::ADDRESS_FAMILY_IPV4 ||
33 interfaces[i].second == net::ADDRESS_FAMILY_IPV6);
34 base::FileDescriptor socket_descriptor(
35 net::CreatePlatformSocket(
36 net::ConvertAddressFamily(interfaces[i].second), SOCK_DGRAM,
37 IPPROTO_UDP),
38 true);
39 LOG_IF(ERROR, socket_descriptor.fd == net::kInvalidSocket)
40 << "Can't create socket, family=" << interfaces[i].second;
41 if (socket_descriptor.fd != net::kInvalidSocket) {
42 LocalDiscoveryMsg_SocketInfo socket;
43 socket.descriptor = socket_descriptor;
44 socket.interface_index = interfaces[i].first;
45 socket.address_family = interfaces[i].second;
46 sockets.push_back(socket);
50 return sockets;
52 #endif // OS_POSIX
54 } // namespace
56 class ServiceDiscoveryHostClient::ServiceWatcherProxy : public ServiceWatcher {
57 public:
58 ServiceWatcherProxy(ServiceDiscoveryHostClient* host,
59 const std::string& service_type,
60 const ServiceWatcher::UpdatedCallback& callback)
61 : host_(host),
62 service_type_(service_type),
63 id_(host_->RegisterWatcherCallback(callback)),
64 started_(false) {
67 ~ServiceWatcherProxy() override {
68 DVLOG(1) << "~ServiceWatcherProxy with id " << id_;
69 host_->UnregisterWatcherCallback(id_);
70 if (started_)
71 host_->Send(new LocalDiscoveryMsg_DestroyWatcher(id_));
74 void Start() override {
75 DVLOG(1) << "ServiceWatcher::Start with id " << id_;
76 DCHECK(!started_);
77 host_->Send(new LocalDiscoveryMsg_StartWatcher(id_, service_type_));
78 started_ = true;
81 void DiscoverNewServices(bool force_update) override {
82 DVLOG(1) << "ServiceWatcher::DiscoverNewServices with id " << id_;
83 DCHECK(started_);
84 host_->Send(new LocalDiscoveryMsg_DiscoverServices(id_, force_update));
87 void SetActivelyRefreshServices(bool actively_refresh_services) override {
88 DVLOG(1) << "ServiceWatcher::SetActivelyRefreshServices with id " << id_;
89 DCHECK(started_);
90 host_->Send(new LocalDiscoveryMsg_SetActivelyRefreshServices(
91 id_, actively_refresh_services));
94 std::string GetServiceType() const override { return service_type_; }
96 private:
97 scoped_refptr<ServiceDiscoveryHostClient> host_;
98 const std::string service_type_;
99 const uint64 id_;
100 bool started_;
103 class ServiceDiscoveryHostClient::ServiceResolverProxy
104 : public ServiceResolver {
105 public:
106 ServiceResolverProxy(ServiceDiscoveryHostClient* host,
107 const std::string& service_name,
108 const ServiceResolver::ResolveCompleteCallback& callback)
109 : host_(host),
110 service_name_(service_name),
111 id_(host->RegisterResolverCallback(callback)),
112 started_(false) {
115 ~ServiceResolverProxy() override {
116 DVLOG(1) << "~ServiceResolverProxy with id " << id_;
117 host_->UnregisterResolverCallback(id_);
118 if (started_)
119 host_->Send(new LocalDiscoveryMsg_DestroyResolver(id_));
122 void StartResolving() override {
123 DVLOG(1) << "ServiceResolverProxy::StartResolving with id " << id_;
124 DCHECK(!started_);
125 host_->Send(new LocalDiscoveryMsg_ResolveService(id_, service_name_));
126 started_ = true;
129 std::string GetName() const override { return service_name_; }
131 private:
132 scoped_refptr<ServiceDiscoveryHostClient> host_;
133 const std::string service_name_;
134 const uint64 id_;
135 bool started_;
138 class ServiceDiscoveryHostClient::LocalDomainResolverProxy
139 : public LocalDomainResolver {
140 public:
141 LocalDomainResolverProxy(ServiceDiscoveryHostClient* host,
142 const std::string& domain,
143 net::AddressFamily address_family,
144 const LocalDomainResolver::IPAddressCallback& callback)
145 : host_(host),
146 domain_(domain),
147 address_family_(address_family),
148 id_(host->RegisterLocalDomainResolverCallback(callback)),
149 started_(false) {
152 ~LocalDomainResolverProxy() override {
153 DVLOG(1) << "~LocalDomainResolverProxy with id " << id_;
154 host_->UnregisterLocalDomainResolverCallback(id_);
155 if (started_)
156 host_->Send(new LocalDiscoveryMsg_DestroyLocalDomainResolver(id_));
159 void Start() override {
160 DVLOG(1) << "LocalDomainResolverProxy::Start with id " << id_;
161 DCHECK(!started_);
162 host_->Send(new LocalDiscoveryMsg_ResolveLocalDomain(id_, domain_,
163 address_family_));
164 started_ = true;
167 private:
168 scoped_refptr<ServiceDiscoveryHostClient> host_;
169 std::string domain_;
170 net::AddressFamily address_family_;
171 const uint64 id_;
172 bool started_;
175 ServiceDiscoveryHostClient::ServiceDiscoveryHostClient() : current_id_(0) {
176 callback_runner_ = base::MessageLoop::current()->message_loop_proxy();
177 io_runner_ = BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
180 ServiceDiscoveryHostClient::~ServiceDiscoveryHostClient() {
181 DCHECK(service_watcher_callbacks_.empty());
182 DCHECK(service_resolver_callbacks_.empty());
183 DCHECK(domain_resolver_callbacks_.empty());
186 scoped_ptr<ServiceWatcher> ServiceDiscoveryHostClient::CreateServiceWatcher(
187 const std::string& service_type,
188 const ServiceWatcher::UpdatedCallback& callback) {
189 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
190 return scoped_ptr<ServiceWatcher>(
191 new ServiceWatcherProxy(this, service_type, callback));
194 scoped_ptr<ServiceResolver> ServiceDiscoveryHostClient::CreateServiceResolver(
195 const std::string& service_name,
196 const ServiceResolver::ResolveCompleteCallback& callback) {
197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
198 return scoped_ptr<ServiceResolver>(
199 new ServiceResolverProxy(this, service_name, callback));
202 scoped_ptr<LocalDomainResolver>
203 ServiceDiscoveryHostClient::CreateLocalDomainResolver(
204 const std::string& domain,
205 net::AddressFamily address_family,
206 const LocalDomainResolver::IPAddressCallback& callback) {
207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
208 return scoped_ptr<LocalDomainResolver>(new LocalDomainResolverProxy(
209 this, domain, address_family, callback));
212 uint64 ServiceDiscoveryHostClient::RegisterWatcherCallback(
213 const ServiceWatcher::UpdatedCallback& callback) {
214 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
215 DCHECK(!ContainsKey(service_watcher_callbacks_, current_id_ + 1));
216 service_watcher_callbacks_[++current_id_] = callback;
217 return current_id_;
220 uint64 ServiceDiscoveryHostClient::RegisterResolverCallback(
221 const ServiceResolver::ResolveCompleteCallback& callback) {
222 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
223 DCHECK(!ContainsKey(service_resolver_callbacks_, current_id_ + 1));
224 service_resolver_callbacks_[++current_id_] = callback;
225 return current_id_;
228 uint64 ServiceDiscoveryHostClient::RegisterLocalDomainResolverCallback(
229 const LocalDomainResolver::IPAddressCallback& callback) {
230 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
231 DCHECK(!ContainsKey(domain_resolver_callbacks_, current_id_ + 1));
232 domain_resolver_callbacks_[++current_id_] = callback;
233 return current_id_;
236 void ServiceDiscoveryHostClient::UnregisterWatcherCallback(uint64 id) {
237 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
238 service_watcher_callbacks_.erase(id);
241 void ServiceDiscoveryHostClient::UnregisterResolverCallback(uint64 id) {
242 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
243 service_resolver_callbacks_.erase(id);
246 void ServiceDiscoveryHostClient::UnregisterLocalDomainResolverCallback(
247 uint64 id) {
248 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
249 domain_resolver_callbacks_.erase(id);
252 void ServiceDiscoveryHostClient::Start(
253 const base::Closure& error_callback) {
254 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
255 DCHECK(!utility_host_);
256 DCHECK(error_callback_.is_null());
257 error_callback_ = error_callback;
258 io_runner_->PostTask(
259 FROM_HERE,
260 base::Bind(&ServiceDiscoveryHostClient::StartOnIOThread, this));
263 void ServiceDiscoveryHostClient::Shutdown() {
264 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
265 io_runner_->PostTask(
266 FROM_HERE,
267 base::Bind(&ServiceDiscoveryHostClient::ShutdownOnIOThread, this));
270 #if defined(OS_POSIX)
272 void ServiceDiscoveryHostClient::StartOnIOThread() {
273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
274 DCHECK(!utility_host_);
275 BrowserThread::PostTaskAndReplyWithResult(
276 BrowserThread::FILE,
277 FROM_HERE,
278 base::Bind(&GetSocketsOnFileThread),
279 base::Bind(&ServiceDiscoveryHostClient::OnSocketsReady, this));
282 void ServiceDiscoveryHostClient::OnSocketsReady(const SocketInfoList& sockets) {
283 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
284 DCHECK(!utility_host_);
285 utility_host_ = UtilityProcessHost::Create(
286 this, base::MessageLoopProxy::current().get())->AsWeakPtr();
287 utility_host_->SetName(l10n_util::GetStringUTF16(
288 IDS_UTILITY_PROCESS_SERVICE_DISCOVERY_HANDLER_NAME));
289 utility_host_->EnableMDns();
290 utility_host_->StartBatchMode();
291 if (sockets.empty()) {
292 ShutdownOnIOThread();
293 return;
295 utility_host_->Send(new LocalDiscoveryMsg_SetSockets(sockets));
296 // Send messages for requests made during network enumeration.
297 for (size_t i = 0; i < delayed_messages_.size(); ++i)
298 utility_host_->Send(delayed_messages_[i]);
299 delayed_messages_.weak_clear();
302 #else // OS_POSIX
304 void ServiceDiscoveryHostClient::StartOnIOThread() {
305 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
306 DCHECK(!utility_host_);
307 utility_host_ = UtilityProcessHost::Create(
308 this, base::MessageLoopProxy::current().get())->AsWeakPtr();
309 utility_host_->SetName(l10n_util::GetStringUTF16(
310 IDS_UTILITY_PROCESS_SERVICE_DISCOVERY_HANDLER_NAME));
311 utility_host_->EnableMDns();
312 utility_host_->StartBatchMode();
313 // Windows does not enumerate networks here.
314 DCHECK(delayed_messages_.empty());
317 #endif // OS_POSIX
319 void ServiceDiscoveryHostClient::ShutdownOnIOThread() {
320 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
321 if (utility_host_) {
322 utility_host_->Send(new LocalDiscoveryMsg_ShutdownLocalDiscovery);
323 utility_host_->EndBatchMode();
324 utility_host_.reset();
326 error_callback_ = base::Closure();
329 void ServiceDiscoveryHostClient::Send(IPC::Message* msg) {
330 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
331 io_runner_->PostTask(
332 FROM_HERE,
333 base::Bind(&ServiceDiscoveryHostClient::SendOnIOThread, this, msg));
336 void ServiceDiscoveryHostClient::SendOnIOThread(IPC::Message* msg) {
337 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
338 if (utility_host_) {
339 utility_host_->Send(msg);
340 } else {
341 delayed_messages_.push_back(msg);
345 void ServiceDiscoveryHostClient::OnProcessCrashed(int exit_code) {
346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
347 DCHECK(!utility_host_);
348 OnError();
351 bool ServiceDiscoveryHostClient::OnMessageReceived(
352 const IPC::Message& message) {
353 bool handled = true;
354 IPC_BEGIN_MESSAGE_MAP(ServiceDiscoveryHostClient, message)
355 IPC_MESSAGE_HANDLER(LocalDiscoveryHostMsg_Error, OnError)
356 IPC_MESSAGE_HANDLER(LocalDiscoveryHostMsg_WatcherCallback,
357 OnWatcherCallback)
358 IPC_MESSAGE_HANDLER(LocalDiscoveryHostMsg_ResolverCallback,
359 OnResolverCallback)
360 IPC_MESSAGE_HANDLER(LocalDiscoveryHostMsg_LocalDomainResolverCallback,
361 OnLocalDomainResolverCallback)
362 IPC_MESSAGE_UNHANDLED(handled = false)
363 IPC_END_MESSAGE_MAP()
364 return handled;
367 void ServiceDiscoveryHostClient::InvalidateWatchers() {
368 WatcherCallbacks service_watcher_callbacks;
369 service_watcher_callbacks_.swap(service_watcher_callbacks);
370 service_resolver_callbacks_.clear();
371 domain_resolver_callbacks_.clear();
373 for (WatcherCallbacks::iterator i = service_watcher_callbacks.begin();
374 i != service_watcher_callbacks.end(); i++) {
375 if (!i->second.is_null()) {
376 i->second.Run(ServiceWatcher::UPDATE_INVALIDATED, "");
381 void ServiceDiscoveryHostClient::OnError() {
382 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
383 if (!error_callback_.is_null())
384 callback_runner_->PostTask(FROM_HERE, error_callback_);
387 void ServiceDiscoveryHostClient::OnWatcherCallback(
388 uint64 id,
389 ServiceWatcher::UpdateType update,
390 const std::string& service_name) {
391 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
392 callback_runner_->PostTask(
393 FROM_HERE,
394 base::Bind(&ServiceDiscoveryHostClient::RunWatcherCallback, this, id,
395 update, service_name));
398 void ServiceDiscoveryHostClient::OnResolverCallback(
399 uint64 id,
400 ServiceResolver::RequestStatus status,
401 const ServiceDescription& description) {
402 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
403 callback_runner_->PostTask(
404 FROM_HERE,
405 base::Bind(&ServiceDiscoveryHostClient::RunResolverCallback, this, id,
406 status, description));
409 void ServiceDiscoveryHostClient::OnLocalDomainResolverCallback(
410 uint64 id,
411 bool success,
412 const net::IPAddressNumber& ip_address_ipv4,
413 const net::IPAddressNumber& ip_address_ipv6) {
414 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
415 callback_runner_->PostTask(
416 FROM_HERE,
417 base::Bind(&ServiceDiscoveryHostClient::RunLocalDomainResolverCallback,
418 this, id, success, ip_address_ipv4, ip_address_ipv6));
421 void ServiceDiscoveryHostClient::RunWatcherCallback(
422 uint64 id,
423 ServiceWatcher::UpdateType update,
424 const std::string& service_name) {
425 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
426 WatcherCallbacks::iterator it = service_watcher_callbacks_.find(id);
427 if (it != service_watcher_callbacks_.end() && !it->second.is_null())
428 it->second.Run(update, service_name);
431 void ServiceDiscoveryHostClient::RunResolverCallback(
432 uint64 id,
433 ServiceResolver::RequestStatus status,
434 const ServiceDescription& description) {
435 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
436 ResolverCallbacks::iterator it = service_resolver_callbacks_.find(id);
437 if (it != service_resolver_callbacks_.end() && !it->second.is_null())
438 it->second.Run(status, description);
441 void ServiceDiscoveryHostClient::RunLocalDomainResolverCallback(
442 uint64 id,
443 bool success,
444 const net::IPAddressNumber& ip_address_ipv4,
445 const net::IPAddressNumber& ip_address_ipv6) {
446 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
447 DomainResolverCallbacks::iterator it = domain_resolver_callbacks_.find(id);
448 if (it != domain_resolver_callbacks_.end() && !it->second.is_null())
449 it->second.Run(success, ip_address_ipv4, ip_address_ipv6);
452 } // namespace local_discovery