summaryrefslogtreecommitdiffstats
path: root/chrome/browser/local_discovery/service_discovery_client_utility.cc
blob: 9e2d5d719a072ac6fb097ce28e3df5ab99fd5cfc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// 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/metrics/histogram.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(BrowserThread::CurrentlyOn(BrowserThread::UI));
  return host_client_->CreateServiceWatcher(service_type, callback);
}

scoped_ptr<ServiceResolver>
ServiceDiscoveryClientUtility::CreateServiceResolver(
    const std::string& service_name,
    const ServiceResolver::ResolveCompleteCallback& callback) {
  DCHECK(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(BrowserThread::UI));
  return host_client_->CreateLocalDomainResolver(domain, address_family,
                                                 callback);
}

ServiceDiscoveryClientUtility::ServiceDiscoveryClientUtility()
    : restart_attempts_(kMaxRestartAttempts),
      weak_ptr_factory_(this) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
  StartNewClient();
}

ServiceDiscoveryClientUtility::~ServiceDiscoveryClientUtility() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
  host_client_->Shutdown();
}

void ServiceDiscoveryClientUtility::OnNetworkChanged(
    net::NetworkChangeNotifier::ConnectionType type) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  // Only network changes resets kMaxRestartAttempts.
  restart_attempts_ = kMaxRestartAttempts;
  ScheduleStartNewClient();
}

void ServiceDiscoveryClientUtility::ScheduleStartNewClient() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  host_client_->Shutdown();
  weak_ptr_factory_.InvalidateWeakPtrs();
  base::MessageLoop::current()->PostDelayedTask(
      FROM_HERE,
      base::Bind(&ServiceDiscoveryClientUtility::StartNewClient,
                 weak_ptr_factory_.GetWeakPtr()),
      base::TimeDelta::FromSeconds(kRestartDelayOnNetworkChangeSeconds));
}

void ServiceDiscoveryClientUtility::StartNewClient() {
  DCHECK(BrowserThread::CurrentlyOn(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::MessageLoop::current()->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