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 #ifndef CHROME_BROWSER_CHROMEOS_NET_NETWORK_PORTAL_DETECTOR_IMPL_H_
6 #define CHROME_BROWSER_CHROMEOS_NET_NETWORK_PORTAL_DETECTOR_IMPL_H_
7 
8 #include <map>
9 #include <memory>
10 #include <string>
11 
12 #include "base/callback_forward.h"
13 #include "base/cancelable_callback.h"
14 #include "base/compiler_specific.h"
15 #include "base/macros.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/memory/scoped_refptr.h"
18 #include "base/memory/weak_ptr.h"
19 #include "base/observer_list.h"
20 #include "base/sequence_checker.h"
21 #include "base/time/time.h"
22 #include "chromeos/network/network_state_handler_observer.h"
23 #include "chromeos/network/portal_detector/network_portal_detector.h"
24 #include "chromeos/network/portal_detector/network_portal_detector_strategy.h"
25 #include "components/captive_portal/core/captive_portal_detector.h"
26 #include "components/captive_portal/core/captive_portal_types.h"
27 #include "content/public/browser/notification_observer.h"
28 #include "content/public/browser/notification_registrar.h"
29 #include "url/gurl.h"
30 
31 namespace base {
32 class Value;
33 }
34 
35 namespace network {
36 class SharedURLLoaderFactory;
37 namespace mojom {
38 class URLLoaderFactory;
39 }
40 }  // namespace network
41 
42 namespace chromeos {
43 
44 class NetworkState;
45 
46 // This class handles all notifications about network changes from
47 // NetworkStateHandler and delegates portal detection for the default
48 // network to captive_portal::CaptivePortalService.
49 class NetworkPortalDetectorImpl : public NetworkPortalDetector,
50                                   public chromeos::NetworkStateHandlerObserver,
51                                   public content::NotificationObserver,
52                                   public PortalDetectorStrategy::Delegate {
53  public:
54   explicit NetworkPortalDetectorImpl(
55       network::mojom::URLLoaderFactory* loader_factory_for_testing = nullptr);
56   ~NetworkPortalDetectorImpl() override;
57 
58  private:
59   friend class NetworkPortalDetectorImplTest;
60   friend class NetworkPortalDetectorImplBrowserTest;
61 
62   enum State {
63     // No portal check is running.
64     STATE_IDLE = 0,
65     // Waiting for portal check.
66     STATE_PORTAL_CHECK_PENDING,
67     // Portal check is in progress.
68     STATE_CHECKING_FOR_PORTAL,
69   };
70 
71   // Starts detection process.
72   void StartDetection();
73 
74   // Stops whole detection process.
75   void StopDetection();
76 
77   // Stops and restarts the detection process.
78   void RetryDetection();
79 
80   // Initiates Captive Portal detection attempt after |delay|.
81   void ScheduleAttempt(const base::TimeDelta& delay);
82 
83   // Starts detection attempt.
84   void StartAttempt();
85 
86   // Called when portal check is timed out. Cancels portal check and calls
87   // OnPortalDetectionCompleted() with RESULT_NO_RESPONSE as a result.
88   void OnAttemptTimeout();
89 
90   // Called by CaptivePortalDetector when detection attempt completes.
91   void OnAttemptCompleted(
92       const captive_portal::CaptivePortalDetector::Results& results);
93 
94   // NetworkPortalDetector implementation:
95   void AddObserver(Observer* observer) override;
96   void AddAndFireObserver(Observer* observer) override;
97   void RemoveObserver(Observer* observer) override;
98   CaptivePortalStatus GetCaptivePortalStatus() override;
99   bool IsEnabled() override;
100   void Enable(bool start_detection) override;
101   void StartPortalDetection() override;
102   void SetStrategy(PortalDetectorStrategy::StrategyId id) override;
103 
104   // NetworkStateHandlerObserver implementation:
105   void DefaultNetworkChanged(const NetworkState* network) override;
106 
107   // PortalDetectorStrategy::Delegate implementation:
108   int NoResponseResultCount() override;
109   base::TimeTicks AttemptStartTime() override;
110   base::TimeTicks NowTicks() const override;
111 
112   // content::NotificationObserver implementation:
113   void Observe(int type,
114                const content::NotificationSource& source,
115                const content::NotificationDetails& details) override;
116 
117   // Called synchronously from OnAttemptCompleted with the current default
118   // network. Stores the captive portal status and notifies observers.
119   void DetectionCompleted(const NetworkState* network,
120                           const CaptivePortalStatus& results,
121                           int response_code);
122 
state()123   State state() const { return state_; }
124 
is_idle()125   bool is_idle() const { return state_ == STATE_IDLE; }
is_portal_check_pending()126   bool is_portal_check_pending() const {
127     return state_ == STATE_PORTAL_CHECK_PENDING;
128   }
is_checking_for_portal()129   bool is_checking_for_portal() const {
130     return state_ == STATE_CHECKING_FOR_PORTAL;
131   }
132 
same_detection_result_count_for_testing()133   int same_detection_result_count_for_testing() const {
134     return same_detection_result_count_;
135   }
136 
no_response_result_count_for_testing()137   int no_response_result_count_for_testing() const {
138     return no_response_result_count_;
139   }
140 
set_no_response_result_count_for_testing(int count)141   void set_no_response_result_count_for_testing(int count) {
142     no_response_result_count_ = count;
143   }
144 
145   // Returns delay before next portal check. Used by unit tests.
next_attempt_delay_for_testing()146   const base::TimeDelta& next_attempt_delay_for_testing() const {
147     return next_attempt_delay_;
148   }
149 
150   // Returns true if attempt timeout callback isn't fired or
151   // cancelled.
152   bool AttemptTimeoutIsCancelledForTesting() const;
153 
154   // Resets strategy and all counters used in computations of
155   // timeouts.
156   void ResetStrategyAndCounters();
157 
158   // Sets current test time ticks. Used by unit tests.
set_time_ticks_for_testing(const base::TimeTicks & time_ticks)159   void set_time_ticks_for_testing(const base::TimeTicks& time_ticks) {
160     time_ticks_for_testing_ = time_ticks;
161   }
162 
163   // Advances current test time ticks. Used by unit tests.
advance_time_ticks_for_testing(const base::TimeDelta & delta)164   void advance_time_ticks_for_testing(const base::TimeDelta& delta) {
165     time_ticks_for_testing_ += delta;
166   }
167 
default_network_id_for_testing()168   const std::string& default_network_id_for_testing() const {
169     return default_network_id_;
170   }
response_code_for_testing()171   int response_code_for_testing() const { return response_code_for_testing_; }
172 
173   // Unique identifier of the default network.
174   std::string default_network_id_;
175 
176   // Connection state of the default network.
177   std::string default_connection_state_;
178 
179   // Proxy configuration of the default network.
180   base::Value default_proxy_config_;
181 
182   CaptivePortalStatus default_portal_status_ = CAPTIVE_PORTAL_STATUS_UNKNOWN;
183   int response_code_for_testing_ = -1;
184 
185   State state_ = STATE_IDLE;
186   base::ObserverList<Observer>::Unchecked observers_;
187 
188   base::CancelableClosure attempt_task_;
189   base::CancelableClosure attempt_timeout_;
190 
191   // Reference to a SharedURLLoaderFactory used to detect portals.
192   scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
193 
194   // Detector for checking default network for a portal state.
195   std::unique_ptr<captive_portal::CaptivePortalDetector>
196       captive_portal_detector_;
197 
198   // True if the NetworkPortalDetector is enabled.
199   bool enabled_ = false;
200 
201   // Start time of portal detection.
202   base::TimeTicks detection_start_time_;
203 
204   // Start time of detection attempt.
205   base::TimeTicks attempt_start_time_;
206 
207   // Delay before next portal detection.
208   base::TimeDelta next_attempt_delay_;
209 
210   // Current detection strategy.
211   std::unique_ptr<PortalDetectorStrategy> strategy_;
212 
213   // Last received result from captive portal detector.
214   CaptivePortalStatus last_detection_result_ = CAPTIVE_PORTAL_STATUS_UNKNOWN;
215 
216   // Number of detection attempts with same result in a row.
217   int same_detection_result_count_ = 0;
218 
219   // Number of detection attempts in a row with NO RESPONSE result.
220   int no_response_result_count_ = 0;
221 
222   SEQUENCE_CHECKER(sequence_checker_);
223 
224   content::NotificationRegistrar registrar_;
225 
226   // Test time ticks used by unit tests.
227   base::TimeTicks time_ticks_for_testing_;
228 
229   base::WeakPtrFactory<NetworkPortalDetectorImpl> weak_factory_{this};
230 
231   DISALLOW_COPY_AND_ASSIGN(NetworkPortalDetectorImpl);
232 };
233 
234 }  // namespace chromeos
235 
236 #endif  // CHROME_BROWSER_CHROMEOS_NET_NETWORK_PORTAL_DETECTOR_IMPL_H_
237