OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/local_discovery/service_discovery_client_mdns.h" | 5 #include "chrome/browser/local_discovery/service_discovery_client_mdns.h" |
6 | 6 |
7 #include "base/memory/scoped_vector.h" | 7 #include "base/memory/scoped_vector.h" |
8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 #include "chrome/common/local_discovery/service_discovery_client_impl.h" | 9 #include "chrome/common/local_discovery/service_discovery_client_impl.h" |
10 #include "content/public/browser/browser_thread.h" | 10 #include "content/public/browser/browser_thread.h" |
11 #include "net/dns/mdns_client.h" | 11 #include "net/dns/mdns_client.h" |
12 #include "net/udp/datagram_server_socket.h" | 12 #include "net/udp/datagram_server_socket.h" |
13 | 13 |
14 namespace local_discovery { | 14 namespace local_discovery { |
15 | 15 |
16 using content::BrowserThread; | 16 using content::BrowserThread; |
17 | 17 |
18 // Base class for objects returned by ServiceDiscoveryClient implementation. | 18 // Base class for objects returned by ServiceDiscoveryClient implementation. |
19 // Handles interaction of client code on UI thread end net code on mdns thread. | 19 // Handles interaction of client code on UI thread end net code on mdns thread. |
20 class ServiceDiscoveryClientMdns::Proxy { | 20 class ServiceDiscoveryClientMdns::Proxy { |
21 public: | 21 public: |
22 typedef base::WeakPtr<Proxy> WeakPtr; | 22 typedef base::WeakPtr<Proxy> WeakPtr; |
23 | 23 |
24 explicit Proxy(ServiceDiscoveryClientMdns* client) | 24 explicit Proxy(ServiceDiscoveryClientMdns* client) |
25 : client_(client), | 25 : client_(client), |
26 weak_ptr_factory_(this) { | 26 weak_ptr_factory_(this) { |
27 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 27 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
28 client_->proxies_.AddObserver(this); | 28 client_->proxies_.AddObserver(this); |
29 } | 29 } |
30 | 30 |
31 virtual ~Proxy() { | 31 virtual ~Proxy() { |
32 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 32 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
33 client_->proxies_.RemoveObserver(this); | 33 client_->proxies_.RemoveObserver(this); |
34 } | 34 } |
35 | 35 |
36 // Returns true if object is not yet shutdown. | 36 // Returns true if object is not yet shutdown. |
37 virtual bool IsValid() = 0; | 37 virtual bool IsValid() = 0; |
38 | 38 |
39 // Notifies proxies that mDNS layer is going to be destroyed. | 39 // Notifies proxies that mDNS layer is going to be destroyed. |
40 virtual void OnMdnsDestroy() = 0; | 40 virtual void OnMdnsDestroy() = 0; |
41 | 41 |
42 // Notifies proxies that new mDNS instance is ready. | 42 // Notifies proxies that new mDNS instance is ready. |
43 virtual void OnNewMdnsReady() { | 43 virtual void OnNewMdnsReady() { |
44 DCHECK(!client_->need_dalay_mdns_tasks_); | 44 DCHECK(!client_->need_dalay_mdns_tasks_); |
45 if (IsValid()) { | 45 if (IsValid()) { |
46 for (size_t i = 0; i < delayed_tasks_.size(); ++i) | 46 for (size_t i = 0; i < delayed_tasks_.size(); ++i) |
47 client_->mdns_runner_->PostTask(FROM_HERE, delayed_tasks_[i]); | 47 client_->mdns_runner_->PostTask(FROM_HERE, delayed_tasks_[i]); |
48 } | 48 } |
49 delayed_tasks_.clear(); | 49 delayed_tasks_.clear(); |
50 } | 50 } |
51 | 51 |
52 // Runs callback using this method to abort callback if instance of |Proxy| | 52 // Runs callback using this method to abort callback if instance of |Proxy| |
53 // is deleted. | 53 // is deleted. |
54 void RunCallback(const base::Closure& callback) { | 54 void RunCallback(const base::Closure& callback) { |
55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 55 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
56 callback.Run(); | 56 callback.Run(); |
57 } | 57 } |
58 | 58 |
59 protected: | 59 protected: |
60 void PostToMdnsThread(const base::Closure& task) { | 60 void PostToMdnsThread(const base::Closure& task) { |
61 DCHECK(IsValid()); | 61 DCHECK(IsValid()); |
62 // The first task on IO thread for each |mdns_| instance must be |InitMdns|. | 62 // The first task on IO thread for each |mdns_| instance must be |InitMdns|. |
63 // |OnInterfaceListReady| could be delayed by |GetMDnsInterfacesToBind| | 63 // |OnInterfaceListReady| could be delayed by |GetMDnsInterfacesToBind| |
64 // running on FILE thread, so |PostToMdnsThread| could be called to post | 64 // running on FILE thread, so |PostToMdnsThread| could be called to post |
65 // task for |mdns_| that is not initialized yet. | 65 // task for |mdns_| that is not initialized yet. |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 }; | 311 }; |
312 | 312 |
313 } // namespace | 313 } // namespace |
314 | 314 |
315 ServiceDiscoveryClientMdns::ServiceDiscoveryClientMdns() | 315 ServiceDiscoveryClientMdns::ServiceDiscoveryClientMdns() |
316 : mdns_runner_( | 316 : mdns_runner_( |
317 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)), | 317 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)), |
318 restart_attempts_(0), | 318 restart_attempts_(0), |
319 need_dalay_mdns_tasks_(true), | 319 need_dalay_mdns_tasks_(true), |
320 weak_ptr_factory_(this) { | 320 weak_ptr_factory_(this) { |
321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 321 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
322 net::NetworkChangeNotifier::AddNetworkChangeObserver(this); | 322 net::NetworkChangeNotifier::AddNetworkChangeObserver(this); |
323 StartNewClient(); | 323 StartNewClient(); |
324 } | 324 } |
325 | 325 |
326 scoped_ptr<ServiceWatcher> ServiceDiscoveryClientMdns::CreateServiceWatcher( | 326 scoped_ptr<ServiceWatcher> ServiceDiscoveryClientMdns::CreateServiceWatcher( |
327 const std::string& service_type, | 327 const std::string& service_type, |
328 const ServiceWatcher::UpdatedCallback& callback) { | 328 const ServiceWatcher::UpdatedCallback& callback) { |
329 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 329 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
330 return scoped_ptr<ServiceWatcher>( | 330 return scoped_ptr<ServiceWatcher>( |
331 new ServiceWatcherProxy(this, service_type, callback)); | 331 new ServiceWatcherProxy(this, service_type, callback)); |
332 } | 332 } |
333 | 333 |
334 scoped_ptr<ServiceResolver> ServiceDiscoveryClientMdns::CreateServiceResolver( | 334 scoped_ptr<ServiceResolver> ServiceDiscoveryClientMdns::CreateServiceResolver( |
335 const std::string& service_name, | 335 const std::string& service_name, |
336 const ServiceResolver::ResolveCompleteCallback& callback) { | 336 const ServiceResolver::ResolveCompleteCallback& callback) { |
337 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 337 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
338 return scoped_ptr<ServiceResolver>( | 338 return scoped_ptr<ServiceResolver>( |
339 new ServiceResolverProxy(this, service_name, callback)); | 339 new ServiceResolverProxy(this, service_name, callback)); |
340 } | 340 } |
341 | 341 |
342 scoped_ptr<LocalDomainResolver> | 342 scoped_ptr<LocalDomainResolver> |
343 ServiceDiscoveryClientMdns::CreateLocalDomainResolver( | 343 ServiceDiscoveryClientMdns::CreateLocalDomainResolver( |
344 const std::string& domain, | 344 const std::string& domain, |
345 net::AddressFamily address_family, | 345 net::AddressFamily address_family, |
346 const LocalDomainResolver::IPAddressCallback& callback) { | 346 const LocalDomainResolver::IPAddressCallback& callback) { |
347 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 347 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
348 return scoped_ptr<LocalDomainResolver>( | 348 return scoped_ptr<LocalDomainResolver>( |
349 new LocalDomainResolverProxy(this, domain, address_family, callback)); | 349 new LocalDomainResolverProxy(this, domain, address_family, callback)); |
350 } | 350 } |
351 | 351 |
352 ServiceDiscoveryClientMdns::~ServiceDiscoveryClientMdns() { | 352 ServiceDiscoveryClientMdns::~ServiceDiscoveryClientMdns() { |
353 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 353 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
354 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); | 354 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); |
355 DestroyMdns(); | 355 DestroyMdns(); |
356 } | 356 } |
357 | 357 |
358 void ServiceDiscoveryClientMdns::OnNetworkChanged( | 358 void ServiceDiscoveryClientMdns::OnNetworkChanged( |
359 net::NetworkChangeNotifier::ConnectionType type) { | 359 net::NetworkChangeNotifier::ConnectionType type) { |
360 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 360 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
361 // Only network changes resets counter. | 361 // Only network changes resets counter. |
362 restart_attempts_ = 0; | 362 restart_attempts_ = 0; |
363 ScheduleStartNewClient(); | 363 ScheduleStartNewClient(); |
364 } | 364 } |
365 | 365 |
366 void ServiceDiscoveryClientMdns::ScheduleStartNewClient() { | 366 void ServiceDiscoveryClientMdns::ScheduleStartNewClient() { |
367 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 367 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
368 OnBeforeMdnsDestroy(); | 368 OnBeforeMdnsDestroy(); |
369 if (restart_attempts_ < kMaxRestartAttempts) { | 369 if (restart_attempts_ < kMaxRestartAttempts) { |
370 base::MessageLoop::current()->PostDelayedTask( | 370 base::MessageLoop::current()->PostDelayedTask( |
371 FROM_HERE, | 371 FROM_HERE, |
372 base::Bind(&ServiceDiscoveryClientMdns::StartNewClient, | 372 base::Bind(&ServiceDiscoveryClientMdns::StartNewClient, |
373 weak_ptr_factory_.GetWeakPtr()), | 373 weak_ptr_factory_.GetWeakPtr()), |
374 base::TimeDelta::FromSeconds( | 374 base::TimeDelta::FromSeconds( |
375 kRestartDelayOnNetworkChangeSeconds * (1 << restart_attempts_))); | 375 kRestartDelayOnNetworkChangeSeconds * (1 << restart_attempts_))); |
376 } else { | 376 } else { |
377 ReportSuccess(); | 377 ReportSuccess(); |
378 } | 378 } |
379 } | 379 } |
380 | 380 |
381 void ServiceDiscoveryClientMdns::StartNewClient() { | 381 void ServiceDiscoveryClientMdns::StartNewClient() { |
382 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 382 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
383 ++restart_attempts_; | 383 ++restart_attempts_; |
384 DestroyMdns(); | 384 DestroyMdns(); |
385 mdns_.reset(net::MDnsClient::CreateDefault().release()); | 385 mdns_.reset(net::MDnsClient::CreateDefault().release()); |
386 client_.reset(new ServiceDiscoveryClientImpl(mdns_.get())); | 386 client_.reset(new ServiceDiscoveryClientImpl(mdns_.get())); |
387 BrowserThread::PostTaskAndReplyWithResult( | 387 BrowserThread::PostTaskAndReplyWithResult( |
388 BrowserThread::FILE, | 388 BrowserThread::FILE, |
389 FROM_HERE, | 389 FROM_HERE, |
390 base::Bind(&net::GetMDnsInterfacesToBind), | 390 base::Bind(&net::GetMDnsInterfacesToBind), |
391 base::Bind(&ServiceDiscoveryClientMdns::OnInterfaceListReady, | 391 base::Bind(&ServiceDiscoveryClientMdns::OnInterfaceListReady, |
392 weak_ptr_factory_.GetWeakPtr())); | 392 weak_ptr_factory_.GetWeakPtr())); |
393 } | 393 } |
394 | 394 |
395 void ServiceDiscoveryClientMdns::OnInterfaceListReady( | 395 void ServiceDiscoveryClientMdns::OnInterfaceListReady( |
396 const net::InterfaceIndexFamilyList& interfaces) { | 396 const net::InterfaceIndexFamilyList& interfaces) { |
397 mdns_runner_->PostTask( | 397 mdns_runner_->PostTask( |
398 FROM_HERE, | 398 FROM_HERE, |
399 base::Bind(&InitMdns, | 399 base::Bind(&InitMdns, |
400 base::Bind(&ServiceDiscoveryClientMdns::OnMdnsInitialized, | 400 base::Bind(&ServiceDiscoveryClientMdns::OnMdnsInitialized, |
401 weak_ptr_factory_.GetWeakPtr()), | 401 weak_ptr_factory_.GetWeakPtr()), |
402 interfaces, | 402 interfaces, |
403 base::Unretained(mdns_.get()))); | 403 base::Unretained(mdns_.get()))); |
404 } | 404 } |
405 | 405 |
406 void ServiceDiscoveryClientMdns::OnMdnsInitialized(bool success) { | 406 void ServiceDiscoveryClientMdns::OnMdnsInitialized(bool success) { |
407 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 407 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
408 if (!success) { | 408 if (!success) { |
409 ScheduleStartNewClient(); | 409 ScheduleStartNewClient(); |
410 return; | 410 return; |
411 } | 411 } |
412 ReportSuccess(); | 412 ReportSuccess(); |
413 | 413 |
414 // Initialization is done, no need to delay tasks. | 414 // Initialization is done, no need to delay tasks. |
415 need_dalay_mdns_tasks_ = false; | 415 need_dalay_mdns_tasks_ = false; |
416 FOR_EACH_OBSERVER(Proxy, proxies_, OnNewMdnsReady()); | 416 FOR_EACH_OBSERVER(Proxy, proxies_, OnNewMdnsReady()); |
417 } | 417 } |
418 | 418 |
419 void ServiceDiscoveryClientMdns::ReportSuccess() { | 419 void ServiceDiscoveryClientMdns::ReportSuccess() { |
420 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 420 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
421 UMA_HISTOGRAM_COUNTS_100("LocalDiscovery.ClientRestartAttempts", | 421 UMA_HISTOGRAM_COUNTS_100("LocalDiscovery.ClientRestartAttempts", |
422 restart_attempts_); | 422 restart_attempts_); |
423 } | 423 } |
424 | 424 |
425 void ServiceDiscoveryClientMdns::OnBeforeMdnsDestroy() { | 425 void ServiceDiscoveryClientMdns::OnBeforeMdnsDestroy() { |
426 need_dalay_mdns_tasks_ = true; | 426 need_dalay_mdns_tasks_ = true; |
427 weak_ptr_factory_.InvalidateWeakPtrs(); | 427 weak_ptr_factory_.InvalidateWeakPtrs(); |
428 FOR_EACH_OBSERVER(Proxy, proxies_, OnMdnsDestroy()); | 428 FOR_EACH_OBSERVER(Proxy, proxies_, OnMdnsDestroy()); |
429 } | 429 } |
430 | 430 |
431 void ServiceDiscoveryClientMdns::DestroyMdns() { | 431 void ServiceDiscoveryClientMdns::DestroyMdns() { |
432 OnBeforeMdnsDestroy(); | 432 OnBeforeMdnsDestroy(); |
433 // After calling |Proxy::OnMdnsDestroy| all references to client_ and mdns_ | 433 // After calling |Proxy::OnMdnsDestroy| all references to client_ and mdns_ |
434 // should be destroyed. | 434 // should be destroyed. |
435 if (client_) | 435 if (client_) |
436 mdns_runner_->DeleteSoon(FROM_HERE, client_.release()); | 436 mdns_runner_->DeleteSoon(FROM_HERE, client_.release()); |
437 if (mdns_) | 437 if (mdns_) |
438 mdns_runner_->DeleteSoon(FROM_HERE, mdns_.release()); | 438 mdns_runner_->DeleteSoon(FROM_HERE, mdns_.release()); |
439 } | 439 } |
440 | 440 |
441 } // namespace local_discovery | 441 } // namespace local_discovery |
OLD | NEW |