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