OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "chromecast/net/connectivity_checker.h" | |
6 | |
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" | |
19 | |
20 namespace chromecast { | |
21 | |
22 namespace { | |
23 | |
24 // How often we perform connectivity checks in seconds | |
gunsch
2015/02/20 01:56:03
nit: avoid first-person references in comments, he
derekjchow1
2015/02/20 02:24:16
Done.
| |
25 const unsigned int kConnectivityPeriodSeconds = 1; | |
26 | |
27 // Number of consecutive bad responses we receive before we change connectivity | |
28 // to offline | |
29 const unsigned int kNumBadResponses = 3; | |
30 | |
31 // Default url for connectivity checking. | |
32 const char kDefaultConnectivityCheckUrl[] = | |
33 "https://clients3.google.com/generate_204"; | |
34 | |
35 } // namespace | |
36 | |
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)); | |
47 } | |
48 | |
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)); | |
55 | |
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()); | |
61 | |
62 net::NetworkChangeNotifier::AddConnectionTypeObserver(this); | |
63 if (!net::NetworkChangeNotifier::IsOffline()) { | |
64 loop_proxy_->PostTask(FROM_HERE, | |
65 base::Bind(&ConnectivityChecker::Check, this)); | |
66 } | |
67 } | |
68 | |
69 ConnectivityChecker::~ConnectivityChecker() { | |
70 DCHECK(loop_proxy_.get()); | |
71 loop_proxy_->DeleteSoon(FROM_HERE, url_request_context_.release()); | |
72 } | |
73 | |
74 void ConnectivityChecker::AddConnectivityObserver( | |
75 ConnectivityObserver* observer) { | |
76 connectivity_observer_list_->AddObserver(observer); | |
77 } | |
78 | |
79 void ConnectivityChecker::RemoveConnectivityObserver( | |
80 ConnectivityObserver* observer) { | |
81 connectivity_observer_list_->RemoveObserver(observer); | |
82 } | |
83 | |
84 bool ConnectivityChecker::Connected() const { | |
85 return connected_; | |
86 } | |
87 | |
88 void ConnectivityChecker::SetConnectivity(bool connected) { | |
89 if (connected) | |
90 bad_responses_ = 0; | |
gunsch
2015/02/20 01:57:28
how about moving "bad_responses_ = 0" to "OnRespon
derekjchow1
2015/02/20 02:24:16
Done.
| |
91 | |
92 if (connected_ == connected) | |
93 return; | |
94 | |
95 connected_ = connected; | |
96 connectivity_observer_list_->Notify( | |
97 FROM_HERE, &ConnectivityObserver::OnConnectivityChanged, connected); | |
98 LOG(INFO) << "Global connection is: " << (connected ? "Up" : "Down"); | |
99 } | |
100 | |
101 void ConnectivityChecker::Check() { | |
102 if (!loop_proxy_->BelongsToCurrentThread()) { | |
103 loop_proxy_->PostTask(FROM_HERE, | |
104 base::Bind(&ConnectivityChecker::Check, this)); | |
105 return; | |
106 } | |
107 DCHECK(url_request_context_.get()); | |
108 | |
109 // If url_request_ is non-null, there is already a check going on. Don't | |
110 // start another. | |
111 if (url_request_.get()) | |
112 return; | |
113 | |
114 VLOG(2) << "Connectivity check: url=" << *connectivity_check_url_; | |
115 url_request_ = url_request_context_->CreateRequest( | |
116 *connectivity_check_url_, net::MAXIMUM_PRIORITY, this, NULL); | |
117 url_request_->set_method("HEAD"); | |
118 url_request_->Start(); | |
119 } | |
120 | |
121 void ConnectivityChecker::OnConnectionTypeChanged( | |
122 net::NetworkChangeNotifier::ConnectionType type) { | |
123 Cancel(); | |
124 | |
125 // If there is no connection, set connectivity to false. Otherwise retest | |
126 // connectivity | |
127 if (type == net::NetworkChangeNotifier::CONNECTION_NONE) { | |
128 SetConnectivity(false); | |
129 } else { | |
130 Check(); | |
131 } | |
132 } | |
133 | |
134 void ConnectivityChecker::OnResponseStarted(net::URLRequest* request) { | |
135 int http_response_code = | |
136 (request->status().is_success() && | |
137 request->response_info().headers.get() != NULL) | |
138 ? request->response_info().headers->response_code() | |
139 : net::HTTP_BAD_REQUEST; | |
140 | |
141 // Clears resources. | |
142 url_request_.reset(NULL); // URLRequest::Cancel() is called in destructor. | |
143 | |
144 if (http_response_code < 400) { | |
145 SetConnectivity(true); | |
146 return; | |
147 } | |
148 | |
149 ++bad_responses_; | |
150 if (bad_responses_ > kNumBadResponses) { | |
151 bad_responses_ = kNumBadResponses; | |
152 SetConnectivity(false); | |
153 } | |
154 | |
155 // Check again | |
156 if (!net::NetworkChangeNotifier::IsOffline()) { | |
157 loop_proxy_->PostDelayedTask( | |
158 FROM_HERE, base::Bind(&ConnectivityChecker::Check, this), | |
159 base::TimeDelta::FromSeconds(kConnectivityPeriodSeconds)); | |
160 } | |
161 } | |
162 | |
163 void ConnectivityChecker::OnReadCompleted(net::URLRequest* request, | |
164 int bytes_read) { | |
165 NOTREACHED(); | |
166 } | |
167 | |
168 void ConnectivityChecker::Cancel() { | |
169 if (url_request_.get()) { | |
170 VLOG(2) << "Cancel connectivity check in progress"; | |
171 url_request_.reset(NULL); // URLRequest::Cancel() is called in destructor. | |
172 } | |
173 } | |
174 | |
175 } // namespace chromecast | |
OLD | NEW |