#ifndef CHROME_BROWSER_CHROMEOS_NET_NETWORK_PORTAL_DETECTOR_IMPL_H_
#define CHROME_BROWSER_CHROMEOS_NET_NETWORK_PORTAL_DETECTOR_IMPL_H_
#include <string>
#include "base/basictypes.h"
#include "base/cancelable_callback.h"
#include "base/compiler_specific.h"
#include "base/containers/hash_tables.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/threading/non_thread_safe.h"
#include "base/time/time.h"
#include "chrome/browser/captive_portal/captive_portal_detector.h"
#include "chrome/browser/chromeos/net/network_portal_detector.h"
#include "chrome/browser/chromeos/net/network_portal_detector_strategy.h"
#include "chrome/browser/chromeos/net/network_portal_notification_controller.h"
#include "chromeos/network/network_state_handler_observer.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"
namespace net {
class URLRequestContextGetter;
}
namespace chromeos {
class NetworkState;
class NetworkPortalDetectorImpl
: public NetworkPortalDetector,
public base::NonThreadSafe,
public chromeos::NetworkStateHandlerObserver,
public content::NotificationObserver,
public PortalDetectorStrategy::Delegate {
public:
static const char kOobeDetectionResultHistogram[];
static const char kOobeDetectionDurationHistogram[];
static const char kOobeShillOnlineHistogram[];
static const char kOobeShillPortalHistogram[];
static const char kOobeShillOfflineHistogram[];
static const char kOobePortalToOnlineHistogram[];
static const char kSessionDetectionResultHistogram[];
static const char kSessionDetectionDurationHistogram[];
static const char kSessionShillOnlineHistogram[];
static const char kSessionShillPortalHistogram[];
static const char kSessionShillOfflineHistogram[];
static const char kSessionPortalToOnlineHistogram[];
explicit NetworkPortalDetectorImpl(
const scoped_refptr<net::URLRequestContextGetter>& request_context);
virtual ~NetworkPortalDetectorImpl();
virtual void AddObserver(Observer* observer) OVERRIDE;
virtual void AddAndFireObserver(Observer* observer) OVERRIDE;
virtual void RemoveObserver(Observer* observer) OVERRIDE;
virtual CaptivePortalState GetCaptivePortalState(
const std::string& service_path) OVERRIDE;
virtual bool IsEnabled() OVERRIDE;
virtual void Enable(bool start_detection) OVERRIDE;
virtual bool StartDetectionIfIdle() OVERRIDE;
virtual void DefaultNetworkChanged(const NetworkState* network) OVERRIDE;
virtual int AttemptCount() OVERRIDE;
virtual base::TimeTicks AttemptStartTime() OVERRIDE;
virtual base::TimeTicks GetCurrentTimeTicks() OVERRIDE;
virtual void OnErrorScreenShow() OVERRIDE;
virtual void OnErrorScreenHide() OVERRIDE;
private:
friend class NetworkPortalDetectorImplTest;
friend class NetworkPortalDetectorImplBrowserTest;
typedef std::string NetworkId;
typedef base::hash_map<NetworkId, CaptivePortalState> CaptivePortalStateMap;
enum State {
STATE_IDLE = 0,
STATE_PORTAL_CHECK_PENDING,
STATE_CHECKING_FOR_PORTAL,
};
void StartDetection();
void StopDetection();
bool CanPerformAttempt() const;
void ScheduleAttempt(const base::TimeDelta& delay);
void StartAttempt();
void OnAttemptTimeout();
void OnAttemptCompleted(
const captive_portal::CaptivePortalDetector::Results& results);
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
void OnDetectionCompleted(const NetworkState* network,
const CaptivePortalState& results);
void NotifyDetectionCompleted(const NetworkState* network,
const CaptivePortalState& state);
void UpdateCurrentStrategy();
void SetStrategy(PortalDetectorStrategy::StrategyId id);
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 attempt_count_for_testing() {
return attempt_count_;
}
void set_attempt_count_for_testing(int attempt_count) {
attempt_count_ = attempt_count;
}
const base::TimeDelta& next_attempt_delay_for_testing() const {
return next_attempt_delay_;
}
bool AttemptTimeoutIsCancelledForTesting() const;
void RecordDetectionStats(const NetworkState* network,
CaptivePortalStatus status);
void set_time_ticks_for_testing(const base::TimeTicks& time_ticks) {
time_ticks_for_testing_ = time_ticks;
}
void advance_time_ticks_for_testing(const base::TimeDelta& delta) {
time_ticks_for_testing_ += delta;
}
std::string default_network_name_;
std::string default_network_id_;
std::string default_service_path_;
std::string default_connection_state_;
State state_;
CaptivePortalStateMap portal_state_map_;
ObserverList<Observer> observers_;
base::CancelableClosure attempt_task_;
base::CancelableClosure attempt_timeout_;
GURL test_url_;
scoped_ptr<captive_portal::CaptivePortalDetector> captive_portal_detector_;
bool enabled_;
base::WeakPtrFactory<NetworkPortalDetectorImpl> weak_factory_;
base::TimeTicks detection_start_time_;
base::TimeTicks attempt_start_time_;
int attempt_count_;
base::TimeDelta next_attempt_delay_;
scoped_ptr<PortalDetectorStrategy> strategy_;
bool error_screen_displayed_;
NetworkPortalNotificationController notification_controller_;
content::NotificationRegistrar registrar_;
base::TimeTicks time_ticks_for_testing_;
DISALLOW_COPY_AND_ASSIGN(NetworkPortalDetectorImpl);
};
}
#endif