Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: chrome/browser/chromeos/net/network_portal_detector_impl.cc

Issue 183973029: Refactoring of the NetworkPortalDetector. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixes. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/net/network_portal_detector_impl.h" 5 #include "chrome/browser/chromeos/net/network_portal_detector_impl.h"
6 6
7 #include <algorithm>
8
7 #include "base/bind.h" 9 #include "base/bind.h"
8 #include "base/command_line.h" 10 #include "base/command_line.h"
9 #include "base/logging.h" 11 #include "base/logging.h"
10 #include "base/message_loop/message_loop.h" 12 #include "base/message_loop/message_loop.h"
11 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
12 #include "chrome/browser/chrome_notification_types.h" 14 #include "chrome/browser/chrome_notification_types.h"
13 #include "chromeos/dbus/dbus_thread_manager.h" 15 #include "chromeos/dbus/dbus_thread_manager.h"
14 #include "chromeos/dbus/shill_profile_client.h" 16 #include "chromeos/dbus/shill_profile_client.h"
15 #include "chromeos/network/network_state.h" 17 #include "chromeos/network/network_state.h"
16 #include "chromeos/network/network_state_handler.h" 18 #include "chromeos/network/network_state_handler.h"
17 #include "content/public/browser/notification_service.h" 19 #include "content/public/browser/notification_service.h"
18 #include "grit/generated_resources.h" 20 #include "grit/generated_resources.h"
19 #include "net/http/http_status_code.h" 21 #include "net/http/http_status_code.h"
20 #include "third_party/cros_system_api/dbus/service_constants.h" 22 #include "third_party/cros_system_api/dbus/service_constants.h"
21 #include "ui/base/l10n/l10n_util.h" 23 #include "ui/base/l10n/l10n_util.h"
22 24
23 using captive_portal::CaptivePortalDetector; 25 using captive_portal::CaptivePortalDetector;
24 26
25 namespace chromeos { 27 namespace chromeos {
26 28
27 namespace { 29 namespace {
28 30
29 // Maximum number of portal detections for the same default network
30 // after network change.
31 const int kMaxRequestAttempts = 3;
32
33 // Minimum timeout between consecutive portal checks for the same
34 // network.
35 const int kMinTimeBetweenAttemptsSec = 3;
36
37 // Delay before portal detection caused by changes in proxy settings. 31 // Delay before portal detection caused by changes in proxy settings.
38 const int kProxyChangeDelaySec = 1; 32 const int kProxyChangeDelaySec = 1;
39 33
40 // Delay between consecutive portal checks for a network in lazy mode. 34 const NetworkState* DefaultNetwork() {
41 const int kLazyCheckIntervalSec = 5; 35 return NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
36 }
42 37
43 void RecordDiscrepancyWithShill( 38 void RecordDiscrepancyWithShill(
44 const NetworkState* network, 39 const NetworkState* network,
45 const NetworkPortalDetector::CaptivePortalStatus status) { 40 const NetworkPortalDetector::CaptivePortalStatus status) {
46 if (network->connection_state() == shill::kStateOnline) { 41 if (network->connection_state() == shill::kStateOnline) {
47 UMA_HISTOGRAM_ENUMERATION( 42 UMA_HISTOGRAM_ENUMERATION(
48 NetworkPortalDetectorImpl::kShillOnlineHistogram, 43 NetworkPortalDetectorImpl::kShillOnlineHistogram,
49 status, 44 status,
50 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT); 45 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
51 } else if (network->connection_state() == shill::kStatePortal) { 46 } else if (network->connection_state() == shill::kStatePortal) {
52 UMA_HISTOGRAM_ENUMERATION( 47 UMA_HISTOGRAM_ENUMERATION(
53 NetworkPortalDetectorImpl::kShillPortalHistogram, 48 NetworkPortalDetectorImpl::kShillPortalHistogram,
54 status, 49 status,
55 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT); 50 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
56 } else if (network->connection_state() == shill::kStateOffline) { 51 } else if (network->connection_state() == shill::kStateOffline) {
57 UMA_HISTOGRAM_ENUMERATION( 52 UMA_HISTOGRAM_ENUMERATION(
58 NetworkPortalDetectorImpl::kShillOfflineHistogram, 53 NetworkPortalDetectorImpl::kShillOfflineHistogram,
59 status, 54 status,
60 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT); 55 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
61 } 56 }
62 } 57 }
63 58
64 } // namespace 59 } // namespace
65 60
66 //////////////////////////////////////////////////////////////////////////////// 61 ////////////////////////////////////////////////////////////////////////////////
67 // NetworkPortalDetectorImpl, public: 62 // NetworkPortalDetectorImpl, public:
68 63
69 const char NetworkPortalDetectorImpl::kDetectionResultHistogram[] = 64 const char NetworkPortalDetectorImpl::kDetectionResultHistogram[] =
70 "CaptivePortal.OOBE.DetectionResult"; 65 "CaptivePortal.OOBE.DetectionResult";
71 const char NetworkPortalDetectorImpl::kDetectionDurationHistogram[] = 66 const char NetworkPortalDetectorImpl::kDetectionDurationHistogram[] =
72 "CaptivePortal.OOBE.DetectionDuration"; 67 "CaptivePortal.OOBE.DetectionDuration";
73 const char NetworkPortalDetectorImpl::kShillOnlineHistogram[] = 68 const char NetworkPortalDetectorImpl::kShillOnlineHistogram[] =
74 "CaptivePortal.OOBE.DiscrepancyWithShill_Online"; 69 "CaptivePortal.OOBE.DiscrepancyWithShill_Online";
75 const char NetworkPortalDetectorImpl::kShillPortalHistogram[] = 70 const char NetworkPortalDetectorImpl::kShillPortalHistogram[] =
76 "CaptivePortal.OOBE.DiscrepancyWithShill_RestrictedPool"; 71 "CaptivePortal.OOBE.DiscrepancyWithShill_RestrictedPool";
77 const char NetworkPortalDetectorImpl::kShillOfflineHistogram[] = 72 const char NetworkPortalDetectorImpl::kShillOfflineHistogram[] =
78 "CaptivePortal.OOBE.DiscrepancyWithShill_Offline"; 73 "CaptivePortal.OOBE.DiscrepancyWithShill_Offline";
79 74
80 NetworkPortalDetectorImpl::NetworkPortalDetectorImpl( 75 NetworkPortalDetectorImpl::NetworkPortalDetectorImpl(
81 const scoped_refptr<net::URLRequestContextGetter>& request_context) 76 const scoped_refptr<net::URLRequestContextGetter>& request_context)
82 : state_(STATE_IDLE), 77 : state_(STATE_IDLE),
83 test_url_(CaptivePortalDetector::kDefaultURL), 78 test_url_(CaptivePortalDetector::kDefaultURL),
84 enabled_(false), 79 enabled_(false),
85 weak_ptr_factory_(this), 80 weak_factory_(this),
86 attempt_count_(0), 81 attempt_count_(0),
87 lazy_detection_enabled_(false), 82 strategy_(PortalDetectorStrategy::CreateById(
88 lazy_check_interval_(base::TimeDelta::FromSeconds(kLazyCheckIntervalSec)), 83 PortalDetectorStrategy::STRATEGY_ID_LOGIN_SCREEN)) {
89 min_time_between_attempts_(
90 base::TimeDelta::FromSeconds(kMinTimeBetweenAttemptsSec)),
91 request_timeout_for_testing_initialized_(false) {
92 captive_portal_detector_.reset(new CaptivePortalDetector(request_context)); 84 captive_portal_detector_.reset(new CaptivePortalDetector(request_context));
85 strategy_->set_delegate(this);
93 86
94 registrar_.Add(this, 87 registrar_.Add(this,
95 chrome::NOTIFICATION_LOGIN_PROXY_CHANGED, 88 chrome::NOTIFICATION_LOGIN_PROXY_CHANGED,
96 content::NotificationService::AllSources()); 89 content::NotificationService::AllSources());
97 registrar_.Add(this, 90 registrar_.Add(this,
98 chrome::NOTIFICATION_AUTH_SUPPLIED, 91 chrome::NOTIFICATION_AUTH_SUPPLIED,
99 content::NotificationService::AllSources()); 92 content::NotificationService::AllSources());
100 registrar_.Add(this, 93 registrar_.Add(this,
101 chrome::NOTIFICATION_AUTH_CANCELLED, 94 chrome::NOTIFICATION_AUTH_CANCELLED,
102 content::NotificationService::AllSources()); 95 content::NotificationService::AllSources());
103 96
104 NetworkHandler::Get()->network_state_handler()->AddObserver( 97 NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE);
105 this, FROM_HERE);
106 } 98 }
107 99
108 NetworkPortalDetectorImpl::~NetworkPortalDetectorImpl() { 100 NetworkPortalDetectorImpl::~NetworkPortalDetectorImpl() {
109 DCHECK(CalledOnValidThread()); 101 DCHECK(CalledOnValidThread());
110 102
111 detection_task_.Cancel(); 103 attempt_task_.Cancel();
112 detection_timeout_.Cancel(); 104 attempt_timeout_.Cancel();
113 105
114 captive_portal_detector_->Cancel(); 106 captive_portal_detector_->Cancel();
115 captive_portal_detector_.reset(); 107 captive_portal_detector_.reset();
116 observers_.Clear(); 108 observers_.Clear();
117 if (NetworkHandler::IsInitialized()) { 109 if (NetworkHandler::IsInitialized()) {
118 NetworkHandler::Get()->network_state_handler()->RemoveObserver( 110 NetworkHandler::Get()->network_state_handler()->RemoveObserver(this,
119 this, FROM_HERE); 111 FROM_HERE);
120 } 112 }
121 } 113 }
122 114
123 void NetworkPortalDetectorImpl::AddObserver(Observer* observer) { 115 void NetworkPortalDetectorImpl::AddObserver(Observer* observer) {
124 DCHECK(CalledOnValidThread()); 116 DCHECK(CalledOnValidThread());
125 if (!observer || observers_.HasObserver(observer)) 117 if (observer && !observers_.HasObserver(observer))
126 return; 118 observers_.AddObserver(observer);
127 observers_.AddObserver(observer);
128 } 119 }
129 120
130 void NetworkPortalDetectorImpl::AddAndFireObserver(Observer* observer) { 121 void NetworkPortalDetectorImpl::AddAndFireObserver(Observer* observer) {
131 DCHECK(CalledOnValidThread()); 122 DCHECK(CalledOnValidThread());
132 if (!observer) 123 if (!observer)
133 return; 124 return;
134 AddObserver(observer); 125 AddObserver(observer);
135 CaptivePortalState portal_state; 126 CaptivePortalState portal_state;
136 const NetworkState* network = 127 const NetworkState* network = DefaultNetwork();
137 NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
138 if (network) 128 if (network)
139 portal_state = GetCaptivePortalState(network->path()); 129 portal_state = GetCaptivePortalState(network->path());
140 observer->OnPortalDetectionCompleted(network, portal_state); 130 observer->OnPortalDetectionCompleted(network, portal_state);
141 } 131 }
142 132
143 void NetworkPortalDetectorImpl::RemoveObserver(Observer* observer) { 133 void NetworkPortalDetectorImpl::RemoveObserver(Observer* observer) {
144 DCHECK(CalledOnValidThread()); 134 DCHECK(CalledOnValidThread());
145 if (observer) 135 if (observer)
146 observers_.RemoveObserver(observer); 136 observers_.RemoveObserver(observer);
147 } 137 }
148 138
149 bool NetworkPortalDetectorImpl::IsEnabled() { 139 bool NetworkPortalDetectorImpl::IsEnabled() { return enabled_; }
150 return enabled_;
151 }
152 140
153 void NetworkPortalDetectorImpl::Enable(bool start_detection) { 141 void NetworkPortalDetectorImpl::Enable(bool start_detection) {
154 DCHECK(CalledOnValidThread()); 142 DCHECK(CalledOnValidThread());
155 if (enabled_) 143 if (enabled_)
156 return; 144 return;
145
146 DCHECK(is_idle());
157 enabled_ = true; 147 enabled_ = true;
158 DCHECK(!IsPortalCheckPending()); 148
159 DCHECK(!IsCheckingForPortal()); 149 const NetworkState* network = DefaultNetwork();
160 DCHECK(!lazy_detection_enabled()); 150 if (!start_detection || !network)
161 if (!start_detection)
162 return; 151 return;
163 state_ = STATE_IDLE; 152 portal_state_map_.erase(network->path());
164 attempt_count_ = 0; 153 StartDetection();
165 const NetworkState* default_network =
166 NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
167 if (!default_network)
168 return;
169 portal_state_map_.erase(default_network->path());
170 DCHECK(CanPerformDetection());
171 DetectCaptivePortal(base::TimeDelta());
172 } 154 }
173 155
174 NetworkPortalDetectorImpl::CaptivePortalState 156 NetworkPortalDetectorImpl::CaptivePortalState
175 NetworkPortalDetectorImpl::GetCaptivePortalState( 157 NetworkPortalDetectorImpl::GetCaptivePortalState(
176 const std::string& service_path) { 158 const std::string& service_path) {
177 DCHECK(CalledOnValidThread()); 159 DCHECK(CalledOnValidThread());
178 CaptivePortalStateMap::const_iterator it = 160 CaptivePortalStateMap::const_iterator it =
179 portal_state_map_.find(service_path); 161 portal_state_map_.find(service_path);
180 if (it == portal_state_map_.end()) 162 if (it == portal_state_map_.end())
181 return CaptivePortalState(); 163 return CaptivePortalState();
182 return it->second; 164 return it->second;
183 } 165 }
184 166
185 bool NetworkPortalDetectorImpl::StartDetectionIfIdle() { 167 bool NetworkPortalDetectorImpl::StartDetectionIfIdle() {
186 if (IsPortalCheckPending() || IsCheckingForPortal()) 168 if (!is_idle())
187 return false; 169 return false;
188 if (!CanPerformDetection()) 170 StartDetection();
189 attempt_count_ = 0;
190 DCHECK(CanPerformDetection());
191 DetectCaptivePortal(base::TimeDelta());
192 return true; 171 return true;
193 } 172 }
194 173
195 void NetworkPortalDetectorImpl::EnableLazyDetection() { 174 void NetworkPortalDetectorImpl::EnableErrorScreenStrategy() {
196 if (lazy_detection_enabled()) 175 if (strategy_->Id() == PortalDetectorStrategy::STRATEGY_ID_ERROR_SCREEN)
197 return; 176 return;
198 lazy_detection_enabled_ = true; 177 VLOG(1) << "Error screen detection strategy enabled.";
199 VLOG(1) << "Lazy detection mode enabled."; 178 strategy_ = PortalDetectorStrategy::CreateById(
179 PortalDetectorStrategy::STRATEGY_ID_ERROR_SCREEN);
180 strategy_->set_delegate(this);
200 StartDetectionIfIdle(); 181 StartDetectionIfIdle();
201 } 182 }
202 183
203 void NetworkPortalDetectorImpl::DisableLazyDetection() { 184 void NetworkPortalDetectorImpl::DisableErrorScreenStrategy() {
204 if (!lazy_detection_enabled()) 185 if (strategy_->Id() != PortalDetectorStrategy::STRATEGY_ID_ERROR_SCREEN)
205 return; 186 return;
206 lazy_detection_enabled_ = false; 187 VLOG(1) << "Error screen detection strategy disabled.";
207 if (attempt_count_ == kMaxRequestAttempts && IsPortalCheckPending()) 188 strategy_ = PortalDetectorStrategy::CreateById(
208 CancelPortalDetection(); 189 PortalDetectorStrategy::STRATEGY_ID_LOGIN_SCREEN);
209 VLOG(1) << "Lazy detection mode disabled."; 190 strategy_->set_delegate(this);
191 StopDetection();
210 } 192 }
211 193
212 void NetworkPortalDetectorImpl::DefaultNetworkChanged( 194 void NetworkPortalDetectorImpl::DefaultNetworkChanged(
213 const NetworkState* default_network) { 195 const NetworkState* default_network) {
214 DCHECK(CalledOnValidThread()); 196 DCHECK(CalledOnValidThread());
215 197
216 if (!default_network) { 198 if (!default_network) {
217 default_network_name_.clear(); 199 default_network_name_.clear();
218 default_network_id_.clear(); 200 default_network_id_.clear();
219 201
220 CancelPortalDetection(); 202 StopDetection();
221 203
222 CaptivePortalState state; 204 CaptivePortalState state;
223 state.status = CAPTIVE_PORTAL_STATUS_OFFLINE; 205 state.status = CAPTIVE_PORTAL_STATUS_OFFLINE;
224 SetCaptivePortalState(NULL, state); 206 OnDetectionCompleted(NULL, state);
225 return; 207 return;
226 } 208 }
227 209
228 default_network_name_ = default_network->name(); 210 default_network_name_ = default_network->name();
229 default_network_id_ = default_network->guid(); 211 default_network_id_ = default_network->guid();
230 212
231 bool network_changed = (default_service_path_ != default_network->path()); 213 bool network_changed = (default_service_path_ != default_network->path());
232 default_service_path_ = default_network->path(); 214 default_service_path_ = default_network->path();
233 215
234 bool connection_state_changed = (default_connection_state_ != 216 bool connection_state_changed =
235 default_network->connection_state()); 217 (default_connection_state_ != default_network->connection_state());
236 default_connection_state_ = default_network->connection_state(); 218 default_connection_state_ = default_network->connection_state();
237 219
238 if (network_changed || connection_state_changed) { 220 if (network_changed || connection_state_changed)
239 attempt_count_ = 0; 221 StopDetection();
240 CancelPortalDetection();
241 }
242 222
243 if (CanPerformDetection() && 223 if (CanPerformAttempt() &&
244 NetworkState::StateIsConnected(default_connection_state_)) { 224 NetworkState::StateIsConnected(default_connection_state_)) {
245 // Initiate Captive Portal detection if network's captive 225 // Initiate Captive Portal detection if network's captive
246 // portal state is unknown (e.g. for freshly created networks), 226 // portal state is unknown (e.g. for freshly created networks),
247 // offline or if network connection state was changed. 227 // offline or if network connection state was changed.
248 CaptivePortalState state = GetCaptivePortalState(default_network->path()); 228 CaptivePortalState state = GetCaptivePortalState(default_network->path());
249 if (state.status == CAPTIVE_PORTAL_STATUS_UNKNOWN || 229 if (state.status == CAPTIVE_PORTAL_STATUS_UNKNOWN ||
250 state.status == CAPTIVE_PORTAL_STATUS_OFFLINE || 230 state.status == CAPTIVE_PORTAL_STATUS_OFFLINE ||
251 (!network_changed && connection_state_changed)) { 231 (!network_changed && connection_state_changed)) {
252 DetectCaptivePortal(base::TimeDelta()); 232 ScheduleAttempt(base::TimeDelta());
253 } 233 }
254 } 234 }
255 } 235 }
256 236
237 int NetworkPortalDetectorImpl::AttemptCount() { return attempt_count_; }
238
239 base::TimeTicks NetworkPortalDetectorImpl::AttemptStartTime() {
240 return attempt_start_time_;
241 }
242
243 base::TimeTicks NetworkPortalDetectorImpl::GetCurrentTimeTicks() {
244 if (time_ticks_for_testing_.is_null())
245 return base::TimeTicks::Now();
246 return time_ticks_for_testing_;
247 }
248
257 //////////////////////////////////////////////////////////////////////////////// 249 ////////////////////////////////////////////////////////////////////////////////
258 // NetworkPortalDetectorImpl, private: 250 // NetworkPortalDetectorImpl, private:
259 251
260 bool NetworkPortalDetectorImpl::CanPerformDetection() const { 252 void NetworkPortalDetectorImpl::StartDetection() {
261 if (IsPortalCheckPending() || IsCheckingForPortal()) 253 attempt_count_ = 0;
262 return false; 254 DCHECK(CanPerformAttempt());
263 return attempt_count_ < kMaxRequestAttempts || lazy_detection_enabled(); 255 detection_start_time_ = GetCurrentTimeTicks();
256 ScheduleAttempt(base::TimeDelta());
264 } 257 }
265 258
266 void NetworkPortalDetectorImpl::DetectCaptivePortal( 259 void NetworkPortalDetectorImpl::StopDetection() {
267 const base::TimeDelta& delay) { 260 attempt_task_.Cancel();
268 DCHECK(CanPerformDetection()); 261 attempt_timeout_.Cancel();
262 captive_portal_detector_->Cancel();
263 state_ = STATE_IDLE;
264 attempt_count_ = 0;
265 }
266
267 bool NetworkPortalDetectorImpl::CanPerformAttempt() const {
268 return is_idle() && strategy_->CanPerformAttempt();
269 }
270
271 void NetworkPortalDetectorImpl::ScheduleAttempt(const base::TimeDelta& delay) {
272 DCHECK(CanPerformAttempt());
269 273
270 if (!IsEnabled()) 274 if (!IsEnabled())
271 return; 275 return;
272 276
273 detection_task_.Cancel(); 277 attempt_task_.Cancel();
274 detection_timeout_.Cancel(); 278 attempt_timeout_.Cancel();
275 state_ = STATE_PORTAL_CHECK_PENDING; 279 state_ = STATE_PORTAL_CHECK_PENDING;
276 280
277 next_attempt_delay_ = delay; 281 next_attempt_delay_ = std::max(delay, strategy_->GetDelayTillNextAttempt());
278 if (attempt_count_ > 0) { 282 attempt_task_.Reset(base::Bind(&NetworkPortalDetectorImpl::StartAttempt,
279 base::TimeTicks now = GetCurrentTimeTicks(); 283 weak_factory_.GetWeakPtr()));
280 base::TimeDelta elapsed_time;
281
282 base::TimeDelta delay_between_attempts = min_time_between_attempts_;
283 if (attempt_count_ == kMaxRequestAttempts) {
284 DCHECK(lazy_detection_enabled());
285 delay_between_attempts = lazy_check_interval_;
286 }
287 if (now > attempt_start_time_)
288 elapsed_time = now - attempt_start_time_;
289 if (elapsed_time < delay_between_attempts &&
290 delay_between_attempts - elapsed_time > next_attempt_delay_) {
291 next_attempt_delay_ = delay_between_attempts - elapsed_time;
292 }
293 } else {
294 detection_start_time_ = GetCurrentTimeTicks();
295 }
296 detection_task_.Reset(
297 base::Bind(&NetworkPortalDetectorImpl::DetectCaptivePortalTask,
298 weak_ptr_factory_.GetWeakPtr()));
299 base::MessageLoop::current()->PostDelayedTask( 284 base::MessageLoop::current()->PostDelayedTask(
300 FROM_HERE, detection_task_.callback(), next_attempt_delay_); 285 FROM_HERE, attempt_task_.callback(), next_attempt_delay_);
301 } 286 }
302 287
303 void NetworkPortalDetectorImpl::DetectCaptivePortalTask() { 288 void NetworkPortalDetectorImpl::StartAttempt() {
304 DCHECK(IsPortalCheckPending()); 289 DCHECK(is_portal_check_pending());
305 290
306 state_ = STATE_CHECKING_FOR_PORTAL; 291 state_ = STATE_CHECKING_FOR_PORTAL;
307 attempt_start_time_ = GetCurrentTimeTicks(); 292 attempt_start_time_ = GetCurrentTimeTicks();
308 293
309 if (attempt_count_ < kMaxRequestAttempts) {
310 ++attempt_count_;
311 VLOG(1) << "Portal detection started: "
312 << "name=" << default_network_name_ << ", "
313 << "id=" << default_network_id_ << ", "
314 << "attempt=" << attempt_count_ << " of " << kMaxRequestAttempts;
315 } else {
316 DCHECK(lazy_detection_enabled());
317 VLOG(1) << "Lazy portal detection attempt started";
318 }
319
320 captive_portal_detector_->DetectCaptivePortal( 294 captive_portal_detector_->DetectCaptivePortal(
321 test_url_, 295 test_url_,
322 base::Bind(&NetworkPortalDetectorImpl::OnPortalDetectionCompleted, 296 base::Bind(&NetworkPortalDetectorImpl::OnAttemptCompleted,
323 weak_ptr_factory_.GetWeakPtr())); 297 weak_factory_.GetWeakPtr()));
324 detection_timeout_.Reset( 298 attempt_timeout_.Reset(
325 base::Bind(&NetworkPortalDetectorImpl::PortalDetectionTimeout, 299 base::Bind(&NetworkPortalDetectorImpl::OnAttemptTimeout,
326 weak_ptr_factory_.GetWeakPtr())); 300 weak_factory_.GetWeakPtr()));
327 base::TimeDelta request_timeout;
328 301
329 // For easier unit testing check for testing state is performed here
330 // and not in the GetRequestTimeoutSec().
331 if (request_timeout_for_testing_initialized_)
332 request_timeout = request_timeout_for_testing_;
333 else
334 request_timeout = base::TimeDelta::FromSeconds(GetRequestTimeoutSec());
335 base::MessageLoop::current()->PostDelayedTask( 302 base::MessageLoop::current()->PostDelayedTask(
336 FROM_HERE, detection_timeout_.callback(), request_timeout); 303 FROM_HERE,
304 attempt_timeout_.callback(),
305 strategy_->GetNextAttemptTimeout());
337 } 306 }
338 307
339 void NetworkPortalDetectorImpl::PortalDetectionTimeout() { 308 void NetworkPortalDetectorImpl::OnAttemptTimeout() {
340 DCHECK(CalledOnValidThread()); 309 DCHECK(CalledOnValidThread());
341 DCHECK(IsCheckingForPortal()); 310 DCHECK(is_checking_for_portal());
342 311
343 VLOG(1) << "Portal detection timeout: name=" << default_network_name_ << ", " 312 VLOG(1) << "Portal detection timeout: name=" << default_network_name_ << ", "
344 << "id=" << default_network_id_; 313 << "id=" << default_network_id_;
345 314
346 captive_portal_detector_->Cancel(); 315 captive_portal_detector_->Cancel();
347 CaptivePortalDetector::Results results; 316 CaptivePortalDetector::Results results;
348 results.result = captive_portal::RESULT_NO_RESPONSE; 317 results.result = captive_portal::RESULT_NO_RESPONSE;
349 OnPortalDetectionCompleted(results); 318 OnAttemptCompleted(results);
350 } 319 }
351 320
352 void NetworkPortalDetectorImpl::CancelPortalDetection() { 321 void NetworkPortalDetectorImpl::OnAttemptCompleted(
353 if (IsPortalCheckPending())
354 detection_task_.Cancel();
355 else if (IsCheckingForPortal())
356 captive_portal_detector_->Cancel();
357 detection_timeout_.Cancel();
358 state_ = STATE_IDLE;
359 }
360
361 void NetworkPortalDetectorImpl::OnPortalDetectionCompleted(
362 const CaptivePortalDetector::Results& results) { 322 const CaptivePortalDetector::Results& results) {
363 captive_portal::Result result = results.result; 323 captive_portal::Result result = results.result;
364 int response_code = results.response_code; 324 int response_code = results.response_code;
365 325
366 DCHECK(CalledOnValidThread()); 326 DCHECK(CalledOnValidThread());
367 DCHECK(IsCheckingForPortal()); 327 DCHECK(is_checking_for_portal());
368 328
369 VLOG(1) << "Portal detection completed: " 329 VLOG(1) << "Detection attempt completed: "
370 << "name=" << default_network_name_ << ", " 330 << "name=" << default_network_name_ << ", "
371 << "id=" << default_network_id_ << ", " 331 << "id=" << default_network_id_ << ", "
372 << "result=" 332 << "result="
373 << CaptivePortalDetector::CaptivePortalResultToString(results.result) 333 << CaptivePortalDetector::CaptivePortalResultToString(results.result)
374 << ", " 334 << ", "
375 << "response_code=" << results.response_code; 335 << "response_code=" << results.response_code;
376 336
377 state_ = STATE_IDLE; 337 state_ = STATE_IDLE;
378 detection_timeout_.Cancel(); 338 attempt_timeout_.Cancel();
339 ++attempt_count_;
379 340
380 const NetworkState* default_network = 341 const NetworkState* network = DefaultNetwork();
381 NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
382 342
383 // If using a fake profile client, also fake being behind a captive portal 343 // If using a fake profile client, also fake being behind a captive portal
384 // if the default network is in portal state. 344 // if the default network is in portal state.
385 if (result != captive_portal::RESULT_NO_RESPONSE && 345 if (result != captive_portal::RESULT_NO_RESPONSE &&
386 DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface() && 346 DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface() &&
387 default_network && 347 network && network->connection_state() == shill::kStatePortal) {
388 default_network->connection_state() == shill::kStatePortal) {
389 result = captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL; 348 result = captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL;
390 response_code = 200; 349 response_code = 200;
391 } 350 }
392 351
393 CaptivePortalState state; 352 CaptivePortalState state;
394 state.response_code = response_code; 353 state.response_code = response_code;
395 switch (result) { 354 switch (result) {
396 case captive_portal::RESULT_NO_RESPONSE: 355 case captive_portal::RESULT_NO_RESPONSE:
397 if (state.response_code == net::HTTP_PROXY_AUTHENTICATION_REQUIRED) { 356 if (state.response_code == net::HTTP_PROXY_AUTHENTICATION_REQUIRED) {
398 state.status = CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED; 357 state.status = CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED;
399 SetCaptivePortalState(default_network, state); 358 } else if (CanPerformAttempt()) {
400 } else if (attempt_count_ >= kMaxRequestAttempts) { 359 ScheduleAttempt(results.retry_after_delta);
401 if (default_network && 360 return;
402 (default_network->connection_state() == shill::kStatePortal)) { 361 } else if (network &&
403 // Take into account shill's detection results. 362 (network->connection_state() == shill::kStatePortal)) {
404 state.status = CAPTIVE_PORTAL_STATUS_PORTAL; 363 // Take into account shill's detection results.
405 LOG(WARNING) << "Network name=" << default_network->name() << ", " 364 state.status = CAPTIVE_PORTAL_STATUS_PORTAL;
406 << "id=" << default_network->guid() << " " 365 LOG(WARNING) << "Network name=" << network->name() << ", "
407 << "is marked as " 366 << "id=" << network->guid() << " "
408 << CaptivePortalStatusString(state.status) << " " 367 << "is marked as "
409 << "despite the fact that CaptivePortalDetector " 368 << CaptivePortalStatusString(state.status) << " "
410 << "received no response"; 369 << "despite the fact that CaptivePortalDetector "
411 } else { 370 << "received no response";
412 state.status = CAPTIVE_PORTAL_STATUS_OFFLINE;
413 }
414 SetCaptivePortalState(default_network, state);
415 } else { 371 } else {
416 DCHECK(CanPerformDetection()); 372 state.status = CAPTIVE_PORTAL_STATUS_OFFLINE;
417 DetectCaptivePortal(results.retry_after_delta);
418 } 373 }
419 break; 374 break;
420 case captive_portal::RESULT_INTERNET_CONNECTED: 375 case captive_portal::RESULT_INTERNET_CONNECTED:
421 state.status = CAPTIVE_PORTAL_STATUS_ONLINE; 376 state.status = CAPTIVE_PORTAL_STATUS_ONLINE;
422 SetCaptivePortalState(default_network, state);
423 break; 377 break;
424 case captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL: 378 case captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL:
425 state.status = CAPTIVE_PORTAL_STATUS_PORTAL; 379 state.status = CAPTIVE_PORTAL_STATUS_PORTAL;
426 SetCaptivePortalState(default_network, state);
427 break; 380 break;
428 default: 381 default:
429 break; 382 break;
430 } 383 }
431 384
432 TryLazyDetection(); 385 OnDetectionCompleted(network, state);
433 } 386 if (CanPerformAttempt() && strategy_->CanPerformAttemptAfterDetection())
434 387 ScheduleAttempt(base::TimeDelta());
435 void NetworkPortalDetectorImpl::TryLazyDetection() {
436 if (lazy_detection_enabled() && CanPerformDetection())
437 DetectCaptivePortal(base::TimeDelta());
438 } 388 }
439 389
440 void NetworkPortalDetectorImpl::Observe( 390 void NetworkPortalDetectorImpl::Observe(
441 int type, 391 int type,
442 const content::NotificationSource& source, 392 const content::NotificationSource& source,
443 const content::NotificationDetails& details) { 393 const content::NotificationDetails& details) {
444 if (type == chrome::NOTIFICATION_LOGIN_PROXY_CHANGED || 394 if (type == chrome::NOTIFICATION_LOGIN_PROXY_CHANGED ||
445 type == chrome::NOTIFICATION_AUTH_SUPPLIED || 395 type == chrome::NOTIFICATION_AUTH_SUPPLIED ||
446 type == chrome::NOTIFICATION_AUTH_CANCELLED) { 396 type == chrome::NOTIFICATION_AUTH_CANCELLED) {
447 VLOG(1) << "Restarting portal detection due to proxy change."; 397 VLOG(1) << "Restarting portal detection due to proxy change.";
448 attempt_count_ = 0; 398 attempt_count_ = 0;
449 if (IsPortalCheckPending()) 399 if (is_portal_check_pending())
450 return; 400 return;
451 CancelPortalDetection(); 401 StopDetection();
452 DCHECK(CanPerformDetection()); 402 ScheduleAttempt(base::TimeDelta::FromSeconds(kProxyChangeDelaySec));
453 DetectCaptivePortal(base::TimeDelta::FromSeconds(kProxyChangeDelaySec));
454 } 403 }
455 } 404 }
456 405
457 bool NetworkPortalDetectorImpl::IsPortalCheckPending() const { 406 void NetworkPortalDetectorImpl::OnDetectionCompleted(
458 return state_ == STATE_PORTAL_CHECK_PENDING;
459 }
460
461 bool NetworkPortalDetectorImpl::IsCheckingForPortal() const {
462 return state_ == STATE_CHECKING_FOR_PORTAL;
463 }
464
465 void NetworkPortalDetectorImpl::SetCaptivePortalState(
466 const NetworkState* network, 407 const NetworkState* network,
467 const CaptivePortalState& state) { 408 const CaptivePortalState& state) {
468 if (!network) { 409 if (!network) {
469 NotifyPortalDetectionCompleted(network, state); 410 NotifyDetectionCompleted(network, state);
470 return; 411 return;
471 } 412 }
472 413
473 CaptivePortalStateMap::const_iterator it = 414 CaptivePortalStateMap::const_iterator it =
474 portal_state_map_.find(network->path()); 415 portal_state_map_.find(network->path());
475 if (it == portal_state_map_.end() || 416 if (it == portal_state_map_.end() || it->second.status != state.status ||
476 it->second.status != state.status ||
477 it->second.response_code != state.response_code) { 417 it->second.response_code != state.response_code) {
478 VLOG(1) << "Updating Chrome Captive Portal state: " 418 VLOG(1) << "Updating Chrome Captive Portal state: "
479 << "name=" << network->name() << ", " 419 << "name=" << network->name() << ", "
480 << "id=" << network->guid() << ", " 420 << "id=" << network->guid() << ", "
481 << "status=" << CaptivePortalStatusString(state.status) << ", " 421 << "status=" << CaptivePortalStatusString(state.status) << ", "
482 << "response_code=" << state.response_code; 422 << "response_code=" << state.response_code;
483 423
484 // Record detection duration iff detection result differs from the 424 // Record detection duration iff detection result differs from the
485 // previous one for this network. The reason is to record all stats 425 // previous one for this network. The reason is to record all stats
486 // only when network changes it's state. 426 // only when network changes it's state.
487 RecordDetectionStats(network, state.status); 427 RecordDetectionStats(network, state.status);
488 428
489 portal_state_map_[network->path()] = state; 429 portal_state_map_[network->path()] = state;
490 } 430 }
491 NotifyPortalDetectionCompleted(network, state); 431 NotifyDetectionCompleted(network, state);
492 } 432 }
493 433
494 void NetworkPortalDetectorImpl::NotifyPortalDetectionCompleted( 434 void NetworkPortalDetectorImpl::NotifyDetectionCompleted(
495 const NetworkState* network, 435 const NetworkState* network,
496 const CaptivePortalState& state) { 436 const CaptivePortalState& state) {
497 FOR_EACH_OBSERVER(Observer, observers_, 437 FOR_EACH_OBSERVER(
498 OnPortalDetectionCompleted(network, state)); 438 Observer, observers_, OnPortalDetectionCompleted(network, state));
499 notification_controller_.OnPortalDetectionCompleted(network, state); 439 notification_controller_.OnPortalDetectionCompleted(network, state);
500 } 440 }
501 441
502 base::TimeTicks NetworkPortalDetectorImpl::GetCurrentTimeTicks() const { 442 bool NetworkPortalDetectorImpl::AttemptTimeoutIsCancelledForTesting() const {
503 if (time_ticks_for_testing_.is_null()) 443 return attempt_timeout_.IsCancelled();
504 return base::TimeTicks::Now();
505 return time_ticks_for_testing_;
506 }
507
508 bool NetworkPortalDetectorImpl::DetectionTimeoutIsCancelledForTesting() const {
509 return detection_timeout_.IsCancelled();
510 }
511
512 int NetworkPortalDetectorImpl::GetRequestTimeoutSec() const {
513 DCHECK_LE(0, attempt_count_);
514 const NetworkState* network =
515 NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
516 if (!network)
517 return kBaseRequestTimeoutSec;
518 if (lazy_detection_enabled_)
519 return kLazyRequestTimeoutSec;
520 return attempt_count_ * kBaseRequestTimeoutSec;
521 } 444 }
522 445
523 void NetworkPortalDetectorImpl::RecordDetectionStats( 446 void NetworkPortalDetectorImpl::RecordDetectionStats(
524 const NetworkState* network, 447 const NetworkState* network,
525 CaptivePortalStatus status) { 448 CaptivePortalStatus status) {
526 // Don't record stats for offline state. 449 // Don't record stats for offline state.
527 if (!network) 450 if (!network)
528 return; 451 return;
529 452
530 if (!detection_start_time_.is_null()) { 453 if (!detection_start_time_.is_null()) {
(...skipping 25 matching lines...) Expand all
556 if (network->connection_state() != shill::kStateOnline) 479 if (network->connection_state() != shill::kStateOnline)
557 RecordDiscrepancyWithShill(network, status); 480 RecordDiscrepancyWithShill(network, status);
558 break; 481 break;
559 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT: 482 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT:
560 NOTREACHED(); 483 NOTREACHED();
561 break; 484 break;
562 } 485 }
563 } 486 }
564 487
565 } // namespace chromeos 488 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698