[Cronet] Delay StartNetLog and StopNetLog until native request context is initialized
[chromium-blink-merge.git] / chrome / browser / local_discovery / service_discovery_host_client.cc
blobebdbe62609e1bd5d750513194f9bb913867006d0
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 "content/public/browser/browser_thread.h"
9 #include "content/public/browser/utility_process_host.h"
10 #include "net/dns/mdns_client.h"
11 #include "net/socket/socket_descriptor.h"
13 #if defined(OS_POSIX)
14 #include <netinet/in.h>
15 #include "base/file_descriptor_posix.h"
16 #endif // OS_POSIX
18 namespace local_discovery {
20 using content::BrowserThread;
21 using content::UtilityProcessHost;
23 namespace {
25 #if defined(OS_POSIX)
26 SocketInfoList GetSocketsOnFileThread() {
27 net::InterfaceIndexFamilyList interfaces(net::GetMDnsInterfacesToBind());
28 SocketInfoList sockets;
29 for (size_t i = 0; i < interfaces.size(); ++i) {
30 DCHECK(interfaces[i].second == net::ADDRESS_FAMILY_IPV4 ||
31 interfaces[i].second == net::ADDRESS_FAMILY_IPV6);
32 base::FileDescriptor socket_descriptor(
33 net::CreatePlatformSocket(
34 net::ConvertAddressFamily(interfaces[i].second), SOCK_DGRAM,
35 IPPROTO_UDP),
36 true);
37 LOG_IF(ERROR, socket_descriptor.fd == net::kInvalidSocket)
38 << "Can't create socket, family=" << interfaces[i].second;
39 if (socket_descriptor.fd != net::kInvalidSocket) {
40 LocalDiscoveryMsg_SocketInfo socket;
41 socket.descriptor = socket_descriptor;
42 socket.interface_index = interfaces[i].first;
43 socket.address_family = interfaces[i].second;
44 sockets.push_back(socket);
48 return sockets;
50 #endif // OS_POSIX
52 } // namespace
54 class ServiceDiscoveryHostClient::ServiceWatcherProxy : public ServiceWatcher {
55 public:
56 ServiceWatcherProxy(ServiceDiscoveryHostClient* host,
57 const std::string& service_type,
58 const ServiceWatcher::UpdatedCallback& callback)
59 : host_(host),
60 service_type_(service_type),
61 id_(host_->RegisterWatcherCallback(callback)),
62 started_(false) {
65 ~ServiceWatcherProxy() override {
66 DVLOG(1) << "~ServiceWatcherProxy with id " << id_;
67 host_->UnregisterWatcherCallback(id_);
68 if (started_)
69 host_->Send(new LocalDiscoveryMsg_DestroyWatcher(id_));
72 void Start() override {
73 DVLOG(1) << "ServiceWatcher::Start with id " << id_;
74 DCHECK(!started_);
75 host_->Send(new LocalDiscoveryMsg_StartWatcher(id_, service_type_));
76 started_ = true;
79 void DiscoverNewServices(bool force_update) override {
80 DVLOG(1) << "ServiceWatcher::DiscoverNewServices with id " << id_;
81 DCHECK(started_);
82 host_->Send(new LocalDiscoveryMsg_DiscoverServices(id_, force_update));
85 void SetActivelyRefreshServices(bool actively_refresh_services) override {
86 DVLOG(1) << "ServiceWatcher::SetActivelyRefreshServices with id " << id_;
87 DCHECK(started_);
88 host_->Send(new LocalDiscoveryMsg_SetActivelyRefreshServices(
89 id_, actively_refresh_services));
92 std::string GetServiceType() const override { return service_type_; }
94 private:
95 scoped_refptr<ServiceDiscoveryHostClient> host_;
96 const std::string service_type_;
97 const uint64 id_;
98 bool started_;
101 class ServiceDiscoveryHostClient::ServiceResolverProxy
102 : public ServiceResolver {
103 public:
104 ServiceResolverProxy(ServiceDiscoveryHostClient* host,
105 const std::string& service_name,
106 const ServiceResolver::ResolveCompleteCallback& callback)
107 : host_(host),
108 service_name_(service_name),
109 id_(host->RegisterResolverCallback(callback)),
110 started_(false) {
113 ~ServiceResolverProxy() override {
114 DVLOG(1) << "~ServiceResolverProxy with id " << id_;
115 host_->UnregisterResolverCallback(id_);
116 if (started_)
117 host_->Send(new LocalDiscoveryMsg_DestroyResolver(id_));
120 void StartResolving() override {
121 DVLOG(1) << "ServiceResolverProxy::StartResolving with id " << id_;
122 DCHECK(!started_);
123 host_->Send(new LocalDiscoveryMsg_ResolveService(id_, service_name_));
124 started_ = true;
127 std::string GetName() const override { return service_name_; }
129 private:
130 scoped_refptr<ServiceDiscoveryHostClient> host_;
131 const std::string service_name_;
132 const uint64 id_;
133 bool started_;
136 class ServiceDiscoveryHostClient::LocalDomainResolverProxy
137 : public LocalDomainResolver {
138 public:
139 LocalDomainResolverProxy(ServiceDiscoveryHostClient* host,
140 const std::string& domain,
141 net::AddressFamily address_family,
142 const LocalDomainResolver::IPAddressCallback& callback)
143 : host_(host),
144 domain_(domain),
145 address_family_(address_family),
146 id_(host->RegisterLocalDomainResolverCallback(callback)),
147 started_(false) {
150 ~LocalDomainResolverProxy() override {
151 DVLOG(1) << "~LocalDomainResolverProxy with id " << id_;
152 host_->UnregisterLocalDomainResolverCallback(id_);
153 if (started_)
154 host_->Send(new LocalDiscoveryMsg_DestroyLocalDomainResolver(id_));
157 void Start() override {
158 DVLOG(1) << "LocalDomainResolverProxy::Start with id " << id_;
159 DCHECK(!started_);
160 host_->Send(new LocalDiscoveryMsg_ResolveLocalDomain(id_, domain_,
161 address_family_));
162 started_ = true;
165 private:
166 scoped_refptr<ServiceDiscoveryHostClient> host_;
167 std::string domain_;
168 net::AddressFamily address_family_;
169 const uint64 id_;
170 bool started_;
173 ServiceDiscoveryHostClient::ServiceDiscoveryHostClient() : current_id_(0) {
174 callback_runner_ = base::MessageLoop::current()->message_loop_proxy();
175 io_runner_ = BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
178 ServiceDiscoveryHostClient::~ServiceDiscoveryHostClient() {
179 DCHECK(service_watcher_callbacks_.empty());
180 DCHECK(service_resolver_callbacks_.empty());
181 DCHECK(domain_resolver_callbacks_.empty());
184 scoped_ptr<ServiceWatcher> ServiceDiscoveryHostClient::CreateServiceWatcher(
185 const std::string& service_type,
186 const ServiceWatcher::UpdatedCallback& callback) {
187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
188 return scoped_ptr<ServiceWatcher>(
189 new ServiceWatcherProxy(this, service_type, callback));
192 scoped_ptr<ServiceResolver> ServiceDiscoveryHostClient::CreateServiceResolver(
193 const std::string& service_name,
194 const ServiceResolver::ResolveCompleteCallback& callback) {
195 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
196 return scoped_ptr<ServiceResolver>(
197 new ServiceResolverProxy(this, service_name, callback));
200 scoped_ptr<LocalDomainResolver>
201 ServiceDiscoveryHostClient::CreateLocalDomainResolver(
202 const std::string& domain,
203 net::AddressFamily address_family,
204 const LocalDomainResolver::IPAddressCallback& callback) {
205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
206 return scoped_ptr<LocalDomainResolver>(new LocalDomainResolverProxy(
207 this, domain, address_family, callback));
210 uint64 ServiceDiscoveryHostClient::RegisterWatcherCallback(
211 const ServiceWatcher::UpdatedCallback& callback) {
212 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
213 DCHECK(!ContainsKey(service_watcher_callbacks_, current_id_ + 1));
214 service_watcher_callbacks_[++current_id_] = callback;
215 return current_id_;
218 uint64 ServiceDiscoveryHostClient::RegisterResolverCallback(
219 const ServiceResolver::ResolveCompleteCallback& callback) {
220 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
221 DCHECK(!ContainsKey(service_resolver_callbacks_, current_id_ + 1));
222 service_resolver_callbacks_[++current_id_] = callback;
223 return current_id_;
226 uint64 ServiceDiscoveryHostClient::RegisterLocalDomainResolverCallback(
227 const LocalDomainResolver::IPAddressCallback& callback) {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
229 DCHECK(!ContainsKey(domain_resolver_callbacks_, current_id_ + 1));
230 domain_resolver_callbacks_[++current_id_] = callback;
231 return current_id_;
234 void ServiceDiscoveryHostClient::UnregisterWatcherCallback(uint64 id) {
235 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
236 service_watcher_callbacks_.erase(id);
239 void ServiceDiscoveryHostClient::UnregisterResolverCallback(uint64 id) {
240 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
241 service_resolver_callbacks_.erase(id);
244 void ServiceDiscoveryHostClient::UnregisterLocalDomainResolverCallback(
245 uint64 id) {
246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
247 domain_resolver_callbacks_.erase(id);
250 void ServiceDiscoveryHostClient::Start(
251 const base::Closure& error_callback) {
252 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
253 DCHECK(!utility_host_);
254 DCHECK(error_callback_.is_null());
255 error_callback_ = error_callback;
256 io_runner_->PostTask(
257 FROM_HERE,
258 base::Bind(&ServiceDiscoveryHostClient::StartOnIOThread, this));
261 void ServiceDiscoveryHostClient::Shutdown() {
262 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
263 io_runner_->PostTask(
264 FROM_HERE,
265 base::Bind(&ServiceDiscoveryHostClient::ShutdownOnIOThread, this));
268 #if defined(OS_POSIX)
270 void ServiceDiscoveryHostClient::StartOnIOThread() {
271 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
272 DCHECK(!utility_host_);
273 BrowserThread::PostTaskAndReplyWithResult(
274 BrowserThread::FILE,
275 FROM_HERE,
276 base::Bind(&GetSocketsOnFileThread),
277 base::Bind(&ServiceDiscoveryHostClient::OnSocketsReady, this));
280 void ServiceDiscoveryHostClient::OnSocketsReady(const SocketInfoList& sockets) {
281 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
282 DCHECK(!utility_host_);
283 utility_host_ = UtilityProcessHost::Create(
284 this, base::MessageLoopProxy::current().get())->AsWeakPtr();
285 if (!utility_host_)
286 return;
287 utility_host_->EnableMDns();
288 utility_host_->StartBatchMode();
289 if (sockets.empty()) {
290 ShutdownOnIOThread();
291 return;
293 utility_host_->Send(new LocalDiscoveryMsg_SetSockets(sockets));
294 // Send messages for requests made during network enumeration.
295 for (size_t i = 0; i < delayed_messages_.size(); ++i)
296 utility_host_->Send(delayed_messages_[i]);
297 delayed_messages_.weak_clear();
300 #else // OS_POSIX
302 void ServiceDiscoveryHostClient::StartOnIOThread() {
303 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
304 DCHECK(!utility_host_);
305 utility_host_ = UtilityProcessHost::Create(
306 this, base::MessageLoopProxy::current().get())->AsWeakPtr();
307 if (!utility_host_)
308 return;
309 utility_host_->EnableMDns();
310 utility_host_->StartBatchMode();
311 // Windows does not enumerate networks here.
312 DCHECK(delayed_messages_.empty());
315 #endif // OS_POSIX
317 void ServiceDiscoveryHostClient::ShutdownOnIOThread() {
318 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
319 if (utility_host_) {
320 utility_host_->Send(new LocalDiscoveryMsg_ShutdownLocalDiscovery);
321 utility_host_->EndBatchMode();
322 utility_host_.reset();
324 error_callback_ = base::Closure();
327 void ServiceDiscoveryHostClient::Send(IPC::Message* msg) {
328 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
329 io_runner_->PostTask(
330 FROM_HERE,
331 base::Bind(&ServiceDiscoveryHostClient::SendOnIOThread, this, msg));
334 void ServiceDiscoveryHostClient::SendOnIOThread(IPC::Message* msg) {
335 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
336 if (utility_host_) {
337 utility_host_->Send(msg);
338 } else {
339 delayed_messages_.push_back(msg);
343 void ServiceDiscoveryHostClient::OnProcessCrashed(int exit_code) {
344 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
345 DCHECK(!utility_host_);
346 OnError();
349 bool ServiceDiscoveryHostClient::OnMessageReceived(
350 const IPC::Message& message) {
351 bool handled = true;
352 IPC_BEGIN_MESSAGE_MAP(ServiceDiscoveryHostClient, message)
353 IPC_MESSAGE_HANDLER(LocalDiscoveryHostMsg_Error, OnError)
354 IPC_MESSAGE_HANDLER(LocalDiscoveryHostMsg_WatcherCallback,
355 OnWatcherCallback)
356 IPC_MESSAGE_HANDLER(LocalDiscoveryHostMsg_ResolverCallback,
357 OnResolverCallback)
358 IPC_MESSAGE_HANDLER(LocalDiscoveryHostMsg_LocalDomainResolverCallback,
359 OnLocalDomainResolverCallback)
360 IPC_MESSAGE_UNHANDLED(handled = false)
361 IPC_END_MESSAGE_MAP()
362 return handled;
365 void ServiceDiscoveryHostClient::InvalidateWatchers() {
366 WatcherCallbacks service_watcher_callbacks;
367 service_watcher_callbacks_.swap(service_watcher_callbacks);
368 service_resolver_callbacks_.clear();
369 domain_resolver_callbacks_.clear();
371 for (WatcherCallbacks::iterator i = service_watcher_callbacks.begin();
372 i != service_watcher_callbacks.end(); i++) {
373 if (!i->second.is_null()) {
374 i->second.Run(ServiceWatcher::UPDATE_INVALIDATED, "");
379 void ServiceDiscoveryHostClient::OnError() {
380 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
381 if (!error_callback_.is_null())
382 callback_runner_->PostTask(FROM_HERE, error_callback_);
385 void ServiceDiscoveryHostClient::OnWatcherCallback(
386 uint64 id,
387 ServiceWatcher::UpdateType update,
388 const std::string& service_name) {
389 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
390 callback_runner_->PostTask(
391 FROM_HERE,
392 base::Bind(&ServiceDiscoveryHostClient::RunWatcherCallback, this, id,
393 update, service_name));
396 void ServiceDiscoveryHostClient::OnResolverCallback(
397 uint64 id,
398 ServiceResolver::RequestStatus status,
399 const ServiceDescription& description) {
400 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
401 callback_runner_->PostTask(
402 FROM_HERE,
403 base::Bind(&ServiceDiscoveryHostClient::RunResolverCallback, this, id,
404 status, description));
407 void ServiceDiscoveryHostClient::OnLocalDomainResolverCallback(
408 uint64 id,
409 bool success,
410 const net::IPAddressNumber& ip_address_ipv4,
411 const net::IPAddressNumber& ip_address_ipv6) {
412 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
413 callback_runner_->PostTask(
414 FROM_HERE,
415 base::Bind(&ServiceDiscoveryHostClient::RunLocalDomainResolverCallback,
416 this, id, success, ip_address_ipv4, ip_address_ipv6));
419 void ServiceDiscoveryHostClient::RunWatcherCallback(
420 uint64 id,
421 ServiceWatcher::UpdateType update,
422 const std::string& service_name) {
423 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
424 WatcherCallbacks::iterator it = service_watcher_callbacks_.find(id);
425 if (it != service_watcher_callbacks_.end() && !it->second.is_null())
426 it->second.Run(update, service_name);
429 void ServiceDiscoveryHostClient::RunResolverCallback(
430 uint64 id,
431 ServiceResolver::RequestStatus status,
432 const ServiceDescription& description) {
433 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
434 ResolverCallbacks::iterator it = service_resolver_callbacks_.find(id);
435 if (it != service_resolver_callbacks_.end() && !it->second.is_null())
436 it->second.Run(status, description);
439 void ServiceDiscoveryHostClient::RunLocalDomainResolverCallback(
440 uint64 id,
441 bool success,
442 const net::IPAddressNumber& ip_address_ipv4,
443 const net::IPAddressNumber& ip_address_ipv6) {
444 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
445 DomainResolverCallbacks::iterator it = domain_resolver_callbacks_.find(id);
446 if (it != domain_resolver_callbacks_.end() && !it->second.is_null())
447 it->second.Run(success, ip_address_ipv4, ip_address_ipv6);
450 } // namespace local_discovery