base/threading: remove ScopedTracker placed for experiments
[chromium-blink-merge.git] / chromecast / net / connectivity_checker_impl.cc
blobd298d1bbfde30758f0315488453892656a6f71f3
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_impl.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 connectivity check errors before status is changed
28 // to offline.
29 const unsigned int kNumErrorsToNotifyOffline = 3;
31 // Request timeout value in seconds.
32 const unsigned int kRequestTimeoutInSeconds = 3;
34 // Default url for connectivity checking.
35 const char kDefaultConnectivityCheckUrl[] =
36 "https://clients3.google.com/generate_204";
38 } // namespace
40 ConnectivityCheckerImpl::ConnectivityCheckerImpl(
41 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
42 : ConnectivityChecker(),
43 task_runner_(task_runner),
44 connected_(false),
45 check_errors_(0) {
46 DCHECK(task_runner_.get());
47 task_runner->PostTask(FROM_HERE,
48 base::Bind(&ConnectivityCheckerImpl::Initialize, this));
51 void ConnectivityCheckerImpl::Initialize() {
52 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
53 base::CommandLine::StringType check_url_str =
54 command_line->GetSwitchValueNative(switches::kConnectivityCheckUrl);
55 connectivity_check_url_.reset(new GURL(
56 check_url_str.empty() ? kDefaultConnectivityCheckUrl : check_url_str));
58 net::URLRequestContextBuilder builder;
59 builder.set_proxy_config_service(
60 new net::ProxyConfigServiceFixed(net::ProxyConfig::CreateDirect()));
61 builder.DisableHttpCache();
62 url_request_context_.reset(builder.Build());
64 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
65 task_runner_->PostTask(FROM_HERE,
66 base::Bind(&ConnectivityCheckerImpl::Check, this));
69 ConnectivityCheckerImpl::~ConnectivityCheckerImpl() {
70 DCHECK(task_runner_.get());
71 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
72 task_runner_->DeleteSoon(FROM_HERE, url_request_.release());
73 task_runner_->DeleteSoon(FROM_HERE, url_request_context_.release());
76 bool ConnectivityCheckerImpl::Connected() const {
77 return connected_;
80 void ConnectivityCheckerImpl::SetConnected(bool connected) {
81 if (connected_ == connected)
82 return;
84 connected_ = connected;
85 Notify(connected);
86 LOG(INFO) << "Global connection is: " << (connected ? "Up" : "Down");
89 void ConnectivityCheckerImpl::Check() {
90 if (!task_runner_->BelongsToCurrentThread()) {
91 task_runner_->PostTask(FROM_HERE,
92 base::Bind(&ConnectivityCheckerImpl::Check, this));
93 return;
95 DCHECK(url_request_context_.get());
97 // Don't check connectivity if network is offline, because Internet could be
98 // accessible via netifs ignored.
99 if (net::NetworkChangeNotifier::IsOffline())
100 return;
102 // If url_request_ is non-null, there is already a check going on. Don't
103 // start another.
104 if (url_request_.get())
105 return;
107 VLOG(1) << "Connectivity check: url=" << *connectivity_check_url_;
108 url_request_ = url_request_context_->CreateRequest(
109 *connectivity_check_url_, net::MAXIMUM_PRIORITY, this);
110 url_request_->set_method("HEAD");
111 url_request_->Start();
113 timeout_.Reset(base::Bind(&ConnectivityCheckerImpl::OnUrlRequestTimeout,
114 this));
115 base::MessageLoop::current()->PostDelayedTask(
116 FROM_HERE,
117 timeout_.callback(),
118 base::TimeDelta::FromSeconds(kRequestTimeoutInSeconds));
121 void ConnectivityCheckerImpl::OnNetworkChanged(
122 net::NetworkChangeNotifier::ConnectionType type) {
123 VLOG(2) << "OnNetworkChanged " << type;
124 Cancel();
126 if (type == net::NetworkChangeNotifier::CONNECTION_NONE) {
127 SetConnected(false);
128 return;
131 Check();
134 void ConnectivityCheckerImpl::OnResponseStarted(net::URLRequest* request) {
135 timeout_.Cancel();
136 int http_response_code =
137 (request->status().is_success() &&
138 request->response_info().headers.get() != NULL)
139 ? request->response_info().headers->response_code()
140 : net::HTTP_BAD_REQUEST;
142 // Clears resources.
143 url_request_.reset(NULL); // URLRequest::Cancel() is called in destructor.
145 if (http_response_code < 400) {
146 VLOG(1) << "Connectivity check succeeded";
147 check_errors_ = 0;
148 SetConnected(true);
149 return;
151 VLOG(1) << "Connectivity check failed: " << http_response_code;
152 OnUrlRequestError();
155 void ConnectivityCheckerImpl::OnReadCompleted(net::URLRequest* request,
156 int bytes_read) {
157 NOTREACHED();
160 void ConnectivityCheckerImpl::OnSSLCertificateError(
161 net::URLRequest* request,
162 const net::SSLInfo& ssl_info,
163 bool fatal) {
164 LOG(ERROR) << "OnSSLCertificateError: cert_status=" << ssl_info.cert_status;
165 timeout_.Cancel();
166 OnUrlRequestError();
169 void ConnectivityCheckerImpl::OnUrlRequestError() {
170 ++check_errors_;
171 if (check_errors_ > kNumErrorsToNotifyOffline) {
172 check_errors_ = kNumErrorsToNotifyOffline;
173 SetConnected(false);
175 url_request_.reset(NULL);
176 // Check again.
177 task_runner_->PostDelayedTask(
178 FROM_HERE, base::Bind(&ConnectivityCheckerImpl::Check, this),
179 base::TimeDelta::FromSeconds(kConnectivityPeriodSeconds));
182 void ConnectivityCheckerImpl::OnUrlRequestTimeout() {
183 LOG(ERROR) << "time out";
184 OnUrlRequestError();
187 void ConnectivityCheckerImpl::Cancel() {
188 if (!url_request_.get())
189 return;
190 VLOG(2) << "Cancel connectivity check in progress";
191 timeout_.Cancel();
192 url_request_.reset(NULL); // URLRequest::Cancel() is called in destructor.
195 } // namespace chromecast