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