| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_BROWSER_CAPTIVE_PORTAL_CAPTIVE_PORTAL_SERVICE_H_ |
| #define CHROME_BROWSER_CAPTIVE_PORTAL_CAPTIVE_PORTAL_SERVICE_H_ |
| |
| #include "base/basictypes.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/prefs/pref_member.h" |
| #include "base/threading/non_thread_safe.h" |
| #include "base/time/time.h" |
| #include "base/timer/timer.h" |
| #include "chrome/browser/captive_portal/captive_portal_detector.h" |
| #include "components/browser_context_keyed_service/browser_context_keyed_service.h" |
| #include "net/base/backoff_entry.h" |
| #include "url/gurl.h" |
| |
| class Profile; |
| |
| namespace captive_portal { |
| |
| // Service that checks for captive portals when queried, and sends a |
| // NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT with the Profile as the source and |
| // a CaptivePortalService::Results as the details. |
| // |
| // Captive portal checks are rate-limited. The CaptivePortalService may only |
| // be accessed on the UI thread. |
| // Design doc: https://docs.google.com/document/d/1k-gP2sswzYNvryu9NcgN7q5XrsMlUdlUdoW9WRaEmfM/edit |
| class CaptivePortalService : public BrowserContextKeyedService, |
| public base::NonThreadSafe { |
| public: |
| enum TestingState { |
| NOT_TESTING, |
| DISABLED_FOR_TESTING, // The service is always disabled. |
| SKIP_OS_CHECK_FOR_TESTING // The service can be enabled even if the OS has |
| // native captive portal detection. |
| }; |
| |
| // The details sent via a NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT. |
| struct Results { |
| // The result of the second most recent captive portal check. |
| Result previous_result; |
| // The result of the most recent captive portal check. |
| Result result; |
| }; |
| |
| explicit CaptivePortalService(Profile* profile); |
| virtual ~CaptivePortalService(); |
| |
| // Triggers a check for a captive portal. If there's already a check in |
| // progress, does nothing. Throttles the rate at which requests are sent. |
| // Always sends the result notification asynchronously. |
| void DetectCaptivePortal(); |
| |
| // Returns the URL used for captive portal testing. When a captive portal is |
| // detected, this URL will take us to the captive portal landing page. |
| const GURL& test_url() const { return test_url_; } |
| |
| // Result of the most recent captive portal check. |
| Result last_detection_result() const { return last_detection_result_; } |
| |
| // Whether or not the CaptivePortalService is enabled. When disabled, all |
| // checks return INTERNET_CONNECTED. |
| bool enabled() const { return enabled_; } |
| |
| // Used to disable captive portal detection so it doesn't interfere with |
| // tests. Should be called before the service is created. |
| static void set_state_for_testing(TestingState testing_state) { |
| testing_state_ = testing_state; |
| } |
| static TestingState get_state_for_testing() { return testing_state_; } |
| |
| private: |
| friend class CaptivePortalServiceTest; |
| friend class CaptivePortalBrowserTest; |
| |
| // Subclass of BackoffEntry that uses the CaptivePortalService's |
| // GetCurrentTime function, for unit testing. |
| class RecheckBackoffEntry; |
| |
| enum State { |
| // No check is running or pending. |
| STATE_IDLE, |
| // The timer to check for a captive portal is running. |
| STATE_TIMER_RUNNING, |
| // There's an outstanding HTTP request to check for a captive portal. |
| STATE_CHECKING_FOR_PORTAL, |
| }; |
| |
| // Contains all the information about the minimum time allowed between two |
| // consecutive captive portal checks. |
| struct RecheckPolicy { |
| // Constructor initializes all values to defaults. |
| RecheckPolicy(); |
| |
| // The minimum amount of time between two captive portal checks, when the |
| // last check found no captive portal. |
| int initial_backoff_no_portal_ms; |
| |
| // The minimum amount of time between two captive portal checks, when the |
| // last check found a captive portal. This is expected to be less than |
| // |initial_backoff_no_portal_ms|. Also used when the service is disabled. |
| int initial_backoff_portal_ms; |
| |
| net::BackoffEntry::Policy backoff_policy; |
| }; |
| |
| // Initiates a captive portal check, without any throttling. If the service |
| // is disabled, just acts like there's an Internet connection. |
| void DetectCaptivePortalInternal(); |
| |
| // Called by CaptivePortalDetector when detection completes. |
| void OnPortalDetectionCompleted( |
| const CaptivePortalDetector::Results& results); |
| |
| // BrowserContextKeyedService: |
| virtual void Shutdown() OVERRIDE; |
| |
| // Called when a captive portal check completes. Passes the result to all |
| // observers. |
| void OnResult(Result result); |
| |
| // Updates BackoffEntry::Policy and creates a new BackoffEntry, which |
| // resets the count used for throttling. |
| void ResetBackoffEntry(Result result); |
| |
| // Updates |enabled_| based on command line flags and Profile preferences, |
| // and sets |state_| to STATE_NONE if it's false. |
| // TODO(mmenke): Figure out on which platforms, if any, should not use |
| // automatic captive portal detection. Currently it's enabled |
| // on all platforms, though this code is not compiled on |
| // Android, since it lacks the Browser class. |
| void UpdateEnabledState(); |
| |
| // Returns the current TimeTicks. |
| base::TimeTicks GetCurrentTimeTicks() const; |
| |
| bool DetectionInProgress() const; |
| |
| // Returns true if the timer to try and detect a captive portal is running. |
| bool TimerRunning() const; |
| |
| State state() const { return state_; } |
| |
| RecheckPolicy& recheck_policy() { return recheck_policy_; } |
| |
| void set_test_url(const GURL& test_url) { test_url_ = test_url; } |
| |
| // Sets current test time ticks. Used by unit tests. |
| void set_time_ticks_for_testing(const base::TimeTicks& time_ticks) { |
| time_ticks_for_testing_ = time_ticks; |
| } |
| |
| // Advances current test time ticks. Used by unit tests. |
| void advance_time_ticks_for_testing(const base::TimeDelta& delta) { |
| time_ticks_for_testing_ += delta; |
| } |
| |
| // The profile that owns this CaptivePortalService. |
| Profile* profile_; |
| |
| State state_; |
| |
| // Detector for checking active network for a portal state. |
| CaptivePortalDetector captive_portal_detector_; |
| |
| // True if the service is enabled. When not enabled, all checks will return |
| // RESULT_INTERNET_CONNECTED. |
| bool enabled_; |
| |
| // The result of the most recent captive portal check. |
| Result last_detection_result_; |
| |
| // Number of sequential checks with the same captive portal result. |
| int num_checks_with_same_result_; |
| |
| // Time when |last_detection_result_| was first received. |
| base::TimeTicks first_check_time_with_same_result_; |
| |
| // Time the last captive portal check completed. |
| base::TimeTicks last_check_time_; |
| |
| // Policy for throttling portal checks. |
| RecheckPolicy recheck_policy_; |
| |
| // Implements behavior needed by |recheck_policy_|. Whenever there's a new |
| // captive_portal::Result, BackoffEntry::Policy is updated and |
| // |backoff_entry_| is recreated. Each check that returns the same Result |
| // is considered a "failure", to trigger throttling. |
| scoped_ptr<net::BackoffEntry> backoff_entry_; |
| |
| // URL that returns a 204 response code when connected to the Internet. |
| GURL test_url_; |
| |
| // The pref member for whether navigation errors should be resolved with a web |
| // service. Actually called "alternate_error_pages", since it's also used for |
| // the Link Doctor. |
| BooleanPrefMember resolve_errors_with_web_service_; |
| |
| base::OneShotTimer<CaptivePortalService> check_captive_portal_timer_; |
| |
| static TestingState testing_state_; |
| |
| // Test time ticks used by unit tests. |
| base::TimeTicks time_ticks_for_testing_; |
| |
| DISALLOW_COPY_AND_ASSIGN(CaptivePortalService); |
| }; |
| |
| } // namespace captive_portal |
| |
| #endif // CHROME_BROWSER_CAPTIVE_PORTAL_CAPTIVE_PORTAL_SERVICE_H_ |