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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/net/network_portal_detector_impl.h"
6
7 #include <algorithm>
8 #include <memory>
9 #include <vector>
10
11 #include "base/bind.h"
12 #include "base/callback_helpers.h"
13 #include "base/command_line.h"
14 #include "base/compiler_specific.h"
15 #include "base/logging.h"
16 #include "base/memory/ptr_util.h"
17 #include "base/metrics/histogram_base.h"
18 #include "base/metrics/histogram_samples.h"
19 #include "base/metrics/statistics_recorder.h"
20 #include "base/run_loop.h"
21 #include "base/test/metrics/histogram_tester.h"
22 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
23 #include "chrome/browser/chromeos/net/network_portal_detector_test_utils.h"
24 #include "chrome/test/base/testing_browser_process.h"
25 #include "chrome/test/base/testing_profile.h"
26 #include "chrome/test/base/testing_profile_manager.h"
27 #include "chromeos/constants/chromeos_switches.h"
28 #include "chromeos/dbus/dbus_thread_manager.h"
29 #include "chromeos/dbus/shill/shill_device_client.h"
30 #include "chromeos/dbus/shill/shill_service_client.h"
31 #include "chromeos/network/network_handler.h"
32 #include "chromeos/network/network_state.h"
33 #include "chromeos/network/network_state_handler.h"
34 #include "chromeos/network/portal_detector/network_portal_detector_strategy.h"
35 #include "components/captive_portal/core/captive_portal_detector.h"
36 #include "components/captive_portal/core/captive_portal_testing_utils.h"
37 #include "components/user_manager/scoped_user_manager.h"
38 #include "components/user_manager/user_manager.h"
39 #include "content/public/test/browser_task_environment.h"
40 #include "dbus/object_path.h"
41 #include "net/base/net_errors.h"
42 #include "testing/gmock/include/gmock/gmock.h"
43 #include "testing/gtest/include/gtest/gtest.h"
44 #include "third_party/cros_system_api/dbus/service_constants.h"
45
46 using testing::_;
47 using testing::AnyNumber;
48 using testing::Mock;
49
50 namespace chromeos {
51
52 namespace {
53
54 // Service path / guid for stub networks.
55 const char kStubEthernet[] = "stub_ethernet";
56 const char kStubWireless1[] = "stub_wifi1";
57 const char kStubWireless2[] = "stub_wifi2";
58 const char kStubCellular[] = "stub_cellular";
59
ErrorCallbackFunction(const std::string & error_name,const std::string & error_message)60 void ErrorCallbackFunction(const std::string& error_name,
61 const std::string& error_message) {
62 LOG(ERROR) << "Shill Error: " << error_name << " : " << error_message;
63 }
64
65 class MockObserver : public NetworkPortalDetector::Observer {
66 public:
~MockObserver()67 virtual ~MockObserver() {}
68
69 MOCK_METHOD2(OnPortalDetectionCompleted,
70 void(const NetworkState* network,
71 const NetworkPortalDetector::CaptivePortalStatus status));
72 };
73
74 } // namespace
75
76 class NetworkPortalDetectorImplTest
77 : public testing::Test,
78 public captive_portal::CaptivePortalDetectorTestBase {
79 protected:
80 using State = NetworkPortalDetectorImpl::State;
81
NetworkPortalDetectorImplTest()82 NetworkPortalDetectorImplTest()
83 : test_profile_manager_(TestingBrowserProcess::GetGlobal()) {}
84
SetUp()85 void SetUp() override {
86 FakeChromeUserManager* user_manager = new FakeChromeUserManager();
87 user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>(
88 base::WrapUnique(user_manager));
89
90 DBusThreadManager::Initialize();
91 SetupNetworkHandler();
92
93 ASSERT_TRUE(test_profile_manager_.SetUp());
94
95 // Add a user.
96 const AccountId test_account_id(
97 AccountId::FromUserEmail("test-user@example.com"));
98 user_manager->AddUser(test_account_id);
99 user_manager->LoginUser(test_account_id);
100
101 // Create a profile for the user.
102 profile_ = test_profile_manager_.CreateTestingProfile(
103 test_account_id.GetUserEmail());
104 EXPECT_TRUE(user_manager::UserManager::Get()->GetPrimaryUser());
105
106 network_portal_detector_.reset(
107 new NetworkPortalDetectorImpl(test_loader_factory()));
108 network_portal_detector_->Enable(false);
109
110 set_detector(network_portal_detector_->captive_portal_detector_.get());
111
112 // Prevents flakiness due to message loop delays.
113 set_time_ticks(base::TimeTicks::Now());
114
115 if (base::HistogramBase* histogram =
116 base::StatisticsRecorder::FindHistogram(
117 "CaptivePortal.OOBE.DetectionResult")) {
118 original_samples_ = histogram->SnapshotSamples();
119 }
120 }
121
TearDown()122 void TearDown() override {
123 network_portal_detector_.reset();
124 profile_ = nullptr;
125 NetworkHandler::Shutdown();
126 DBusThreadManager::Shutdown();
127 PortalDetectorStrategy::reset_fields_for_testing();
128 }
129
CheckPortalState(NetworkPortalDetector::CaptivePortalStatus status,int response_code,const std::string & guid)130 bool CheckPortalState(NetworkPortalDetector::CaptivePortalStatus status,
131 int response_code,
132 const std::string& guid) {
133 NetworkPortalDetector::CaptivePortalStatus detector_status =
134 network_portal_detector()->GetCaptivePortalStatus();
135 int detector_response_code =
136 network_portal_detector()->response_code_for_testing();
137 std::string default_network_id =
138 network_portal_detector()->default_network_id_for_testing();
139 EXPECT_EQ(status, detector_status);
140 EXPECT_EQ(response_code, detector_response_code);
141 EXPECT_EQ(guid, default_network_id);
142 return status == detector_status &&
143 response_code == detector_response_code &&
144 guid == default_network_id;
145 }
146
CheckRequestTimeoutAndCompleteAttempt(int expected_same_detection_result_count,int expected_no_response_result_count,int expected_request_timeout_sec,int net_error,int status_code)147 void CheckRequestTimeoutAndCompleteAttempt(
148 int expected_same_detection_result_count,
149 int expected_no_response_result_count,
150 int expected_request_timeout_sec,
151 int net_error,
152 int status_code) {
153 ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
154 ASSERT_EQ(expected_same_detection_result_count,
155 same_detection_result_count());
156 ASSERT_EQ(expected_no_response_result_count, no_response_result_count());
157 ASSERT_EQ(base::TimeDelta::FromSeconds(expected_request_timeout_sec),
158 get_next_attempt_timeout());
159 CompleteURLFetch(net_error, status_code, nullptr);
160 }
161
profile()162 Profile* profile() { return profile_; }
163
network_portal_detector()164 NetworkPortalDetectorImpl* network_portal_detector() {
165 return network_portal_detector_.get();
166 }
167
AddObserver(NetworkPortalDetector::Observer * observer)168 void AddObserver(NetworkPortalDetector::Observer* observer) {
169 network_portal_detector()->AddObserver(observer);
170 }
171
RemoveObserver(NetworkPortalDetector::Observer * observer)172 void RemoveObserver(NetworkPortalDetector::Observer* observer) {
173 network_portal_detector()->RemoveObserver(observer);
174 }
175
state()176 NetworkPortalDetectorImpl::State state() {
177 return network_portal_detector()->state();
178 }
179
StartPortalDetection()180 void StartPortalDetection() {
181 network_portal_detector()->StartPortalDetection();
182 }
183
enable_error_screen_strategy()184 void enable_error_screen_strategy() {
185 network_portal_detector()->SetStrategy(
186 PortalDetectorStrategy::STRATEGY_ID_ERROR_SCREEN);
187 }
188
disable_error_screen_strategy()189 void disable_error_screen_strategy() {
190 network_portal_detector()->SetStrategy(
191 PortalDetectorStrategy::STRATEGY_ID_LOGIN_SCREEN);
192 }
193
stop_detection()194 void stop_detection() { network_portal_detector()->StopDetection(); }
195
attempt_timeout_is_cancelled()196 bool attempt_timeout_is_cancelled() {
197 return network_portal_detector()->AttemptTimeoutIsCancelledForTesting();
198 }
199
get_next_attempt_timeout()200 base::TimeDelta get_next_attempt_timeout() {
201 return network_portal_detector()->strategy_->GetNextAttemptTimeout();
202 }
203
set_next_attempt_timeout(const base::TimeDelta & timeout)204 void set_next_attempt_timeout(const base::TimeDelta& timeout) {
205 PortalDetectorStrategy::set_next_attempt_timeout_for_testing(timeout);
206 }
207
next_attempt_delay()208 const base::TimeDelta& next_attempt_delay() {
209 return network_portal_detector()->next_attempt_delay_for_testing();
210 }
211
same_detection_result_count()212 int same_detection_result_count() {
213 return network_portal_detector()->same_detection_result_count_for_testing();
214 }
215
no_response_result_count()216 int no_response_result_count() {
217 return network_portal_detector()->no_response_result_count_for_testing();
218 }
219
set_no_response_result_count(int count)220 void set_no_response_result_count(int count) {
221 network_portal_detector()->set_no_response_result_count_for_testing(count);
222 }
223
set_delay_till_next_attempt(const base::TimeDelta & delta)224 void set_delay_till_next_attempt(const base::TimeDelta& delta) {
225 PortalDetectorStrategy::set_delay_till_next_attempt_for_testing(delta);
226 }
227
set_time_ticks(const base::TimeTicks & time_ticks)228 void set_time_ticks(const base::TimeTicks& time_ticks) {
229 network_portal_detector()->set_time_ticks_for_testing(time_ticks);
230 }
231
advance_time_ticks(const base::TimeDelta & delta)232 void advance_time_ticks(const base::TimeDelta& delta) {
233 network_portal_detector()->advance_time_ticks_for_testing(delta);
234 }
235
SetBehindPortal(const std::string & service_path)236 void SetBehindPortal(const std::string& service_path) {
237 DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
238 dbus::ObjectPath(service_path), shill::kStateProperty,
239 base::Value(shill::kStateNoConnectivity), base::DoNothing(),
240 base::BindOnce(&ErrorCallbackFunction));
241 base::RunLoop().RunUntilIdle();
242 }
243
SetNetworkDeviceEnabled(const std::string & type,bool enabled)244 void SetNetworkDeviceEnabled(const std::string& type, bool enabled) {
245 NetworkHandler::Get()->network_state_handler()->SetTechnologyEnabled(
246 NetworkTypePattern::Primitive(type), enabled,
247 network_handler::ErrorCallback());
248 base::RunLoop().RunUntilIdle();
249 }
250
SetConnected(const std::string & service_path)251 void SetConnected(const std::string& service_path) {
252 DBusThreadManager::Get()->GetShillServiceClient()->Connect(
253 dbus::ObjectPath(service_path), base::DoNothing(),
254 base::BindOnce(&ErrorCallbackFunction));
255 base::RunLoop().RunUntilIdle();
256 }
257
SetDisconnected(const std::string & service_path)258 void SetDisconnected(const std::string& service_path) {
259 DBusThreadManager::Get()->GetShillServiceClient()->Disconnect(
260 dbus::ObjectPath(service_path), base::DoNothing(),
261 base::BindOnce(&ErrorCallbackFunction));
262 base::RunLoop().RunUntilIdle();
263 }
264
265 private:
AddService(const std::string & network_id,const std::string & type)266 void AddService(const std::string& network_id, const std::string& type) {
267 DBusThreadManager::Get()
268 ->GetShillServiceClient()
269 ->GetTestInterface()
270 ->AddService(network_id /* service_path */, network_id /* guid */,
271 network_id /* name */, type, shill::kStateIdle,
272 true /* add_to_visible */);
273 }
274
SetupDefaultShillState()275 void SetupDefaultShillState() {
276 base::RunLoop().RunUntilIdle();
277 DBusThreadManager::Get()
278 ->GetShillServiceClient()
279 ->GetTestInterface()
280 ->ClearServices();
281 AddService(kStubEthernet, shill::kTypeEthernet);
282 AddService(kStubWireless1, shill::kTypeWifi);
283 AddService(kStubWireless2, shill::kTypeWifi);
284 AddService(kStubCellular, shill::kTypeCellular);
285 }
286
SetupNetworkHandler()287 void SetupNetworkHandler() {
288 SetupDefaultShillState();
289 NetworkHandler::Initialize();
290 }
291
292 content::BrowserTaskEnvironment task_environment_;
293 Profile* profile_ = nullptr;
294 std::unique_ptr<NetworkPortalDetectorImpl> network_portal_detector_;
295 std::unique_ptr<base::HistogramSamples> original_samples_;
296 std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_;
297 TestingProfileManager test_profile_manager_;
298 };
299
TEST_F(NetworkPortalDetectorImplTest,NoPortal)300 TEST_F(NetworkPortalDetectorImplTest, NoPortal) {
301 ASSERT_EQ(State::STATE_IDLE, state());
302
303 SetConnected(kStubWireless1);
304
305 ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
306 EXPECT_TRUE(
307 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN, -1,
308 kStubWireless1));
309
310 CompleteURLFetch(net::OK, 204, nullptr);
311
312 EXPECT_NE(State::STATE_IDLE, state());
313 EXPECT_TRUE(
314 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204,
315 kStubWireless1));
316 }
317
TEST_F(NetworkPortalDetectorImplTest,Portal)318 TEST_F(NetworkPortalDetectorImplTest, Portal) {
319 ASSERT_EQ(State::STATE_IDLE, state());
320
321 // Check HTTP 200 response code.
322 SetConnected(kStubWireless1);
323 ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
324
325 CompleteURLFetch(net::OK, 200, nullptr);
326
327 EXPECT_NE(State::STATE_IDLE, state());
328 EXPECT_TRUE(
329 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 200,
330 kStubWireless1));
331
332 // Check HTTP 301 response code.
333 SetConnected(kStubWireless2);
334 ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
335
336 CompleteURLFetch(net::OK, 301, nullptr);
337
338 EXPECT_NE(State::STATE_IDLE, state());
339 EXPECT_TRUE(
340 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 301,
341 kStubWireless2));
342
343 // Check HTTP 302 response code.
344 SetConnected(kStubEthernet);
345 ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
346
347 CompleteURLFetch(net::OK, 302, nullptr);
348
349 EXPECT_NE(State::STATE_IDLE, state());
350 EXPECT_TRUE(CheckPortalState(
351 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 302, kStubEthernet));
352 }
353
TEST_F(NetworkPortalDetectorImplTest,Online2Offline)354 TEST_F(NetworkPortalDetectorImplTest, Online2Offline) {
355 ASSERT_EQ(State::STATE_IDLE, state());
356
357 MockObserver observer;
358 AddObserver(&observer);
359
360 NetworkPortalDetector::CaptivePortalStatus offline_status =
361 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE;
362
363 // WiFi is in online state.
364 {
365 // When transitioning to a connected state, the network will transition to
366 // connecting states which will set the default network to nullptr. This may
367 // get triggered multiple times.
368 EXPECT_CALL(observer, OnPortalDetectionCompleted(_, offline_status))
369 .Times(AnyNumber());
370
371 // Expect a single transition to an online state.
372 EXPECT_CALL(observer,
373 OnPortalDetectionCompleted(
374 _, NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE))
375 .Times(1);
376
377 SetConnected(kStubWireless1);
378 ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
379
380 CompleteURLFetch(net::OK, 204, nullptr);
381 EXPECT_NE(State::STATE_IDLE, state());
382
383 // Check that observer was notified about online state.
384 Mock::VerifyAndClearExpectations(&observer);
385 }
386
387 // WiFi is turned off.
388 {
389 EXPECT_CALL(observer, OnPortalDetectionCompleted(nullptr, offline_status))
390 .Times(1);
391
392 SetDisconnected(kStubWireless1);
393 ASSERT_EQ(State::STATE_IDLE, state());
394
395 // Check that observer was notified about offline state.
396 Mock::VerifyAndClearExpectations(&observer);
397 }
398
399 RemoveObserver(&observer);
400 }
401
TEST_F(NetworkPortalDetectorImplTest,NetworkChanged)402 TEST_F(NetworkPortalDetectorImplTest, NetworkChanged) {
403 ASSERT_EQ(State::STATE_IDLE, state());
404
405 SetConnected(kStubWireless1);
406
407 // WiFi is in portal state.
408 ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
409
410 // Active network is changed during portal detection for WiFi.
411 SetConnected(kStubEthernet);
412
413 // Portal detection for WiFi is cancelled, portal detection for
414 // ethernet is initiated.
415 ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
416
417 // ethernet is in online state.
418 CompleteURLFetch(net::OK, 204, nullptr);
419 EXPECT_NE(State::STATE_IDLE, state());
420 EXPECT_TRUE(CheckPortalState(
421 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubEthernet));
422 }
423
TEST_F(NetworkPortalDetectorImplTest,NetworkStateReconnect)424 TEST_F(NetworkPortalDetectorImplTest, NetworkStateReconnect) {
425 ASSERT_EQ(State::STATE_IDLE, state());
426
427 SetConnected(kStubWireless1);
428 ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
429
430 CompleteURLFetch(net::OK, 204, nullptr);
431
432 EXPECT_NE(State::STATE_IDLE, state());
433 EXPECT_TRUE(
434 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204,
435 kStubWireless1));
436
437 // Triggering a connect to the same network will trigger another portal check
438 // with the same results.
439 SetConnected(kStubWireless1);
440 ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
441
442 CompleteURLFetch(net::OK, 204, nullptr);
443
444 EXPECT_NE(State::STATE_IDLE, state());
445 EXPECT_TRUE(
446 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204,
447 kStubWireless1));
448 }
449
TEST_F(NetworkPortalDetectorImplTest,NetworkStateChanged)450 TEST_F(NetworkPortalDetectorImplTest, NetworkStateChanged) {
451 // Test for Portal -> Online -> Portal network state transitions.
452 ASSERT_EQ(State::STATE_IDLE, state());
453
454 SetBehindPortal(kStubWireless1);
455 ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
456
457 CompleteURLFetch(net::OK, 200, nullptr);
458
459 ASSERT_NE(State::STATE_IDLE, state());
460 EXPECT_TRUE(
461 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 200,
462 kStubWireless1));
463
464 SetConnected(kStubWireless1);
465 ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
466
467 CompleteURLFetch(net::OK, 204, nullptr);
468
469 EXPECT_NE(State::STATE_IDLE, state());
470 EXPECT_TRUE(
471 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204,
472 kStubWireless1));
473
474 SetBehindPortal(kStubWireless1);
475 ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
476
477 CompleteURLFetch(net::OK, 200, nullptr);
478
479 ASSERT_NE(State::STATE_IDLE, state());
480 EXPECT_TRUE(
481 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 200,
482 kStubWireless1));
483 }
484
TEST_F(NetworkPortalDetectorImplTest,PortalDetectionTimeout)485 TEST_F(NetworkPortalDetectorImplTest, PortalDetectionTimeout) {
486 ASSERT_EQ(State::STATE_IDLE, state());
487
488 // For instantaneous timeout.
489 set_next_attempt_timeout(base::TimeDelta::FromSeconds(0));
490
491 ASSERT_EQ(State::STATE_IDLE, state());
492 ASSERT_EQ(0, same_detection_result_count());
493 ASSERT_EQ(0, no_response_result_count());
494
495 SetConnected(kStubWireless1);
496 base::RunLoop().RunUntilIdle();
497
498 // First portal detection timeouts, next portal detection is
499 // scheduled.
500 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
501 ASSERT_EQ(1, no_response_result_count());
502 }
503
TEST_F(NetworkPortalDetectorImplTest,PortalDetectionRetryAfter)504 TEST_F(NetworkPortalDetectorImplTest, PortalDetectionRetryAfter) {
505 ASSERT_EQ(State::STATE_IDLE, state());
506
507 const char retry_after[] = "HTTP/1.1 503 OK\nRetry-After: 101\n\n";
508
509 ASSERT_EQ(State::STATE_IDLE, state());
510 ASSERT_EQ(0, no_response_result_count());
511
512 SetConnected(kStubWireless1);
513 ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
514 CompleteURLFetch(net::OK, 503, retry_after);
515
516 // First portal detection completed, next portal detection is
517 // scheduled after 101 seconds.
518 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
519 ASSERT_EQ(1, no_response_result_count());
520 ASSERT_EQ(base::TimeDelta::FromSeconds(101), next_attempt_delay());
521 }
522
TEST_F(NetworkPortalDetectorImplTest,PortalDetectorRetryAfterIsSmall)523 TEST_F(NetworkPortalDetectorImplTest, PortalDetectorRetryAfterIsSmall) {
524 ASSERT_EQ(State::STATE_IDLE, state());
525
526 const char retry_after[] = "HTTP/1.1 503 OK\nRetry-After: 1\n\n";
527
528 ASSERT_EQ(State::STATE_IDLE, state());
529 ASSERT_EQ(0, no_response_result_count());
530
531 SetConnected(kStubWireless1);
532 CompleteURLFetch(net::OK, 503, retry_after);
533
534 // First portal detection completed, next portal detection is
535 // scheduled after 3 seconds (due to minimum time between detection
536 // attemps).
537 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
538 ASSERT_EQ(1, no_response_result_count());
539 }
540
TEST_F(NetworkPortalDetectorImplTest,FirstAttemptFailed)541 TEST_F(NetworkPortalDetectorImplTest, FirstAttemptFailed) {
542 ASSERT_EQ(State::STATE_IDLE, state());
543
544 set_delay_till_next_attempt(base::TimeDelta());
545 const char retry_after[] = "HTTP/1.1 503 OK\nRetry-After: 0\n\n";
546
547 ASSERT_EQ(State::STATE_IDLE, state());
548 ASSERT_EQ(0, no_response_result_count());
549
550 SetConnected(kStubWireless1);
551
552 CompleteURLFetch(net::OK, 503, retry_after);
553 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
554 ASSERT_EQ(1, no_response_result_count());
555 ASSERT_EQ(base::TimeDelta::FromSeconds(0), next_attempt_delay());
556
557 // To run CaptivePortalDetector::DetectCaptivePortal().
558 base::RunLoop().RunUntilIdle();
559
560 CompleteURLFetch(net::OK, 204, nullptr);
561 EXPECT_NE(State::STATE_IDLE, state());
562 ASSERT_EQ(0, no_response_result_count());
563 EXPECT_TRUE(
564 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204,
565 kStubWireless1));
566 }
567
TEST_F(NetworkPortalDetectorImplTest,AllAttemptsFailed)568 TEST_F(NetworkPortalDetectorImplTest, AllAttemptsFailed) {
569 ASSERT_EQ(State::STATE_IDLE, state());
570
571 set_delay_till_next_attempt(base::TimeDelta());
572 const char retry_after[] = "HTTP/1.1 503 OK\nRetry-After: 0\n\n";
573
574 ASSERT_EQ(State::STATE_IDLE, state());
575 ASSERT_EQ(0, no_response_result_count());
576
577 SetConnected(kStubWireless1);
578
579 CompleteURLFetch(net::OK, 503, retry_after);
580 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
581 ASSERT_EQ(1, no_response_result_count());
582 ASSERT_EQ(base::TimeDelta::FromSeconds(0), next_attempt_delay());
583
584 // To run CaptivePortalDetector::DetectCaptivePortal().
585 base::RunLoop().RunUntilIdle();
586
587 CompleteURLFetch(net::OK, 503, retry_after);
588 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
589 ASSERT_EQ(2, no_response_result_count());
590 ASSERT_EQ(base::TimeDelta::FromSeconds(0), next_attempt_delay());
591
592 // To run CaptivePortalDetector::DetectCaptivePortal().
593 base::RunLoop().RunUntilIdle();
594
595 CompleteURLFetch(net::OK, 503, retry_after);
596 EXPECT_NE(State::STATE_IDLE, state());
597 ASSERT_EQ(3, no_response_result_count());
598 EXPECT_TRUE(
599 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE,
600 503, kStubWireless1));
601 }
602
TEST_F(NetworkPortalDetectorImplTest,ProxyAuthRequired)603 TEST_F(NetworkPortalDetectorImplTest, ProxyAuthRequired) {
604 ASSERT_EQ(State::STATE_IDLE, state());
605 set_delay_till_next_attempt(base::TimeDelta());
606
607 SetConnected(kStubWireless1);
608 CompleteURLFetch(net::OK, 407, nullptr);
609 ASSERT_EQ(1, no_response_result_count());
610 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
611
612 base::RunLoop().RunUntilIdle();
613 CompleteURLFetch(net::OK, 407, nullptr);
614 ASSERT_EQ(2, no_response_result_count());
615 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
616
617 base::RunLoop().RunUntilIdle();
618 CompleteURLFetch(net::OK, 407, nullptr);
619 ASSERT_EQ(3, no_response_result_count());
620 EXPECT_NE(State::STATE_IDLE, state());
621
622 EXPECT_TRUE(CheckPortalState(
623 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED, 407,
624 kStubWireless1));
625 }
626
TEST_F(NetworkPortalDetectorImplTest,NoResponseButBehindPortal)627 TEST_F(NetworkPortalDetectorImplTest, NoResponseButBehindPortal) {
628 ASSERT_EQ(State::STATE_IDLE, state());
629 set_delay_till_next_attempt(base::TimeDelta());
630
631 SetBehindPortal(kStubWireless1);
632 ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
633
634 CompleteURLFetch(net::ERR_CONNECTION_CLOSED, 0, nullptr);
635 ASSERT_EQ(1, no_response_result_count());
636 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
637
638 // To run CaptivePortalDetector::DetectCaptivePortal().
639 base::RunLoop().RunUntilIdle();
640
641 CompleteURLFetch(net::ERR_CONNECTION_CLOSED, 0, nullptr);
642 ASSERT_EQ(2, no_response_result_count());
643 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
644
645 // To run CaptivePortalDetector::DetectCaptivePortal().
646 base::RunLoop().RunUntilIdle();
647
648 CompleteURLFetch(net::ERR_CONNECTION_CLOSED, 0, nullptr);
649 ASSERT_EQ(3, no_response_result_count());
650 EXPECT_NE(State::STATE_IDLE, state());
651
652 EXPECT_TRUE(CheckPortalState(
653 NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 0, kStubWireless1));
654 }
655
TEST_F(NetworkPortalDetectorImplTest,DisableErrorScreenStrategyWhilePendingRequest)656 TEST_F(NetworkPortalDetectorImplTest,
657 DisableErrorScreenStrategyWhilePendingRequest) {
658 ASSERT_EQ(State::STATE_IDLE, state());
659 set_no_response_result_count(3);
660 enable_error_screen_strategy();
661 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
662 disable_error_screen_strategy();
663
664 // To run CaptivePortalDetector::DetectCaptivePortal().
665 base::RunLoop().RunUntilIdle();
666 }
667
TEST_F(NetworkPortalDetectorImplTest,ErrorScreenStrategyForOnlineNetwork)668 TEST_F(NetworkPortalDetectorImplTest, ErrorScreenStrategyForOnlineNetwork) {
669 ASSERT_EQ(State::STATE_IDLE, state());
670 set_delay_till_next_attempt(base::TimeDelta());
671
672 SetConnected(kStubWireless1);
673 enable_error_screen_strategy();
674 // To run CaptivePortalDetector::DetectCaptivePortal().
675 base::RunLoop().RunUntilIdle();
676 CompleteURLFetch(net::OK, 204, nullptr);
677
678 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
679 EXPECT_TRUE(
680 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204,
681 kStubWireless1));
682
683 // To run CaptivePortalDetector::DetectCaptivePortal().
684 base::RunLoop().RunUntilIdle();
685
686 CompleteURLFetch(net::OK, 204, nullptr);
687
688 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
689 EXPECT_TRUE(
690 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204,
691 kStubWireless1));
692
693 // To run CaptivePortalDetector::DetectCaptivePortal().
694 base::RunLoop().RunUntilIdle();
695
696 disable_error_screen_strategy();
697
698 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
699 // To run CaptivePortalDetector::DetectCaptivePortal().
700 base::RunLoop().RunUntilIdle();
701 ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
702 CompleteURLFetch(net::OK, 204, nullptr);
703
704 EXPECT_TRUE(
705 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204,
706 kStubWireless1));
707 }
708
TEST_F(NetworkPortalDetectorImplTest,ErrorScreenStrategyForPortalNetwork)709 TEST_F(NetworkPortalDetectorImplTest, ErrorScreenStrategyForPortalNetwork) {
710 ASSERT_EQ(State::STATE_IDLE, state());
711 set_delay_till_next_attempt(base::TimeDelta());
712
713 enable_error_screen_strategy();
714 SetConnected(kStubWireless1);
715
716 CompleteURLFetch(net::ERR_CONNECTION_CLOSED, 0, nullptr);
717 ASSERT_EQ(1, no_response_result_count());
718 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
719 EXPECT_TRUE(
720 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN, -1,
721 kStubWireless1));
722
723 // To run CaptivePortalDetector::DetectCaptivePortal().
724 base::RunLoop().RunUntilIdle();
725
726 CompleteURLFetch(net::ERR_CONNECTION_CLOSED, 0, nullptr);
727 ASSERT_EQ(2, no_response_result_count());
728 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
729 EXPECT_TRUE(
730 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN, -1,
731 kStubWireless1));
732
733 // To run CaptivePortalDetector::DetectCaptivePortal().
734 base::RunLoop().RunUntilIdle();
735
736 CompleteURLFetch(net::OK, 200, nullptr);
737 ASSERT_EQ(0, no_response_result_count());
738 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
739 EXPECT_TRUE(
740 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 200,
741 kStubWireless1));
742
743 // To run CaptivePortalDetector::DetectCaptivePortal().
744 base::RunLoop().RunUntilIdle();
745
746 disable_error_screen_strategy();
747
748 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
749 EXPECT_TRUE(
750 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN,
751 200, kStubWireless1));
752 }
753
TEST_F(NetworkPortalDetectorImplTest,DetectionTimeoutIsCancelled)754 TEST_F(NetworkPortalDetectorImplTest, DetectionTimeoutIsCancelled) {
755 ASSERT_EQ(State::STATE_IDLE, state());
756 set_delay_till_next_attempt(base::TimeDelta());
757
758 SetConnected(kStubWireless1);
759 ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
760 EXPECT_TRUE(
761 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN, -1,
762 kStubWireless1));
763
764 stop_detection();
765
766 ASSERT_EQ(State::STATE_IDLE, state());
767 ASSERT_TRUE(attempt_timeout_is_cancelled());
768 EXPECT_TRUE(
769 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN, -1,
770 kStubWireless1));
771 }
772
TEST_F(NetworkPortalDetectorImplTest,TestDetectionRestart)773 TEST_F(NetworkPortalDetectorImplTest, TestDetectionRestart) {
774 ASSERT_EQ(State::STATE_IDLE, state());
775 set_delay_till_next_attempt(base::TimeDelta());
776
777 // First portal detection attempts determines ONLINE state.
778 SetConnected(kStubWireless1);
779 ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
780 StartPortalDetection();
781
782 CompleteURLFetch(net::OK, 204, nullptr);
783
784 EXPECT_TRUE(
785 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204,
786 kStubWireless1));
787 EXPECT_NE(State::STATE_IDLE, state());
788
789 // First portal detection attempts determines PORTAL state.
790 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
791
792 base::RunLoop().RunUntilIdle();
793 ASSERT_EQ(State::STATE_CHECKING_FOR_PORTAL, state());
794 CompleteURLFetch(net::OK, 200, nullptr);
795
796 EXPECT_TRUE(
797 CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 200,
798 kStubWireless1));
799 EXPECT_NE(State::STATE_IDLE, state());
800 }
801
TEST_F(NetworkPortalDetectorImplTest,RequestTimeouts)802 TEST_F(NetworkPortalDetectorImplTest, RequestTimeouts) {
803 ASSERT_EQ(State::STATE_IDLE, state());
804 set_delay_till_next_attempt(base::TimeDelta());
805
806 SetNetworkDeviceEnabled(shill::kTypeWifi, false);
807 SetConnected(kStubCellular);
808
809 // First portal detection attempt for cellular1 uses 5sec timeout.
810 CheckRequestTimeoutAndCompleteAttempt(
811 0 /* expected_same_detection_result_count */,
812 0 /* expected_no_response_result_count */,
813 5 /* expected_request_timeout_sec */, net::ERR_CONNECTION_CLOSED, 0);
814
815 // Second portal detection attempt for cellular1 uses 10sec timeout.
816 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
817 base::RunLoop().RunUntilIdle();
818 CheckRequestTimeoutAndCompleteAttempt(
819 1 /* expected_same_detection_result_count */,
820 1 /* expected_no_response_result_count */,
821 10 /* expected_request_timeout_sec */, net::ERR_CONNECTION_CLOSED, 0);
822
823 // Third portal detection attempt for cellular1 uses 15sec timeout.
824 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
825 base::RunLoop().RunUntilIdle();
826 CheckRequestTimeoutAndCompleteAttempt(
827 2 /* expected_same_detection_result_count */,
828 2 /* expected_no_response_result_count */,
829 15 /* expected_request_timeout_sec */, net::ERR_CONNECTION_CLOSED, 0);
830
831 EXPECT_NE(State::STATE_IDLE, state());
832
833 // Check that on the error screen 15sec timeout is used.
834 enable_error_screen_strategy();
835 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
836 base::RunLoop().RunUntilIdle();
837 CheckRequestTimeoutAndCompleteAttempt(
838 0 /* expected_same_detection_result_count */,
839 0 /* expected_no_response_result_count */,
840 15 /* expected_request_timeout_sec */, net::ERR_CONNECTION_CLOSED, 0);
841 disable_error_screen_strategy();
842 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
843
844 SetNetworkDeviceEnabled(shill::kTypeWifi, true);
845 SetConnected(kStubWireless1);
846
847 // First portal detection attempt for wifi1 uses 5sec timeout.
848 CheckRequestTimeoutAndCompleteAttempt(
849 0 /* expected_same_detection_result_count */,
850 0 /* expected_no_response_result_count */,
851 5 /* expected_request_timeout_sec */, net::ERR_CONNECTION_CLOSED, 0);
852
853 // Second portal detection attempt for wifi1 also uses 5sec timeout.
854 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
855 base::RunLoop().RunUntilIdle();
856 CheckRequestTimeoutAndCompleteAttempt(
857 1 /* expected_same_detection_result_count */,
858 1 /* expected_no_response_result_count */,
859 10 /* expected_request_timeout_sec */, net::OK, 204);
860 EXPECT_NE(State::STATE_IDLE, state());
861
862 // Check that in error screen strategy detection for wifi1 15sec
863 // timeout is used.
864 enable_error_screen_strategy();
865 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
866 base::RunLoop().RunUntilIdle();
867 CheckRequestTimeoutAndCompleteAttempt(
868 0 /* expected_same_detection_result_count */,
869 0 /* expected_no_response_result_count */,
870 15 /* expected_request_timeout_sec */, net::OK, 204);
871 disable_error_screen_strategy();
872 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
873 }
874
TEST_F(NetworkPortalDetectorImplTest,RequestTimeouts2)875 TEST_F(NetworkPortalDetectorImplTest, RequestTimeouts2) {
876 ASSERT_EQ(State::STATE_IDLE, state());
877 set_delay_till_next_attempt(base::TimeDelta());
878 SetConnected(kStubWireless1);
879
880 // First portal detection attempt for wifi1 uses 5sec timeout.
881 CheckRequestTimeoutAndCompleteAttempt(
882 0 /* expected_same_detection_result_count */,
883 0 /* expected_no_response_result_count */,
884 5 /* expected_request_timeout_sec */, net::ERR_CONNECTION_CLOSED, 0);
885 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
886 base::RunLoop().RunUntilIdle();
887
888 // Second portal detection attempt for wifi1 uses 10sec timeout.
889 CheckRequestTimeoutAndCompleteAttempt(
890 1 /* expected_same_detection_result_count */,
891 1 /* expected_no_response_result_count */,
892 10 /* expected_request_timeout_sec */, net::ERR_CONNECTION_CLOSED, 0);
893 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
894 base::RunLoop().RunUntilIdle();
895
896 // Second portal detection attempt for wifi1 uses 15sec timeout.
897 CheckRequestTimeoutAndCompleteAttempt(
898 2 /* expected_same_detection_result_count */,
899 2 /* expected_no_response_result_count */,
900 15 /* expected_request_timeout_sec */, net::ERR_CONNECTION_CLOSED, 0);
901 EXPECT_NE(State::STATE_IDLE, state());
902 ASSERT_EQ(State::STATE_PORTAL_CHECK_PENDING, state());
903
904 // Third portal detection attempt for wifi1 uses 20sec timeout.
905 base::RunLoop().RunUntilIdle();
906 CheckRequestTimeoutAndCompleteAttempt(
907 3 /* expected_same_detection_result_count */,
908 3 /* expected_no_response_result_count */,
909 20 /* expected_request_timeout_sec */, net::OK, 204);
910 EXPECT_NE(State::STATE_IDLE, state());
911
912 // Fourth portal detection attempt for wifi1 uses 5sec timeout.
913 base::RunLoop().RunUntilIdle();
914 CheckRequestTimeoutAndCompleteAttempt(
915 1 /* expected_same_detection_result_count */,
916 0 /* expected_no_response_result_count */,
917 5 /* expected_request_timeout_sec */, net::OK, 204);
918 EXPECT_NE(State::STATE_IDLE, state());
919 }
920
921 } // namespace chromeos
922