| 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 |