blob: ae1673ae33d56a665dcdaf3ed76b7c454afb11db [file] [log] [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMECAST_NET_CONNECTIVITY_CHECKER_IMPL_H_
#define CHROMECAST_NET_CONNECTIVITY_CHECKER_IMPL_H_
#include <memory>
#include "base/cancelable_callback.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "chromecast/base/metrics/cast_metrics_helper.h"
#include "chromecast/net/connectivity_checker.h"
#include "chromecast/net/time_sync_tracker.h"
#include "net/http/http_status_code.h"
#include "services/network/public/cpp/network_connection_tracker.h"
class GURL;
namespace base {
class SingleThreadTaskRunner;
} // namespace base
namespace net {
class HttpResponseHeaders;
} // namespace net
namespace network {
class SharedURLLoaderFactory;
class SimpleURLLoader;
} // namespace network
namespace chromecast {
// Default (HTTPS) url for connectivity checking.
constexpr char kDefaultConnectivityCheckUrl[] =
"https://connectivitycheck.gstatic.com/generate_204";
// HTTP url for connectivity checking.
constexpr char kHttpConnectivityCheckUrl[] =
"http://connectivitycheck.gstatic.com/generate_204";
// The default URLs above are expected to respond with HTTP 204 (no content).
constexpr net::HttpStatusCode kConnectivitySuccessStatusCode =
net::HTTP_NO_CONTENT;
// Delay notification of network change events to smooth out rapid flipping.
constexpr base::TimeDelta kNetworkChangedDelay = base::Seconds(3);
// Simple class to check network connectivity by sending a HEAD http request
// to given url.
class ConnectivityCheckerImpl
: public ConnectivityChecker,
public network::NetworkConnectionTracker::NetworkConnectionObserver,
public TimeSyncTracker::Observer {
public:
// Types of errors that can occur when making a network URL request.
enum class ErrorType {
BAD_HTTP_STATUS = 1,
SSL_CERTIFICATE_ERROR = 2,
REQUEST_TIMEOUT = 3,
// A network error not captured by the ones above. See
// net/base/net_error_list.h for full set of errors that might fall under
// this category.
NET_ERROR = 4,
};
// Connectivity checking and initialization will run on task_runner.
static scoped_refptr<ConnectivityCheckerImpl> Create(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
std::unique_ptr<network::PendingSharedURLLoaderFactory>
pending_url_loader_factory,
network::NetworkConnectionTracker* network_connection_tracker,
TimeSyncTracker* time_sync_tracker);
// Connectivity checking and initialization will run on task_runner.
static scoped_refptr<ConnectivityCheckerImpl> Create(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
std::unique_ptr<network::PendingSharedURLLoaderFactory>
pending_url_loader_factory,
network::NetworkConnectionTracker* network_connection_tracker,
base::TimeDelta disconnected_probe_period,
base::TimeDelta connected_probe_period,
TimeSyncTracker* time_sync_tracker);
ConnectivityCheckerImpl(const ConnectivityCheckerImpl&) = delete;
ConnectivityCheckerImpl& operator=(const ConnectivityCheckerImpl&) = delete;
// ConnectivityChecker implementation:
bool Connected() const override;
void Check() override;
void SetCastMetricsHelperForTesting(
metrics::CastMetricsHelper* cast_metrics_helper);
protected:
ConnectivityCheckerImpl(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
network::NetworkConnectionTracker* network_connection_tracker,
base::TimeDelta disconnected_probe_period,
base::TimeDelta connected_probe_period,
TimeSyncTracker* time_sync_tracker);
~ConnectivityCheckerImpl() override;
private:
// Initializes ConnectivityChecker
void Initialize(std::unique_ptr<network::PendingSharedURLLoaderFactory>
pending_url_loader_factory);
// network::NetworkConnectionTracker::NetworkConnectionObserver
// implementation:
void OnConnectionChanged(network::mojom::ConnectionType type) override;
// TimeSyncTracker::Observer implementation:
void OnTimeSynced() override;
void OnConnectionChangedInternal();
void OnConnectivityCheckComplete(
scoped_refptr<net::HttpResponseHeaders> headers);
// Cancels current connectivity checking in progress.
void Cancel();
// Sets connectivity and alerts observers if it has changed
void SetConnected(bool connected);
// Called when URL request failed.
void OnUrlRequestError(ErrorType type);
// Called when URL request timed out. |Timeout| stores how long we waited
// for the URL request to finish before giving up.
void OnUrlRequestTimeout(base::TimeDelta timeout);
void CheckInternal();
std::unique_ptr<GURL> connectivity_check_url_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
std::unique_ptr<network::SimpleURLLoader> url_loader_;
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
network::NetworkConnectionTracker* const network_connection_tracker_;
TimeSyncTracker* const time_sync_tracker_;
metrics::CastMetricsHelper* cast_metrics_helper_;
// connected_lock_ protects access to connected_ which is shared across
// threads.
mutable base::Lock connected_lock_;
// Represents that the device has network connectivity and that time has
// synced.
bool connected_and_time_synced_;
// If the device has network connectivity.
bool network_connected_;
network::mojom::ConnectionType connection_type_;
// Number of connectivity check errors.
unsigned int check_errors_;
bool network_changed_pending_;
// Timeout handler for connectivity checks.
// Note: Cancelling this timeout can cause the destructor for this class to be
// called.
base::CancelableOnceCallback<void()> timeout_;
// Cancelable check handler used to cancel duplicate connectivity check.
base::CancelableOnceCallback<void()> delayed_check_;
// How often connectivity checks are performed while not connected.
const base::TimeDelta disconnected_probe_period_;
// How often connectivity checks are performed while connected.
const base::TimeDelta connected_probe_period_;
// Keeps track of whether this is the first time checking network
// connectivity due to a network change. To prevent unnecessary delays in Cast
// receiver initialization, kNetworkChangedDelay should only be applied on
// network changes after the first one.
bool first_connection_ = true;
base::WeakPtr<ConnectivityCheckerImpl> weak_this_;
base::WeakPtrFactory<ConnectivityCheckerImpl> weak_factory_;
};
} // namespace chromecast
#endif // CHROMECAST_NET_CONNECTIVITY_CHECKER_IMPL_H_