blob: 4b9242ac4f73b8091ccc987ac3acbb9fd0926000 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/local_discovery/service_discovery_client_utility.h"
#include "base/location.h"
#include "base/metrics/histogram.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "chrome/browser/local_discovery/service_discovery_host_client.h"
#include "content/public/browser/browser_thread.h"
namespace local_discovery {
using content::BrowserThread;
namespace {
const int kMaxRestartAttempts = 10;
const int kRestartDelayOnNetworkChangeSeconds = 3;
const int kReportSuccessAfterSeconds = 10;
}
scoped_ptr<ServiceWatcher> ServiceDiscoveryClientUtility::CreateServiceWatcher(
const std::string& service_type,
const ServiceWatcher::UpdatedCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return host_client_->CreateServiceWatcher(service_type, callback);
}
scoped_ptr<ServiceResolver>
ServiceDiscoveryClientUtility::CreateServiceResolver(
const std::string& service_name,
const ServiceResolver::ResolveCompleteCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return host_client_->CreateServiceResolver(service_name, callback);
}
scoped_ptr<LocalDomainResolver>
ServiceDiscoveryClientUtility::CreateLocalDomainResolver(
const std::string& domain,
net::AddressFamily address_family,
const LocalDomainResolver::IPAddressCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return host_client_->CreateLocalDomainResolver(domain, address_family,
callback);
}
ServiceDiscoveryClientUtility::ServiceDiscoveryClientUtility()
: restart_attempts_(kMaxRestartAttempts),
weak_ptr_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
StartNewClient();
}
ServiceDiscoveryClientUtility::~ServiceDiscoveryClientUtility() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
host_client_->Shutdown();
}
void ServiceDiscoveryClientUtility::OnNetworkChanged(
net::NetworkChangeNotifier::ConnectionType type) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Only network changes resets kMaxRestartAttempts.
restart_attempts_ = kMaxRestartAttempts;
ScheduleStartNewClient();
}
void ServiceDiscoveryClientUtility::ScheduleStartNewClient() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
host_client_->Shutdown();
weak_ptr_factory_.InvalidateWeakPtrs();
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::Bind(&ServiceDiscoveryClientUtility::StartNewClient,
weak_ptr_factory_.GetWeakPtr()),
base::TimeDelta::FromSeconds(kRestartDelayOnNetworkChangeSeconds));
}
void ServiceDiscoveryClientUtility::StartNewClient() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
scoped_refptr<ServiceDiscoveryHostClient> old_client = host_client_;
if ((restart_attempts_--) > 0) {
host_client_ = new ServiceDiscoveryHostClient();
host_client_->Start(
base::Bind(&ServiceDiscoveryClientUtility::ScheduleStartNewClient,
weak_ptr_factory_.GetWeakPtr()));
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::Bind(&ServiceDiscoveryClientUtility::ReportSuccess,
weak_ptr_factory_.GetWeakPtr()),
base::TimeDelta::FromSeconds(kReportSuccessAfterSeconds));
} else {
restart_attempts_ = -1;
ReportSuccess();
}
// Run when host_client_ is created. Callbacks created by InvalidateWatchers
// may create new watchers.
if (old_client.get())
old_client->InvalidateWatchers();
}
void ServiceDiscoveryClientUtility::ReportSuccess() {
UMA_HISTOGRAM_COUNTS_100("LocalDiscovery.ClientRestartAttempts",
kMaxRestartAttempts - restart_attempts_);
}
} // namespace local_discovery