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 <string>
9
10#include "base/basictypes.h"
11#include "base/cancelable_callback.h"
12#include "base/compiler_specific.h"
13#include "base/containers/hash_tables.h"
14#include "base/memory/ref_counted.h"
15#include "base/memory/scoped_ptr.h"
16#include "base/memory/weak_ptr.h"
17#include "base/observer_list.h"
18#include "base/threading/non_thread_safe.h"
19#include "base/time/time.h"
20#include "chrome/browser/chromeos/net/network_portal_notification_controller.h"
21#include "chromeos/network/network_state_handler_observer.h"
22#include "chromeos/network/portal_detector/network_portal_detector.h"
23#include "chromeos/network/portal_detector/network_portal_detector_strategy.h"
24#include "components/captive_portal/captive_portal_detector.h"
25#include "components/captive_portal/captive_portal_types.h"
26#include "content/public/browser/notification_observer.h"
27#include "content/public/browser/notification_registrar.h"
28#include "net/url_request/url_fetcher.h"
29#include "url/gurl.h"
30
31namespace net {
32class URLRequestContextGetter;
33}
34
35namespace chromeos {
36
37class NetworkState;
38
39// This class handles all notifications about network changes from
40// NetworkStateHandler and delegates portal detection for the default
41// network to CaptivePortalService.
42class NetworkPortalDetectorImpl
43    : public NetworkPortalDetector,
44      public base::NonThreadSafe,
45      public chromeos::NetworkStateHandlerObserver,
46      public content::NotificationObserver,
47      public PortalDetectorStrategy::Delegate {
48 public:
49  static const char kOobeDetectionResultHistogram[];
50  static const char kOobeDetectionDurationHistogram[];
51  static const char kOobeShillOnlineHistogram[];
52  static const char kOobeShillPortalHistogram[];
53  static const char kOobeShillOfflineHistogram[];
54  static const char kOobePortalToOnlineHistogram[];
55
56  static const char kSessionDetectionResultHistogram[];
57  static const char kSessionDetectionDurationHistogram[];
58  static const char kSessionShillOnlineHistogram[];
59  static const char kSessionShillPortalHistogram[];
60  static const char kSessionShillOfflineHistogram[];
61  static const char kSessionPortalToOnlineHistogram[];
62
63  // Creates an instance of NetworkPortalDetectorImpl.
64  static void Initialize(net::URLRequestContextGetter* url_context);
65
66  explicit NetworkPortalDetectorImpl(
67      const scoped_refptr<net::URLRequestContextGetter>& request_context);
68  virtual ~NetworkPortalDetectorImpl();
69
70  // NetworkPortalDetector implementation:
71  virtual void AddObserver(Observer* observer) OVERRIDE;
72  virtual void AddAndFireObserver(Observer* observer) OVERRIDE;
73  virtual void RemoveObserver(Observer* observer) OVERRIDE;
74  virtual CaptivePortalState GetCaptivePortalState(
75      const std::string& guid) OVERRIDE;
76  virtual bool IsEnabled() OVERRIDE;
77  virtual void Enable(bool start_detection) OVERRIDE;
78  virtual bool StartDetectionIfIdle() OVERRIDE;
79  virtual void SetStrategy(PortalDetectorStrategy::StrategyId id) OVERRIDE;
80
81  // NetworkStateHandlerObserver implementation:
82  virtual void DefaultNetworkChanged(const NetworkState* network) OVERRIDE;
83
84  // PortalDetectorStrategy::Delegate implementation:
85  virtual int NoResponseResultCount() OVERRIDE;
86  virtual base::TimeTicks AttemptStartTime() OVERRIDE;
87  virtual base::TimeTicks GetCurrentTimeTicks() OVERRIDE;
88
89 private:
90  friend class NetworkPortalDetectorImplTest;
91  friend class NetworkPortalDetectorImplBrowserTest;
92
93  struct DetectionAttemptCompletedReport {
94    DetectionAttemptCompletedReport();
95
96    DetectionAttemptCompletedReport(const std::string network_name,
97                                    const std::string network_id,
98                                    captive_portal::CaptivePortalResult result,
99                                    int response_code);
100
101    void Report() const;
102
103    bool Equals(const DetectionAttemptCompletedReport& o) const;
104
105    std::string network_name;
106    std::string network_id;
107    captive_portal::CaptivePortalResult result;
108    int response_code;
109  };
110
111  typedef std::string NetworkId;
112  typedef base::hash_map<NetworkId, CaptivePortalState> CaptivePortalStateMap;
113
114  enum State {
115    // No portal check is running.
116    STATE_IDLE = 0,
117    // Waiting for portal check.
118    STATE_PORTAL_CHECK_PENDING,
119    // Portal check is in progress.
120    STATE_CHECKING_FOR_PORTAL,
121  };
122
123  // Starts detection process.
124  void StartDetection();
125
126  // Stops whole detection process.
127  void StopDetection();
128
129  // Initiates Captive Portal detection attempt after |delay|.
130  void ScheduleAttempt(const base::TimeDelta& delay);
131
132  // Starts detection attempt.
133  void StartAttempt();
134
135  // Called when portal check is timed out. Cancels portal check and calls
136  // OnPortalDetectionCompleted() with RESULT_NO_RESPONSE as a result.
137  void OnAttemptTimeout();
138
139  // Called by CaptivePortalDetector when detection attempt completes.
140  void OnAttemptCompleted(
141      const captive_portal::CaptivePortalDetector::Results& results);
142
143  // content::NotificationObserver implementation:
144  virtual void Observe(int type,
145                       const content::NotificationSource& source,
146                       const content::NotificationDetails& details) OVERRIDE;
147
148  // Stores captive portal state for a |network| and notifies observers.
149  void OnDetectionCompleted(const NetworkState* network,
150                            const CaptivePortalState& results);
151
152  // Notifies observers that portal detection is completed for a |network|.
153  void NotifyDetectionCompleted(const NetworkState* network,
154                                const CaptivePortalState& state);
155
156  State state() const { return state_; }
157
158  bool is_idle() const {
159    return state_ == STATE_IDLE;
160  }
161  bool is_portal_check_pending() const {
162    return state_ == STATE_PORTAL_CHECK_PENDING;
163  }
164  bool is_checking_for_portal() const {
165    return state_ == STATE_CHECKING_FOR_PORTAL;
166  }
167
168  int same_detection_result_count_for_testing() const {
169    return same_detection_result_count_;
170  }
171
172  int no_response_result_count_for_testing() const {
173    return no_response_result_count_;
174  }
175
176  void set_no_response_result_count_for_testing(int count) {
177    no_response_result_count_ = count;
178  }
179
180  // Returns delay before next portal check. Used by unit tests.
181  const base::TimeDelta& next_attempt_delay_for_testing() const {
182    return next_attempt_delay_;
183  }
184
185  // Returns true if attempt timeout callback isn't fired or
186  // cancelled.
187  bool AttemptTimeoutIsCancelledForTesting() const;
188
189  // Record detection stats such as detection duration and detection
190  // result in UMA.
191  void RecordDetectionStats(const NetworkState* network,
192                            CaptivePortalStatus status);
193
194  // Resets strategy and all counters used in computations of
195  // timeouts.
196  void ResetStrategyAndCounters();
197
198  // Sets current test time ticks. Used by unit tests.
199  void set_time_ticks_for_testing(const base::TimeTicks& time_ticks) {
200    time_ticks_for_testing_ = time_ticks;
201  }
202
203  // Advances current test time ticks. Used by unit tests.
204  void advance_time_ticks_for_testing(const base::TimeDelta& delta) {
205    time_ticks_for_testing_ += delta;
206  }
207
208  // Name of the default network.
209  std::string default_network_name_;
210
211  // Unique identifier of the default network.
212  std::string default_network_id_;
213
214  // Connection state of the default network.
215  std::string default_connection_state_;
216
217  State state_;
218  CaptivePortalStateMap portal_state_map_;
219  ObserverList<Observer> observers_;
220
221  base::CancelableClosure attempt_task_;
222  base::CancelableClosure attempt_timeout_;
223
224  // URL that returns a 204 response code when connected to the Internet.
225  GURL test_url_;
226
227  // Detector for checking default network for a portal state.
228  scoped_ptr<captive_portal::CaptivePortalDetector> captive_portal_detector_;
229
230  // True if the NetworkPortalDetector is enabled.
231  bool enabled_;
232
233  // Start time of portal detection.
234  base::TimeTicks detection_start_time_;
235
236  // Start time of detection attempt.
237  base::TimeTicks attempt_start_time_;
238
239  // Delay before next portal detection.
240  base::TimeDelta next_attempt_delay_;
241
242  // Current detection strategy.
243  scoped_ptr<PortalDetectorStrategy> strategy_;
244
245  // Last received result from captive portal detector.
246  CaptivePortalStatus last_detection_result_;
247
248  // Number of detection attempts with same result in a row.
249  int same_detection_result_count_;
250
251  // Number of detection attempts in a row with NO RESPONSE result.
252  int no_response_result_count_;
253
254  // UI notification controller about captive portal state.
255  NetworkPortalNotificationController notification_controller_;
256
257  content::NotificationRegistrar registrar_;
258
259  // Test time ticks used by unit tests.
260  base::TimeTicks time_ticks_for_testing_;
261
262  // Contents of a last log message about completed detection attempt.
263  DetectionAttemptCompletedReport attempt_completed_report_;
264
265  base::WeakPtrFactory<NetworkPortalDetectorImpl> weak_factory_;
266
267  DISALLOW_COPY_AND_ASSIGN(NetworkPortalDetectorImpl);
268};
269
270}  // namespace chromeos
271
272#endif  // CHROME_BROWSER_CHROMEOS_NET_NETWORK_PORTAL_DETECTOR_IMPL_H_
273