blob: 47111d605b26974039825594b1dd01bf7a184777 [file] [log] [blame]
// Copyright (c) 2013 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_CHROMEOS_NET_NETWORK_PORTAL_DETECTOR_IMPL_H_
#define CHROME_BROWSER_CHROMEOS_NET_NETWORK_PORTAL_DETECTOR_IMPL_H_
#include <map>
#include <memory>
#include <string>
#include "base/cancelable_callback.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "chromeos/network/network_state_handler_observer.h"
#include "chromeos/network/portal_detector/network_portal_detector.h"
#include "chromeos/network/portal_detector/network_portal_detector_strategy.h"
#include "components/captive_portal/captive_portal_detector.h"
#include "components/captive_portal/captive_portal_types.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "net/url_request/url_fetcher.h"
#include "url/gurl.h"
class NetworkingConfigTest;
namespace base {
class Value;
}
namespace network {
class SharedURLLoaderFactory;
namespace mojom {
class URLLoaderFactory;
}
} // namespace network
namespace chromeos {
class NetworkState;
// This class handles all notifications about network changes from
// NetworkStateHandler and delegates portal detection for the default
// network to CaptivePortalService.
class NetworkPortalDetectorImpl : public NetworkPortalDetector,
public chromeos::NetworkStateHandlerObserver,
public content::NotificationObserver,
public PortalDetectorStrategy::Delegate {
public:
// The delay since the default network shill reports a portal network, used to
// record UMA. Public for tests.
static constexpr base::TimeDelta kDelaySinceShillPortalForUMA =
base::TimeDelta::FromSeconds(60);
explicit NetworkPortalDetectorImpl(
network::mojom::URLLoaderFactory* loader_factory_for_testing = nullptr);
~NetworkPortalDetectorImpl() override;
// Set the URL to be tested for portal state.
void set_portal_test_url(const GURL& portal_test_url) {
portal_test_url_ = portal_test_url;
}
private:
friend class ::NetworkingConfigTest;
friend class NetworkPortalDetectorImplTest;
friend class NetworkPortalDetectorImplBrowserTest;
using CaptivePortalStateMap = std::map<std::string, CaptivePortalState>;
enum State {
// No portal check is running.
STATE_IDLE = 0,
// Waiting for portal check.
STATE_PORTAL_CHECK_PENDING,
// Portal check is in progress.
STATE_CHECKING_FOR_PORTAL,
};
struct DetectionAttemptCompletedReport {
DetectionAttemptCompletedReport();
DetectionAttemptCompletedReport(const std::string network_name,
const std::string network_id,
captive_portal::CaptivePortalResult result,
int response_code);
void Report() const;
bool Equals(const DetectionAttemptCompletedReport& o) const;
std::string network_name;
std::string network_id;
captive_portal::CaptivePortalResult result = captive_portal::RESULT_COUNT;
int response_code = -1;
};
// Starts detection process.
void StartDetection();
// Stops whole detection process.
void StopDetection();
// Stops and restarts the detection process.
void RetryDetection();
// Initiates Captive Portal detection attempt after |delay|.
void ScheduleAttempt(const base::TimeDelta& delay);
// Starts detection attempt.
void StartAttempt();
// Called when portal check is timed out. Cancels portal check and calls
// OnPortalDetectionCompleted() with RESULT_NO_RESPONSE as a result.
void OnAttemptTimeout();
// Called by CaptivePortalDetector when detection attempt completes.
void OnAttemptCompleted(
const captive_portal::CaptivePortalDetector::Results& results);
// NetworkPortalDetector implementation:
void AddObserver(Observer* observer) override;
void AddAndFireObserver(Observer* observer) override;
void RemoveObserver(Observer* observer) override;
CaptivePortalState GetCaptivePortalState(const std::string& guid) override;
bool IsEnabled() override;
void Enable(bool start_detection) override;
bool StartPortalDetection(bool force) override;
void SetStrategy(PortalDetectorStrategy::StrategyId id) override;
// NetworkStateHandlerObserver implementation:
void DefaultNetworkChanged(const NetworkState* network) override;
// PortalDetectorStrategy::Delegate implementation:
int NoResponseResultCount() override;
base::TimeTicks AttemptStartTime() override;
base::TimeTicks NowTicks() const override;
// content::NotificationObserver implementation:
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
// Called synchronously from OnAttemptCompleted with the current default
// network. Stores the captive portal state and notifies observers.
void DetectionCompleted(const NetworkState* network,
const CaptivePortalState& results);
// Notifies observers that portal detection is completed for a |network|.
void NotifyDetectionCompleted(const NetworkState* network,
const CaptivePortalState& state);
State state() const { return state_; }
bool is_idle() const {
return state_ == STATE_IDLE;
}
bool is_portal_check_pending() const {
return state_ == STATE_PORTAL_CHECK_PENDING;
}
bool is_checking_for_portal() const {
return state_ == STATE_CHECKING_FOR_PORTAL;
}
int same_detection_result_count_for_testing() const {
return same_detection_result_count_;
}
int no_response_result_count_for_testing() const {
return no_response_result_count_;
}
void set_no_response_result_count_for_testing(int count) {
no_response_result_count_ = count;
}
// Returns delay before next portal check. Used by unit tests.
const base::TimeDelta& next_attempt_delay_for_testing() const {
return next_attempt_delay_;
}
// Returns true if attempt timeout callback isn't fired or
// cancelled.
bool AttemptTimeoutIsCancelledForTesting() const;
// Record detection stats such as detection duration and detection
// result in UMA.
void RecordDetectionStats(const NetworkState* network,
CaptivePortalStatus status);
// Resets strategy and all counters used in computations of
// timeouts.
void ResetStrategyAndCounters();
// 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;
}
// Name of the default network.
std::string default_network_name_;
// Unique identifier of the default network.
std::string default_network_id_;
// Connection state of the default network.
std::string default_connection_state_;
// Proxy configuration of the default network.
std::unique_ptr<base::Value> default_proxy_config_;
State state_ = STATE_IDLE;
CaptivePortalStateMap portal_state_map_;
base::ObserverList<Observer>::Unchecked observers_;
base::CancelableClosure attempt_task_;
base::CancelableClosure attempt_timeout_;
// Reference to a SharedURLLoaderFactory used to detect portals.
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
// URL that returns a 204 response code when connected to the Internet. Used
// by tests.
GURL portal_test_url_;
// Detector for checking default network for a portal state.
std::unique_ptr<captive_portal::CaptivePortalDetector>
captive_portal_detector_;
// True if the NetworkPortalDetector is enabled.
bool enabled_ = false;
// Start time of portal detection.
base::TimeTicks detection_start_time_;
// Start time of detection attempt.
base::TimeTicks attempt_start_time_;
// Delay before next portal detection.
base::TimeDelta next_attempt_delay_;
// Saves the most recent timestamp that shill reports |default_network_id_|
// network is portal network.
base::TimeTicks last_shill_reports_portal_time_;
// Current detection strategy.
std::unique_ptr<PortalDetectorStrategy> strategy_;
// Last received result from captive portal detector.
CaptivePortalStatus last_detection_result_ = CAPTIVE_PORTAL_STATUS_UNKNOWN;
// Number of detection attempts with same result in a row.
int same_detection_result_count_ = 0;
// Number of detection attempts in a row with NO RESPONSE result.
int no_response_result_count_ = 0;
SEQUENCE_CHECKER(sequence_checker_);
content::NotificationRegistrar registrar_;
// Test time ticks used by unit tests.
base::TimeTicks time_ticks_for_testing_;
// Contents of a last log message about completed detection attempt.
DetectionAttemptCompletedReport attempt_completed_report_;
base::WeakPtrFactory<NetworkPortalDetectorImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(NetworkPortalDetectorImpl);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_NET_NETWORK_PORTAL_DETECTOR_IMPL_H_