Roll src/third_party/skia 2469c99:48c3534
[chromium-blink-merge.git] / chromecast / net / connectivity_checker.cc
blobde3081291f3e2e71b2b25757b05af569871d756f
1 // Copyright 2015 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.
5 #include "chromecast/net/connectivity_checker.h"
7 #include "base/command_line.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "chromecast/net/net_switches.h"
11 #include "net/base/request_priority.h"
12 #include "net/http/http_response_headers.h"
13 #include "net/http/http_response_info.h"
14 #include "net/http/http_status_code.h"
15 #include "net/proxy/proxy_config.h"
16 #include "net/proxy/proxy_config_service_fixed.h"
17 #include "net/url_request/url_request_context.h"
18 #include "net/url_request/url_request_context_builder.h"
20 namespace chromecast {
22 namespace {
24 // How often connectivity checks are performed in seconds
25 const unsigned int kConnectivityPeriodSeconds = 1;
27 // Number of consecutive bad responses received before connectivity status is
28 // changed to offline
29 const unsigned int kNumBadResponses = 3;
31 // Default url for connectivity checking.
32 const char kDefaultConnectivityCheckUrl[] =
33 "https://clients3.google.com/generate_204";
35 } // namespace
37 ConnectivityChecker::ConnectivityChecker(
38 const scoped_refptr<base::MessageLoopProxy>& loop_proxy)
39 : connectivity_observer_list_(
40 new ObserverListThreadSafe<ConnectivityObserver>()),
41 loop_proxy_(loop_proxy),
42 connected_(false),
43 bad_responses_(0) {
44 DCHECK(loop_proxy_.get());
45 loop_proxy->PostTask(FROM_HERE,
46 base::Bind(&ConnectivityChecker::Initialize, this));
49 void ConnectivityChecker::Initialize() {
50 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
51 base::CommandLine::StringType check_url_str =
52 command_line->GetSwitchValueNative(switches::kConnectivityCheckUrl);
53 connectivity_check_url_.reset(new GURL(
54 check_url_str.empty() ? kDefaultConnectivityCheckUrl : check_url_str));
56 net::URLRequestContextBuilder builder;
57 builder.set_proxy_config_service(
58 new net::ProxyConfigServiceFixed(net::ProxyConfig::CreateDirect()));
59 builder.DisableHttpCache();
60 url_request_context_.reset(builder.Build());
62 net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
63 net::NetworkChangeNotifier::AddIPAddressObserver(this);
64 loop_proxy_->PostTask(FROM_HERE,
65 base::Bind(&ConnectivityChecker::Check, this));
68 ConnectivityChecker::~ConnectivityChecker() {
69 DCHECK(loop_proxy_.get());
70 net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
71 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
72 loop_proxy_->DeleteSoon(FROM_HERE, url_request_context_.release());
73 loop_proxy_->DeleteSoon(FROM_HERE, url_request_.release());
76 void ConnectivityChecker::AddConnectivityObserver(
77 ConnectivityObserver* observer) {
78 connectivity_observer_list_->AddObserver(observer);
81 void ConnectivityChecker::RemoveConnectivityObserver(
82 ConnectivityObserver* observer) {
83 connectivity_observer_list_->RemoveObserver(observer);
86 bool ConnectivityChecker::Connected() const {
87 return connected_;
90 void ConnectivityChecker::SetConnectivity(bool connected) {
91 if (connected_ == connected)
92 return;
94 connected_ = connected;
95 connectivity_observer_list_->Notify(
96 FROM_HERE, &ConnectivityObserver::OnConnectivityChanged, connected);
97 LOG(INFO) << "Global connection is: " << (connected ? "Up" : "Down");
100 void ConnectivityChecker::Check() {
101 if (!loop_proxy_->BelongsToCurrentThread()) {
102 loop_proxy_->PostTask(FROM_HERE,
103 base::Bind(&ConnectivityChecker::Check, this));
104 return;
106 DCHECK(url_request_context_.get());
108 // Don't check connectivity if network is offline, because internet could be
109 // accessible via netifs ignored.
110 if (net::NetworkChangeNotifier::IsOffline())
111 return;
113 // If url_request_ is non-null, there is already a check going on. Don't
114 // start another.
115 if (url_request_.get())
116 return;
118 VLOG(1) << "Connectivity check: url=" << *connectivity_check_url_;
119 url_request_ = url_request_context_->CreateRequest(
120 *connectivity_check_url_, net::MAXIMUM_PRIORITY, this);
121 url_request_->set_method("HEAD");
122 url_request_->Start();
125 void ConnectivityChecker::OnConnectionTypeChanged(
126 net::NetworkChangeNotifier::ConnectionType type) {
127 VLOG(2) << "OnConnectionTypeChanged " << type;
128 if (type == net::NetworkChangeNotifier::CONNECTION_NONE)
129 SetConnectivity(false);
131 Cancel();
132 Check();
135 void ConnectivityChecker::OnIPAddressChanged() {
136 VLOG(2) << "OnIPAddressChanged";
138 Cancel();
139 Check();
142 void ConnectivityChecker::OnResponseStarted(net::URLRequest* request) {
143 int http_response_code =
144 (request->status().is_success() &&
145 request->response_info().headers.get() != NULL)
146 ? request->response_info().headers->response_code()
147 : net::HTTP_BAD_REQUEST;
149 // Clears resources.
150 url_request_.reset(NULL); // URLRequest::Cancel() is called in destructor.
152 if (http_response_code < 400) {
153 VLOG(1) << "Connectivity check succeeded";
154 bad_responses_ = 0;
155 SetConnectivity(true);
156 return;
159 VLOG(1) << "Connectivity check failed: " << http_response_code;
160 ++bad_responses_;
161 if (bad_responses_ > kNumBadResponses) {
162 bad_responses_ = kNumBadResponses;
163 SetConnectivity(false);
166 // Check again
167 loop_proxy_->PostDelayedTask(
168 FROM_HERE, base::Bind(&ConnectivityChecker::Check, this),
169 base::TimeDelta::FromSeconds(kConnectivityPeriodSeconds));
172 void ConnectivityChecker::OnReadCompleted(net::URLRequest* request,
173 int bytes_read) {
174 NOTREACHED();
177 void ConnectivityChecker::Cancel() {
178 if (url_request_.get()) {
179 VLOG(2) << "Cancel connectivity check in progress";
180 url_request_.reset(NULL); // URLRequest::Cancel() is called in destructor.
184 } // namespace chromecast