100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com// Copyright 2014 The Chromium Authors. All rights reserved.
200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com// Use of this source code is governed by a BSD-style license that can be
300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com// found in the LICENSE file.
400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com#include "chrome/browser/local_discovery/service_discovery_client_utility.h"
600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com#include "base/metrics/histogram.h"
800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com#include "chrome/browser/local_discovery/service_discovery_host_client.h"
900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com#include "content/public/browser/browser_thread.h"
10a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.org
11a574866c0e4b1539098e64422f59d01c80cea6cfbashi@chromium.orgnamespace local_discovery {
1200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
1300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comusing content::BrowserThread;
1400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
1500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comnamespace {
1600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comconst int kMaxRestartAttempts = 10;
1700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comconst int kRestartDelayOnNetworkChangeSeconds = 3;
1800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comconst int kReportSuccessAfterSeconds = 10;
1900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
2000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
2100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comscoped_ptr<ServiceWatcher> ServiceDiscoveryClientUtility::CreateServiceWatcher(
2200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    const std::string& service_type,
2300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    const ServiceWatcher::UpdatedCallback& callback) {
2400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  return host_client_->CreateServiceWatcher(service_type, callback);
2600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
2700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
2800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comscoped_ptr<ServiceResolver>
2900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comServiceDiscoveryClientUtility::CreateServiceResolver(
3000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    const std::string& service_name,
3100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    const ServiceResolver::ResolveCompleteCallback& callback) {
3200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  return host_client_->CreateServiceResolver(service_name, callback);
3400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
3500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
3600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comscoped_ptr<LocalDomainResolver>
3700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comServiceDiscoveryClientUtility::CreateLocalDomainResolver(
3800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    const std::string& domain,
3900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    net::AddressFamily address_family,
4000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    const LocalDomainResolver::IPAddressCallback& callback) {
4100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
4200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  return host_client_->CreateLocalDomainResolver(domain, address_family,
4300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                                                 callback);
4400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
4526afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.org
4626afae8d52d90e194bad9876776d68bc3bb3a1adbashi@chromium.orgServiceDiscoveryClientUtility::ServiceDiscoveryClientUtility()
4778a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com    : restart_attempts_(kMaxRestartAttempts),
4878a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com      weak_ptr_factory_(this) {
4978a8baafff49244c7f9427ad72115ff1ad28e310bashi@google.com  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
5000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
5100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  StartNewClient();
5200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
5300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
5400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comServiceDiscoveryClientUtility::~ServiceDiscoveryClientUtility() {
5500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
5600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
5700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  host_client_->Shutdown();
5800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
5900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
6000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comvoid ServiceDiscoveryClientUtility::OnNetworkChanged(
6100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    net::NetworkChangeNotifier::ConnectionType type) {
6200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
6300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  // Only network changes resets kMaxRestartAttempts.
6400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  restart_attempts_ = kMaxRestartAttempts;
6500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  ScheduleStartNewClient();
6600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
6700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
6800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comvoid ServiceDiscoveryClientUtility::ScheduleStartNewClient() {
6900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
7000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  host_client_->Shutdown();
7100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  weak_ptr_factory_.InvalidateWeakPtrs();
7200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  base::MessageLoop::current()->PostDelayedTask(
7300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      FROM_HERE,
7400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      base::Bind(&ServiceDiscoveryClientUtility::StartNewClient,
7500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                 weak_ptr_factory_.GetWeakPtr()),
7600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com      base::TimeDelta::FromSeconds(kRestartDelayOnNetworkChangeSeconds));
7700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
7800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
7900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comvoid ServiceDiscoveryClientUtility::StartNewClient() {
8000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
8100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  scoped_refptr<ServiceDiscoveryHostClient> old_client = host_client_;
8200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if ((restart_attempts_--) > 0) {
8300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    host_client_ = new ServiceDiscoveryHostClient();
8400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    host_client_->Start(
8500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        base::Bind(&ServiceDiscoveryClientUtility::ScheduleStartNewClient,
8600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                   weak_ptr_factory_.GetWeakPtr()));
8700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
8800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    base::MessageLoop::current()->PostDelayedTask(
8900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        FROM_HERE,
9000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        base::Bind(&ServiceDiscoveryClientUtility::ReportSuccess,
9100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                   weak_ptr_factory_.GetWeakPtr()),
9200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com        base::TimeDelta::FromSeconds(kReportSuccessAfterSeconds));
9300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  } else {
9400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    restart_attempts_ = -1;
9500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    ReportSuccess();
9600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  }
9700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  // Run when host_client_ is created. Callbacks created by InvalidateWatchers
9800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  // may create new watchers.
9900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  if (old_client.get())
10000b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com    old_client->InvalidateWatchers();
10100b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
10200b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
10300b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.comvoid ServiceDiscoveryClientUtility::ReportSuccess() {
10400b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com  UMA_HISTOGRAM_COUNTS_100("LocalDiscovery.ClientRestartAttempts",
10500b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com                           kMaxRestartAttempts - restart_attempts_);
10600b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}
10700b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com
10800b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com}  // namespace local_discovery
10900b790a7ad0d65b066a61760f58e7dbfc055cd2dbashi@google.com