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 3// found in the LICENSE file. 4 5#include "chrome/browser/local_discovery/service_discovery_client_utility.h" 6 7#include "base/metrics/histogram.h" 8#include "chrome/browser/local_discovery/service_discovery_host_client.h" 9#include "content/public/browser/browser_thread.h" 10 11namespace local_discovery { 12 13using content::BrowserThread; 14 15namespace { 16const int kMaxRestartAttempts = 10; 17const int kRestartDelayOnNetworkChangeSeconds = 3; 18const int kReportSuccessAfterSeconds = 10; 19} 20 21scoped_ptr<ServiceWatcher> ServiceDiscoveryClientUtility::CreateServiceWatcher( 22 const std::string& service_type, 23 const ServiceWatcher::UpdatedCallback& callback) { 24 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 25 return host_client_->CreateServiceWatcher(service_type, callback); 26} 27 28scoped_ptr<ServiceResolver> 29ServiceDiscoveryClientUtility::CreateServiceResolver( 30 const std::string& service_name, 31 const ServiceResolver::ResolveCompleteCallback& callback) { 32 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 33 return host_client_->CreateServiceResolver(service_name, callback); 34} 35 36scoped_ptr<LocalDomainResolver> 37ServiceDiscoveryClientUtility::CreateLocalDomainResolver( 38 const std::string& domain, 39 net::AddressFamily address_family, 40 const LocalDomainResolver::IPAddressCallback& callback) { 41 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 42 return host_client_->CreateLocalDomainResolver(domain, address_family, 43 callback); 44} 45 46ServiceDiscoveryClientUtility::ServiceDiscoveryClientUtility() 47 : restart_attempts_(kMaxRestartAttempts), 48 weak_ptr_factory_(this) { 49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 50 net::NetworkChangeNotifier::AddNetworkChangeObserver(this); 51 StartNewClient(); 52} 53 54ServiceDiscoveryClientUtility::~ServiceDiscoveryClientUtility() { 55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 56 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); 57 host_client_->Shutdown(); 58} 59 60void ServiceDiscoveryClientUtility::OnNetworkChanged( 61 net::NetworkChangeNotifier::ConnectionType type) { 62 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 63 // Only network changes resets kMaxRestartAttempts. 64 restart_attempts_ = kMaxRestartAttempts; 65 ScheduleStartNewClient(); 66} 67 68void ServiceDiscoveryClientUtility::ScheduleStartNewClient() { 69 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 70 host_client_->Shutdown(); 71 weak_ptr_factory_.InvalidateWeakPtrs(); 72 base::MessageLoop::current()->PostDelayedTask( 73 FROM_HERE, 74 base::Bind(&ServiceDiscoveryClientUtility::StartNewClient, 75 weak_ptr_factory_.GetWeakPtr()), 76 base::TimeDelta::FromSeconds(kRestartDelayOnNetworkChangeSeconds)); 77} 78 79void ServiceDiscoveryClientUtility::StartNewClient() { 80 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 81 scoped_refptr<ServiceDiscoveryHostClient> old_client = host_client_; 82 if ((restart_attempts_--) > 0) { 83 host_client_ = new ServiceDiscoveryHostClient(); 84 host_client_->Start( 85 base::Bind(&ServiceDiscoveryClientUtility::ScheduleStartNewClient, 86 weak_ptr_factory_.GetWeakPtr())); 87 88 base::MessageLoop::current()->PostDelayedTask( 89 FROM_HERE, 90 base::Bind(&ServiceDiscoveryClientUtility::ReportSuccess, 91 weak_ptr_factory_.GetWeakPtr()), 92 base::TimeDelta::FromSeconds(kReportSuccessAfterSeconds)); 93 } else { 94 restart_attempts_ = -1; 95 ReportSuccess(); 96 } 97 // Run when host_client_ is created. Callbacks created by InvalidateWatchers 98 // may create new watchers. 99 if (old_client.get()) 100 old_client->InvalidateWatchers(); 101} 102 103void ServiceDiscoveryClientUtility::ReportSuccess() { 104 UMA_HISTOGRAM_COUNTS_100("LocalDiscovery.ClientRestartAttempts", 105 kMaxRestartAttempts - restart_attempts_); 106} 107 108} // namespace local_discovery 109