BookmarkManager: Fix 'new folder text field size changes on clicking it' issue.
[chromium-blink-merge.git] / chromecast / net / connectivity_checker_impl.cc
blobf82e578d160f31852dc245d1033464291be9c2ed
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/socket/ssl_client_socket.h"
18 #include "net/url_request/url_request_context.h"
19 #include "net/url_request/url_request_context_builder.h"
21 namespace chromecast {
23 namespace {
25 // How often connectivity checks are performed in seconds.
26 const unsigned int kConnectivityPeriodSeconds = 1;
28 // Number of consecutive connectivity check errors before status is changed
29 // to offline.
30 const unsigned int kNumErrorsToNotifyOffline = 3;
32 // Request timeout value in seconds.
33 const unsigned int kRequestTimeoutInSeconds = 3;
35 // Default url for connectivity checking.
36 const char kDefaultConnectivityCheckUrl[] =
37 "https://clients3.google.com/generate_204";
39 } // namespace
41 ConnectivityCheckerImpl::ConnectivityCheckerImpl(
42 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
43 : ConnectivityChecker(),
44 task_runner_(task_runner),
45 connected_(false),
46 check_errors_(0) {
47 DCHECK(task_runner_.get());
48 task_runner->PostTask(FROM_HERE,
49 base::Bind(&ConnectivityCheckerImpl::Initialize, this));
52 void ConnectivityCheckerImpl::Initialize() {
53 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
54 base::CommandLine::StringType check_url_str =
55 command_line->GetSwitchValueNative(switches::kConnectivityCheckUrl);
56 connectivity_check_url_.reset(new GURL(
57 check_url_str.empty() ? kDefaultConnectivityCheckUrl : check_url_str));
59 net::URLRequestContextBuilder builder;
60 builder.set_proxy_config_service(make_scoped_ptr(
61 new net::ProxyConfigServiceFixed(net::ProxyConfig::CreateDirect())));
62 builder.DisableHttpCache();
63 url_request_context_ = builder.Build().Pass();
65 net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
66 task_runner_->PostTask(FROM_HERE,
67 base::Bind(&ConnectivityCheckerImpl::Check, this));
70 ConnectivityCheckerImpl::~ConnectivityCheckerImpl() {
71 DCHECK(task_runner_.get());
72 net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
73 task_runner_->DeleteSoon(FROM_HERE, url_request_.release());
74 task_runner_->DeleteSoon(FROM_HERE, url_request_context_.release());
77 bool ConnectivityCheckerImpl::Connected() const {
78 return connected_;
81 void ConnectivityCheckerImpl::SetConnected(bool connected) {
82 if (connected_ == connected)
83 return;
85 connected_ = connected;
86 Notify(connected);
87 LOG(INFO) << "Global connection is: " << (connected ? "Up" : "Down");
90 void ConnectivityCheckerImpl::Check() {
91 if (!task_runner_->BelongsToCurrentThread()) {
92 task_runner_->PostTask(FROM_HERE,
93 base::Bind(&ConnectivityCheckerImpl::Check, this));
94 return;
96 DCHECK(url_request_context_.get());
98 // Don't check connectivity if network is offline, because Internet could be
99 // accessible via netifs ignored.
100 if (net::NetworkChangeNotifier::IsOffline())
101 return;
103 // If url_request_ is non-null, there is already a check going on. Don't
104 // start another.
105 if (url_request_.get())
106 return;
108 VLOG(1) << "Connectivity check: url=" << *connectivity_check_url_;
109 url_request_ = url_request_context_->CreateRequest(
110 *connectivity_check_url_, net::MAXIMUM_PRIORITY, this);
111 url_request_->set_method("HEAD");
112 url_request_->Start();
114 timeout_.Reset(base::Bind(&ConnectivityCheckerImpl::OnUrlRequestTimeout,
115 this));
116 // Exponential backoff for timeout in 3, 6 and 12 sec.
117 const int timeout = kRequestTimeoutInSeconds
118 << (check_errors_ > 2 ? 2 : check_errors_);
119 base::MessageLoop::current()->PostDelayedTask(
120 FROM_HERE,
121 timeout_.callback(),
122 base::TimeDelta::FromSeconds(timeout));
125 void ConnectivityCheckerImpl::OnNetworkChanged(
126 net::NetworkChangeNotifier::ConnectionType type) {
127 VLOG(2) << "OnNetworkChanged " << type;
128 Cancel();
130 if (type == net::NetworkChangeNotifier::CONNECTION_NONE) {
131 SetConnected(false);
132 return;
135 Check();
138 void ConnectivityCheckerImpl::OnResponseStarted(net::URLRequest* request) {
139 timeout_.Cancel();
140 int http_response_code =
141 (request->status().is_success() &&
142 request->response_info().headers.get() != NULL)
143 ? request->response_info().headers->response_code()
144 : net::HTTP_BAD_REQUEST;
146 // Clears resources.
147 url_request_.reset(NULL); // URLRequest::Cancel() is called in destructor.
149 if (http_response_code < 400) {
150 VLOG(1) << "Connectivity check succeeded";
151 check_errors_ = 0;
152 SetConnected(true);
153 return;
155 VLOG(1) << "Connectivity check failed: " << http_response_code;
156 OnUrlRequestError();
159 void ConnectivityCheckerImpl::OnReadCompleted(net::URLRequest* request,
160 int bytes_read) {
161 NOTREACHED();
164 void ConnectivityCheckerImpl::OnSSLCertificateError(
165 net::URLRequest* request,
166 const net::SSLInfo& ssl_info,
167 bool fatal) {
168 LOG(ERROR) << "OnSSLCertificateError: cert_status=" << ssl_info.cert_status;
169 timeout_.Cancel();
170 net::SSLClientSocket::ClearSessionCache();
171 OnUrlRequestError();
174 void ConnectivityCheckerImpl::OnUrlRequestError() {
175 ++check_errors_;
176 if (check_errors_ > kNumErrorsToNotifyOffline) {
177 check_errors_ = kNumErrorsToNotifyOffline;
178 SetConnected(false);
180 url_request_.reset(NULL);
181 // Check again.
182 task_runner_->PostDelayedTask(
183 FROM_HERE, base::Bind(&ConnectivityCheckerImpl::Check, this),
184 base::TimeDelta::FromSeconds(kConnectivityPeriodSeconds));
187 void ConnectivityCheckerImpl::OnUrlRequestTimeout() {
188 LOG(ERROR) << "time out";
189 OnUrlRequestError();
192 void ConnectivityCheckerImpl::Cancel() {
193 if (!url_request_.get())
194 return;
195 VLOG(2) << "Cancel connectivity check in progress";
196 timeout_.Cancel();
197 url_request_.reset(NULL); // URLRequest::Cancel() is called in destructor.
200 } // namespace chromecast