blob: 282da8842fb0ba7f7f45b9ed67c2d87997869150 [file] [log] [blame]
// Copyright 2019 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 COMPONENTS_OPTIMIZATION_GUIDE_HINTS_FETCHER_H_
#define COMPONENTS_OPTIMIZATION_GUIDE_HINTS_FETCHER_H_
#include <memory>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "components/optimization_guide/proto/hints.pb.h"
#include "url/gurl.h"
class PrefService;
namespace network {
class SharedURLLoaderFactory;
class SimpleURLLoader;
} // namespace network
namespace optimization_guide {
// Status of a request to fetch hints.
// This enum must remain synchronized with the enum
// |OptimizationGuideHintsFetcherRequestStatus| in
// tools/metrics/histograms/enums.xml.
enum class HintsFetcherRequestStatus {
// No fetch status known. Used in testing.
kUnknown,
// Fetch request was sent and a response received.
kSuccess,
// Fetch request was sent but no response received.
kResponseError,
// Fetch request not sent because of offline network status.
kNetworkOffline,
// Fetch request not sent because fetcher was busy with another request.
kFetcherBusy,
// Fetch request not sent because the host list was empty.
kNoHostsToFetch,
// Insert new values before this line.
kMaxValue = kNoHostsToFetch
};
// Callback to inform the caller that the remote hints have been fetched and
// to pass back the fetched hints response from the remote Optimization Guide
// Service.
using HintsFetchedCallback = base::OnceCallback<void(
optimization_guide::proto::RequestContext request_context,
HintsFetcherRequestStatus fetch_status,
base::Optional<std::unique_ptr<proto::GetHintsResponse>>)>;
// A class to handle requests for optimization hints from a remote Optimization
// Guide Service.
//
// This class fetches new hints from the remote Optimization Guide Service.
// Owner must ensure that |hint_cache| remains alive for the lifetime of
// |HintsFetcher|.
class HintsFetcher {
public:
HintsFetcher(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const GURL& optimization_guide_service_url,
PrefService* pref_service);
virtual ~HintsFetcher();
// Requests hints from the Optimization Guide Service if a request for them is
// not already in progress. Returns whether a new request was issued.
// |hints_fetched_callback| is run once when the outcome of this request is
// determined (whether a request was actually sent or not).
// Virtualized for testing. Hints fetcher may fetch hints for only a subset
// of the provided |hosts|. |hosts| should be an ordered list in descending
// order of probability that the hints are needed for that host.
virtual bool FetchOptimizationGuideServiceHints(
const std::vector<std::string>& hosts,
optimization_guide::proto::RequestContext request_context,
HintsFetchedCallback hints_fetched_callback);
// Set |time_clock_| for testing.
void SetTimeClockForTesting(const base::Clock* time_clock);
// Clear all the hosts and expiration times from the
// HintsFetcherHostsSuccessfullyFetched dictionary pref.
static void ClearHostsSuccessfullyFetched(PrefService* pref_service);
// Return whether the host was covered by a hints fetch and any returned hints
// would not have expired.
static bool WasHostCoveredByFetch(PrefService* pref_service,
const std::string& host);
static bool WasHostCoveredByFetch(PrefService* pref_service,
const std::string& host,
const base::Clock* clock);
private:
// URL loader completion callback.
void OnURLLoadComplete(std::unique_ptr<std::string> response_body);
// Handles the response from the remote Optimization Guide Service.
// |response| is the response body, |status| is the
// |net::Error| of the response, and response_code is the HTTP
// response code (if available).
void HandleResponse(const std::string& response,
int status,
int response_code);
// Stores the hosts in |hosts_in_fetch_| in the
// HintsFetcherHostsSuccessfullyFetched dictionary pref. The value stored for
// each host is the time that the hints fetched for each host will expire.
// |hosts_in_fetch_| is cleared once the hosts are stored
// in the pref.
void UpdateHostsSuccessfullyFetched();
// Returns the subset of hosts from |hosts| for which the hints should be
// refreshed. The count of returned hosts is limited to
// features::MaxHostsForOptimizationGuideServiceHintsFetch().
std::vector<std::string> GetSizeLimitedHostsDueForHintsRefresh(
const std::vector<std::string>& hosts) const;
// Used to hold the GetHintsRequest being constructed and sent as a remote
// request.
std::unique_ptr<proto::GetHintsRequest> get_hints_request_;
// Used to hold the callback while the SimpleURLLoader performs the request
// asynchronously.
HintsFetchedCallback hints_fetched_callback_;
// The URL for the remote Optimization Guide Service.
const GURL optimization_guide_service_url_;
// Holds the |URLLoader| for an active hints request.
std::unique_ptr<network::SimpleURLLoader> active_url_loader_;
// Context of the fetch request. Opaque field that's returned back in the
// callback and is also included in the requests to the hints server.
optimization_guide::proto::RequestContext request_context_;
// A reference to the PrefService for this profile. Not owned.
PrefService* pref_service_ = nullptr;
// Holds the hosts being requested by the hints fetcher.
std::vector<std::string> hosts_fetched_;
// Clock used for recording time that the hints fetch occurred.
const base::Clock* time_clock_;
// Used for creating an |active_url_loader_| when needed for request hints.
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
// The start time of the current hints fetch, used to determine the latency in
// retrieving hints from the remote Optimization Guide Service.
base::TimeTicks hints_fetch_start_time_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(HintsFetcher);
};
} // namespace optimization_guide
#endif // COMPONENTS_OPTIMIZATION_GUIDE_HINTS_FETCHER_H_