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

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: 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 login_screen_strategy_(this),
87 lazy_detection_enabled_(false), 82 error_screen_strategy_(this),
88 lazy_check_interval_(base::TimeDelta::FromSeconds(kLazyCheckIntervalSec)), 83 strategy_(&login_screen_strategy_) {
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));
93 85
94 registrar_.Add(this, 86 registrar_.Add(this,
95 chrome::NOTIFICATION_LOGIN_PROXY_CHANGED, 87 chrome::NOTIFICATION_LOGIN_PROXY_CHANGED,
96 content::NotificationService::AllSources()); 88 content::NotificationService::AllSources());
97 registrar_.Add(this, 89 registrar_.Add(this,
98 chrome::NOTIFICATION_AUTH_SUPPLIED, 90 chrome::NOTIFICATION_AUTH_SUPPLIED,
99 content::NotificationService::AllSources()); 91 content::NotificationService::AllSources());
100 registrar_.Add(this, 92 registrar_.Add(this,
101 chrome::NOTIFICATION_AUTH_CANCELLED, 93 chrome::NOTIFICATION_AUTH_CANCELLED,
102 content::NotificationService::AllSources()); 94 content::NotificationService::AllSources());
103 95
104 NetworkHandler::Get()->network_state_handler()->AddObserver( 96 NetworkHandler::Get()->network_state_handler()->AddObserver(this, FROM_HERE);
105 this, FROM_HERE);
106 } 97 }
107 98
108 NetworkPortalDetectorImpl::~NetworkPortalDetectorImpl() { 99 NetworkPortalDetectorImpl::~NetworkPortalDetectorImpl() {
109 DCHECK(CalledOnValidThread()); 100 DCHECK(CalledOnValidThread());
110 101
111 detection_task_.Cancel(); 102 attempt_task_.Cancel();
112 detection_timeout_.Cancel(); 103 attempt_timeout_.Cancel();
113 104
114 captive_portal_detector_->Cancel(); 105 captive_portal_detector_->Cancel();
115 captive_portal_detector_.reset(); 106 captive_portal_detector_.reset();
116 observers_.Clear(); 107 observers_.Clear();
117 if (NetworkHandler::IsInitialized()) { 108 if (NetworkHandler::IsInitialized()) {
118 NetworkHandler::Get()->network_state_handler()->RemoveObserver( 109 NetworkHandler::Get()->network_state_handler()->RemoveObserver(this,
119 this, FROM_HERE); 110 FROM_HERE);
120 } 111 }
121 } 112 }
122 113
123 void NetworkPortalDetectorImpl::AddObserver(Observer* observer) { 114 void NetworkPortalDetectorImpl::AddObserver(Observer* observer) {
124 DCHECK(CalledOnValidThread()); 115 DCHECK(CalledOnValidThread());
125 if (!observer || observers_.HasObserver(observer)) 116 if (observer && !observers_.HasObserver(observer))
126 return; 117 observers_.AddObserver(observer);
127 observers_.AddObserver(observer);
128 } 118 }
129 119
130 void NetworkPortalDetectorImpl::AddAndFireObserver(Observer* observer) { 120 void NetworkPortalDetectorImpl::AddAndFireObserver(Observer* observer) {
131 DCHECK(CalledOnValidThread()); 121 DCHECK(CalledOnValidThread());
132 if (!observer) 122 if (!observer)
133 return; 123 return;
134 AddObserver(observer); 124 AddObserver(observer);
135 CaptivePortalState portal_state; 125 CaptivePortalState portal_state;
136 const NetworkState* network = 126 const NetworkState* network = DefaultNetwork();
137 NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
138 if (network) 127 if (network)
139 portal_state = GetCaptivePortalState(network->path()); 128 portal_state = GetCaptivePortalState(network->path());
140 observer->OnPortalDetectionCompleted(network, portal_state); 129 observer->OnPortalDetectionCompleted(network, portal_state);
141 } 130 }
142 131
143 void NetworkPortalDetectorImpl::RemoveObserver(Observer* observer) { 132 void NetworkPortalDetectorImpl::RemoveObserver(Observer* observer) {
144 DCHECK(CalledOnValidThread()); 133 DCHECK(CalledOnValidThread());
145 if (observer) 134 if (observer)
146 observers_.RemoveObserver(observer); 135 observers_.RemoveObserver(observer);
147 } 136 }
148 137
149 bool NetworkPortalDetectorImpl::IsEnabled() { 138 bool NetworkPortalDetectorImpl::IsEnabled() { return enabled_; }
150 return enabled_;
151 }
152 139
153 void NetworkPortalDetectorImpl::Enable(bool start_detection) { 140 void NetworkPortalDetectorImpl::Enable(bool start_detection) {
154 DCHECK(CalledOnValidThread()); 141 DCHECK(CalledOnValidThread());
155 if (enabled_) 142 if (enabled_)
156 return; 143 return;
144
145 DCHECK(is_idle());
157 enabled_ = true; 146 enabled_ = true;
158 DCHECK(!IsPortalCheckPending()); 147
159 DCHECK(!IsCheckingForPortal()); 148 const NetworkState* network = DefaultNetwork();
160 DCHECK(!lazy_detection_enabled()); 149 if (!start_detection || !network)
161 if (!start_detection)
162 return; 150 return;
163 state_ = STATE_IDLE; 151 portal_state_map_.erase(network->path());
164 attempt_count_ = 0; 152 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 } 153 }
173 154
174 NetworkPortalDetectorImpl::CaptivePortalState 155 NetworkPortalDetectorImpl::CaptivePortalState
175 NetworkPortalDetectorImpl::GetCaptivePortalState( 156 NetworkPortalDetectorImpl::GetCaptivePortalState(
176 const std::string& service_path) { 157 const std::string& service_path) {
177 DCHECK(CalledOnValidThread()); 158 DCHECK(CalledOnValidThread());
178 CaptivePortalStateMap::const_iterator it = 159 CaptivePortalStateMap::const_iterator it =
179 portal_state_map_.find(service_path); 160 portal_state_map_.find(service_path);
180 if (it == portal_state_map_.end()) 161 if (it == portal_state_map_.end())
181 return CaptivePortalState(); 162 return CaptivePortalState();
182 return it->second; 163 return it->second;
183 } 164 }
184 165
185 bool NetworkPortalDetectorImpl::StartDetectionIfIdle() { 166 bool NetworkPortalDetectorImpl::StartDetectionIfIdle() {
186 if (IsPortalCheckPending() || IsCheckingForPortal()) 167 if (!is_idle())
187 return false; 168 return false;
188 if (!CanPerformDetection()) 169 StartDetection();
189 attempt_count_ = 0;
190 DCHECK(CanPerformDetection());
191 DetectCaptivePortal(base::TimeDelta());
192 return true; 170 return true;
193 } 171 }
194 172
195 void NetworkPortalDetectorImpl::EnableLazyDetection() { 173 void NetworkPortalDetectorImpl::EnableErrorScreenStrategy() {
196 if (lazy_detection_enabled()) 174 if (strategy_ == &error_screen_strategy_)
197 return; 175 return;
198 lazy_detection_enabled_ = true; 176 VLOG(1) << "Error screen detection strategy enabled.";
199 VLOG(1) << "Lazy detection mode enabled."; 177 strategy_ = &error_screen_strategy_;
178 strategy_->Reset();
200 StartDetectionIfIdle(); 179 StartDetectionIfIdle();
201 } 180 }
202 181
203 void NetworkPortalDetectorImpl::DisableLazyDetection() { 182 void NetworkPortalDetectorImpl::DisableErrorScreenStrategy() {
204 if (!lazy_detection_enabled()) 183 if (strategy_ != &error_screen_strategy_)
205 return; 184 return;
206 lazy_detection_enabled_ = false; 185 VLOG(1) << "Error screen detection strategy disabled.";
207 if (attempt_count_ == kMaxRequestAttempts && IsPortalCheckPending()) 186 strategy_ = &login_screen_strategy_;
208 CancelPortalDetection(); 187 strategy_->Reset();
209 VLOG(1) << "Lazy detection mode disabled."; 188 CancelDetection();
210 } 189 }
211 190
212 void NetworkPortalDetectorImpl::DefaultNetworkChanged( 191 void NetworkPortalDetectorImpl::DefaultNetworkChanged(
213 const NetworkState* default_network) { 192 const NetworkState* default_network) {
214 DCHECK(CalledOnValidThread()); 193 DCHECK(CalledOnValidThread());
215 194
216 if (!default_network) { 195 if (!default_network) {
217 default_network_name_.clear(); 196 default_network_name_.clear();
218 default_network_id_.clear(); 197 default_network_id_.clear();
219 198
220 CancelPortalDetection(); 199 CancelDetection();
221 200
222 CaptivePortalState state; 201 CaptivePortalState state;
223 state.status = CAPTIVE_PORTAL_STATUS_OFFLINE; 202 state.status = CAPTIVE_PORTAL_STATUS_OFFLINE;
224 SetCaptivePortalState(NULL, state); 203 OnDetectionCompleted(NULL, state);
225 return; 204 return;
226 } 205 }
227 206
228 default_network_name_ = default_network->name(); 207 default_network_name_ = default_network->name();
229 default_network_id_ = default_network->guid(); 208 default_network_id_ = default_network->guid();
230 209
231 bool network_changed = (default_service_path_ != default_network->path()); 210 bool network_changed = (default_service_path_ != default_network->path());
232 default_service_path_ = default_network->path(); 211 default_service_path_ = default_network->path();
233 212
234 bool connection_state_changed = (default_connection_state_ != 213 bool connection_state_changed =
235 default_network->connection_state()); 214 (default_connection_state_ != default_network->connection_state());
236 default_connection_state_ = default_network->connection_state(); 215 default_connection_state_ = default_network->connection_state();
237 216
238 if (network_changed || connection_state_changed) { 217 if (network_changed || connection_state_changed)
239 attempt_count_ = 0; 218 CancelDetection();
240 CancelPortalDetection();
241 }
242 219
243 if (CanPerformDetection() && 220 if (CanPerformAttempt() &&
244 NetworkState::StateIsConnected(default_connection_state_)) { 221 NetworkState::StateIsConnected(default_connection_state_)) {
245 // Initiate Captive Portal detection if network's captive 222 // Initiate Captive Portal detection if network's captive
246 // portal state is unknown (e.g. for freshly created networks), 223 // portal state is unknown (e.g. for freshly created networks),
247 // offline or if network connection state was changed. 224 // offline or if network connection state was changed.
248 CaptivePortalState state = GetCaptivePortalState(default_network->path()); 225 CaptivePortalState state = GetCaptivePortalState(default_network->path());
249 if (state.status == CAPTIVE_PORTAL_STATUS_UNKNOWN || 226 if (state.status == CAPTIVE_PORTAL_STATUS_UNKNOWN ||
250 state.status == CAPTIVE_PORTAL_STATUS_OFFLINE || 227 state.status == CAPTIVE_PORTAL_STATUS_OFFLINE ||
251 (!network_changed && connection_state_changed)) { 228 (!network_changed && connection_state_changed)) {
252 DetectCaptivePortal(base::TimeDelta()); 229 ScheduleAttempt(base::TimeDelta());
253 } 230 }
254 } 231 }
255 } 232 }
256 233
234 base::TimeTicks NetworkPortalDetectorImpl::GetCurrentTimeTicks() {
235 if (time_ticks_for_testing_.is_null())
236 return base::TimeTicks::Now();
237 return time_ticks_for_testing_;
238 }
239
257 //////////////////////////////////////////////////////////////////////////////// 240 ////////////////////////////////////////////////////////////////////////////////
258 // NetworkPortalDetectorImpl, private: 241 // NetworkPortalDetectorImpl, private:
259 242
260 bool NetworkPortalDetectorImpl::CanPerformDetection() const { 243 void NetworkPortalDetectorImpl::StartDetection() {
261 if (IsPortalCheckPending() || IsCheckingForPortal()) 244 strategy_->Reset();
262 return false; 245 DCHECK(CanPerformAttempt());
263 return attempt_count_ < kMaxRequestAttempts || lazy_detection_enabled(); 246 detection_start_time_ = GetCurrentTimeTicks();
247 ScheduleAttempt(base::TimeDelta());
264 } 248 }
265 249
266 void NetworkPortalDetectorImpl::DetectCaptivePortal( 250 void NetworkPortalDetectorImpl::CancelDetection() {
267 const base::TimeDelta& delay) { 251 attempt_task_.Cancel();
268 DCHECK(CanPerformDetection()); 252 attempt_timeout_.Cancel();
253 captive_portal_detector_->Cancel();
254 state_ = STATE_IDLE;
255 strategy_->Reset();
256 }
257
258 bool NetworkPortalDetectorImpl::CanPerformAttempt() const {
259 return is_idle() && strategy_->CanPerformAttempt();
260 }
261
262 void NetworkPortalDetectorImpl::ScheduleAttempt(const base::TimeDelta& delay) {
263 DCHECK(CanPerformAttempt());
269 264
270 if (!IsEnabled()) 265 if (!IsEnabled())
271 return; 266 return;
272 267
273 detection_task_.Cancel(); 268 attempt_task_.Cancel();
274 detection_timeout_.Cancel(); 269 attempt_timeout_.Cancel();
275 state_ = STATE_PORTAL_CHECK_PENDING; 270 state_ = STATE_PORTAL_CHECK_PENDING;
276 271
277 next_attempt_delay_ = delay; 272 next_attempt_delay_ =
278 if (attempt_count_ > 0) { 273 std::max(delay, strategy_->GetDelayBeforeCurrentAttempt());
279 base::TimeTicks now = GetCurrentTimeTicks(); 274 attempt_task_.Reset(base::Bind(&NetworkPortalDetectorImpl::StartAttempt,
280 base::TimeDelta elapsed_time; 275 weak_factory_.GetWeakPtr()));
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( 276 base::MessageLoop::current()->PostDelayedTask(
300 FROM_HERE, detection_task_.callback(), next_attempt_delay_); 277 FROM_HERE, attempt_task_.callback(), next_attempt_delay_);
301 } 278 }
302 279
303 void NetworkPortalDetectorImpl::DetectCaptivePortalTask() { 280 void NetworkPortalDetectorImpl::StartAttempt() {
304 DCHECK(IsPortalCheckPending()); 281 DCHECK(is_portal_check_pending());
305 282
306 state_ = STATE_CHECKING_FOR_PORTAL; 283 state_ = STATE_CHECKING_FOR_PORTAL;
307 attempt_start_time_ = GetCurrentTimeTicks();
308
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 284
320 captive_portal_detector_->DetectCaptivePortal( 285 captive_portal_detector_->DetectCaptivePortal(
321 test_url_, 286 test_url_,
322 base::Bind(&NetworkPortalDetectorImpl::OnPortalDetectionCompleted, 287 base::Bind(&NetworkPortalDetectorImpl::OnAttemptCompleted,
323 weak_ptr_factory_.GetWeakPtr())); 288 weak_factory_.GetWeakPtr()));
324 detection_timeout_.Reset( 289 attempt_timeout_.Reset(
325 base::Bind(&NetworkPortalDetectorImpl::PortalDetectionTimeout, 290 base::Bind(&NetworkPortalDetectorImpl::OnAttemptTimeout,
326 weak_ptr_factory_.GetWeakPtr())); 291 weak_factory_.GetWeakPtr()));
327 base::TimeDelta request_timeout;
328 292
329 // For easier unit testing check for testing state is performed here 293 strategy_->OnAttemptStarted();
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( 294 base::MessageLoop::current()->PostDelayedTask(
336 FROM_HERE, detection_timeout_.callback(), request_timeout); 295 FROM_HERE,
296 attempt_timeout_.callback(),
297 strategy_->GetCurrentAttemptTimeout());
337 } 298 }
338 299
339 void NetworkPortalDetectorImpl::PortalDetectionTimeout() { 300 void NetworkPortalDetectorImpl::OnAttemptTimeout() {
340 DCHECK(CalledOnValidThread()); 301 DCHECK(CalledOnValidThread());
341 DCHECK(IsCheckingForPortal()); 302 DCHECK(is_checking_for_portal());
342 303
343 VLOG(1) << "Portal detection timeout: name=" << default_network_name_ << ", " 304 VLOG(1) << "Portal detection timeout: name=" << default_network_name_ << ", "
344 << "id=" << default_network_id_; 305 << "id=" << default_network_id_;
345 306
346 captive_portal_detector_->Cancel(); 307 captive_portal_detector_->Cancel();
347 CaptivePortalDetector::Results results; 308 CaptivePortalDetector::Results results;
348 results.result = captive_portal::RESULT_NO_RESPONSE; 309 results.result = captive_portal::RESULT_NO_RESPONSE;
349 OnPortalDetectionCompleted(results); 310 OnAttemptCompleted(results);
350 } 311 }
351 312
352 void NetworkPortalDetectorImpl::CancelPortalDetection() { 313 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) { 314 const CaptivePortalDetector::Results& results) {
363 captive_portal::Result result = results.result; 315 captive_portal::Result result = results.result;
364 int response_code = results.response_code; 316 int response_code = results.response_code;
365 317
366 DCHECK(CalledOnValidThread()); 318 DCHECK(CalledOnValidThread());
367 DCHECK(IsCheckingForPortal()); 319 DCHECK(is_checking_for_portal());
368 320
369 VLOG(1) << "Portal detection completed: " 321 VLOG(1) << "Detection attempt completed: "
370 << "name=" << default_network_name_ << ", " 322 << "name=" << default_network_name_ << ", "
371 << "id=" << default_network_id_ << ", " 323 << "id=" << default_network_id_ << ", "
372 << "result=" 324 << "result="
373 << CaptivePortalDetector::CaptivePortalResultToString(results.result) 325 << CaptivePortalDetector::CaptivePortalResultToString(results.result)
374 << ", " 326 << ", "
375 << "response_code=" << results.response_code; 327 << "response_code=" << results.response_code;
376 328
377 state_ = STATE_IDLE; 329 state_ = STATE_IDLE;
378 detection_timeout_.Cancel(); 330 attempt_timeout_.Cancel();
379 331
380 const NetworkState* default_network = 332 const NetworkState* network = DefaultNetwork();
381 NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
382 333
383 // If using a fake profile client, also fake being behind a captive portal 334 // If using a fake profile client, also fake being behind a captive portal
384 // if the default network is in portal state. 335 // if the default network is in portal state.
385 if (result != captive_portal::RESULT_NO_RESPONSE && 336 if (result != captive_portal::RESULT_NO_RESPONSE &&
386 DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface() && 337 DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface() &&
387 default_network && 338 network && network->connection_state() == shill::kStatePortal) {
388 default_network->connection_state() == shill::kStatePortal) {
389 result = captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL; 339 result = captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL;
390 response_code = 200; 340 response_code = 200;
391 } 341 }
392 342
393 CaptivePortalState state; 343 CaptivePortalState state;
394 state.response_code = response_code; 344 state.response_code = response_code;
395 switch (result) { 345 switch (result) {
396 case captive_portal::RESULT_NO_RESPONSE: 346 case captive_portal::RESULT_NO_RESPONSE:
397 if (state.response_code == net::HTTP_PROXY_AUTHENTICATION_REQUIRED) { 347 if (state.response_code == net::HTTP_PROXY_AUTHENTICATION_REQUIRED) {
398 state.status = CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED; 348 state.status = CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED;
399 SetCaptivePortalState(default_network, state); 349 } else if (CanPerformAttempt()) {
400 } else if (attempt_count_ >= kMaxRequestAttempts) { 350 ScheduleAttempt(results.retry_after_delta);
401 if (default_network && 351 return;
402 (default_network->connection_state() == shill::kStatePortal)) { 352 } else if (network &&
403 // Take into account shill's detection results. 353 (network->connection_state() == shill::kStatePortal)) {
404 state.status = CAPTIVE_PORTAL_STATUS_PORTAL; 354 // Take into account shill's detection results.
405 LOG(WARNING) << "Network name=" << default_network->name() << ", " 355 state.status = CAPTIVE_PORTAL_STATUS_PORTAL;
406 << "id=" << default_network->guid() << " " 356 LOG(WARNING) << "Network name=" << network->name() << ", "
407 << "is marked as " 357 << "id=" << network->guid() << " "
408 << CaptivePortalStatusString(state.status) << " " 358 << "is marked as "
409 << "despite the fact that CaptivePortalDetector " 359 << CaptivePortalStatusString(state.status) << " "
410 << "received no response"; 360 << "despite the fact that CaptivePortalDetector "
411 } else { 361 << "received no response";
412 state.status = CAPTIVE_PORTAL_STATUS_OFFLINE;
413 }
414 SetCaptivePortalState(default_network, state);
415 } else { 362 } else {
416 DCHECK(CanPerformDetection()); 363 state.status = CAPTIVE_PORTAL_STATUS_OFFLINE;
417 DetectCaptivePortal(results.retry_after_delta);
418 } 364 }
419 break; 365 break;
420 case captive_portal::RESULT_INTERNET_CONNECTED: 366 case captive_portal::RESULT_INTERNET_CONNECTED:
421 state.status = CAPTIVE_PORTAL_STATUS_ONLINE; 367 state.status = CAPTIVE_PORTAL_STATUS_ONLINE;
422 SetCaptivePortalState(default_network, state);
423 break; 368 break;
424 case captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL: 369 case captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL:
425 state.status = CAPTIVE_PORTAL_STATUS_PORTAL; 370 state.status = CAPTIVE_PORTAL_STATUS_PORTAL;
426 SetCaptivePortalState(default_network, state);
427 break; 371 break;
428 default: 372 default:
429 break; 373 break;
430 } 374 }
431 375
432 TryLazyDetection(); 376 OnDetectionCompleted(network, state);
433 } 377 if (CanPerformAttempt())
434 378 ScheduleAttempt(base::TimeDelta());
435 void NetworkPortalDetectorImpl::TryLazyDetection() {
436 if (lazy_detection_enabled() && CanPerformDetection())
437 DetectCaptivePortal(base::TimeDelta());
438 } 379 }
439 380
440 void NetworkPortalDetectorImpl::Observe( 381 void NetworkPortalDetectorImpl::Observe(
441 int type, 382 int type,
442 const content::NotificationSource& source, 383 const content::NotificationSource& source,
443 const content::NotificationDetails& details) { 384 const content::NotificationDetails& details) {
444 if (type == chrome::NOTIFICATION_LOGIN_PROXY_CHANGED || 385 if (type == chrome::NOTIFICATION_LOGIN_PROXY_CHANGED ||
445 type == chrome::NOTIFICATION_AUTH_SUPPLIED || 386 type == chrome::NOTIFICATION_AUTH_SUPPLIED ||
446 type == chrome::NOTIFICATION_AUTH_CANCELLED) { 387 type == chrome::NOTIFICATION_AUTH_CANCELLED) {
447 VLOG(1) << "Restarting portal detection due to proxy change."; 388 VLOG(1) << "Restarting portal detection due to proxy change.";
448 attempt_count_ = 0; 389 strategy_->Reset();
449 if (IsPortalCheckPending()) 390 if (is_portal_check_pending())
450 return; 391 return;
451 CancelPortalDetection(); 392 CancelDetection();
452 DCHECK(CanPerformDetection()); 393 ScheduleAttempt(base::TimeDelta::FromSeconds(kProxyChangeDelaySec));
453 DetectCaptivePortal(base::TimeDelta::FromSeconds(kProxyChangeDelaySec));
454 } 394 }
455 } 395 }
456 396
457 bool NetworkPortalDetectorImpl::IsPortalCheckPending() const { 397 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, 398 const NetworkState* network,
467 const CaptivePortalState& state) { 399 const CaptivePortalState& state) {
400 strategy_->OnDetectionCompleted();
401
468 if (!network) { 402 if (!network) {
469 NotifyPortalDetectionCompleted(network, state); 403 NotifyDetectionCompleted(network, state);
470 return; 404 return;
471 } 405 }
472 406
473 CaptivePortalStateMap::const_iterator it = 407 CaptivePortalStateMap::const_iterator it =
474 portal_state_map_.find(network->path()); 408 portal_state_map_.find(network->path());
475 if (it == portal_state_map_.end() || 409 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) { 410 it->second.response_code != state.response_code) {
478 VLOG(1) << "Updating Chrome Captive Portal state: " 411 VLOG(1) << "Updating Chrome Captive Portal state: "
479 << "name=" << network->name() << ", " 412 << "name=" << network->name() << ", "
480 << "id=" << network->guid() << ", " 413 << "id=" << network->guid() << ", "
481 << "status=" << CaptivePortalStatusString(state.status) << ", " 414 << "status=" << CaptivePortalStatusString(state.status) << ", "
482 << "response_code=" << state.response_code; 415 << "response_code=" << state.response_code;
483 416
484 // Record detection duration iff detection result differs from the 417 // Record detection duration iff detection result differs from the
485 // previous one for this network. The reason is to record all stats 418 // previous one for this network. The reason is to record all stats
486 // only when network changes it's state. 419 // only when network changes it's state.
487 RecordDetectionStats(network, state.status); 420 RecordDetectionStats(network, state.status);
488 421
489 portal_state_map_[network->path()] = state; 422 portal_state_map_[network->path()] = state;
490 } 423 }
491 NotifyPortalDetectionCompleted(network, state); 424 NotifyDetectionCompleted(network, state);
492 } 425 }
493 426
494 void NetworkPortalDetectorImpl::NotifyPortalDetectionCompleted( 427 void NetworkPortalDetectorImpl::NotifyDetectionCompleted(
495 const NetworkState* network, 428 const NetworkState* network,
496 const CaptivePortalState& state) { 429 const CaptivePortalState& state) {
497 FOR_EACH_OBSERVER(Observer, observers_, 430 FOR_EACH_OBSERVER(
498 OnPortalDetectionCompleted(network, state)); 431 Observer, observers_, OnPortalDetectionCompleted(network, state));
499 notification_controller_.OnPortalDetectionCompleted(network, state); 432 notification_controller_.OnPortalDetectionCompleted(network, state);
500 } 433 }
501 434
502 base::TimeTicks NetworkPortalDetectorImpl::GetCurrentTimeTicks() const { 435 bool NetworkPortalDetectorImpl::AttemptTimeoutIsCancelledForTesting() const {
503 if (time_ticks_for_testing_.is_null()) 436 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 } 437 }
522 438
523 void NetworkPortalDetectorImpl::RecordDetectionStats( 439 void NetworkPortalDetectorImpl::RecordDetectionStats(
524 const NetworkState* network, 440 const NetworkState* network,
525 CaptivePortalStatus status) { 441 CaptivePortalStatus status) {
526 // Don't record stats for offline state. 442 // Don't record stats for offline state.
527 if (!network) 443 if (!network)
528 return; 444 return;
529 445
530 if (!detection_start_time_.is_null()) { 446 if (!detection_start_time_.is_null()) {
(...skipping 25 matching lines...) Expand all
556 if (network->connection_state() != shill::kStateOnline) 472 if (network->connection_state() != shill::kStateOnline)
557 RecordDiscrepancyWithShill(network, status); 473 RecordDiscrepancyWithShill(network, status);
558 break; 474 break;
559 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT: 475 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT:
560 NOTREACHED(); 476 NOTREACHED();
561 break; 477 break;
562 } 478 }
563 } 479 }
564 480
565 } // namespace chromeos 481 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698