1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
// Copyright 2014 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_PREDICTORS_RESOURCE_PREFETCHER_H_
#define CHROME_BROWSER_PREDICTORS_RESOURCE_PREFETCHER_H_
#include <list>
#include <map>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/threading/thread_checker.h"
#include "chrome/browser/predictors/resource_prefetch_common.h"
#include "net/url_request/redirect_info.h"
#include "net/url_request/url_request.h"
#include "url/gurl.h"
namespace net {
class URLRequestContext;
}
namespace predictors {
// Responsible for prefetching resources for a single navigation based on the
// input list of resources.
// - Limits the max number of resources in flight for any host and also across
// hosts.
// - When stopped, will wait for the pending requests to finish.
// - Lives entirely on the IO thread.
class ResourcePrefetcher : public net::URLRequest::Delegate {
public:
// Denotes the prefetch request for a single subresource.
struct Request {
explicit Request(const GURL& i_resource_url);
Request(const Request& other);
enum PrefetchStatus {
PREFETCH_STATUS_NOT_STARTED,
PREFETCH_STATUS_STARTED,
// Cancellation reasons.
PREFETCH_STATUS_REDIRECTED,
PREFETCH_STATUS_AUTH_REQUIRED,
PREFETCH_STATUS_CERT_REQUIRED,
PREFETCH_STATUS_CERT_ERROR,
PREFETCH_STATUS_CANCELLED,
PREFETCH_STATUS_FAILED,
// Successful prefetch states.
PREFETCH_STATUS_FROM_CACHE,
PREFETCH_STATUS_FROM_NETWORK
};
enum UsageStatus {
USAGE_STATUS_NOT_REQUESTED,
USAGE_STATUS_FROM_CACHE,
USAGE_STATUS_FROM_NETWORK,
USAGE_STATUS_NAVIGATION_ABANDONED
};
GURL resource_url;
PrefetchStatus prefetch_status;
UsageStatus usage_status;
};
typedef ScopedVector<Request> RequestVector;
// Used to communicate when the prefetching is done. All methods are invoked
// on the IO thread.
class Delegate {
public:
virtual ~Delegate() { }
// Called when the ResourcePrefetcher is finished, i.e. there is nothing
// pending in flight. Should take ownership of |requests|.
virtual void ResourcePrefetcherFinished(
ResourcePrefetcher* prefetcher,
RequestVector* requests) = 0;
virtual net::URLRequestContext* GetURLRequestContext() = 0;
};
// |delegate| has to outlive the ResourcePrefetcher. The ResourcePrefetcher
// takes ownership of |requests|.
ResourcePrefetcher(Delegate* delegate,
const ResourcePrefetchPredictorConfig& config,
const NavigationID& navigation_id,
PrefetchKeyType key_type,
scoped_ptr<RequestVector> requests);
~ResourcePrefetcher() override;
void Start(); // Kicks off the prefetching. Can only be called once.
void Stop(); // No additional prefetches will be queued after this.
const NavigationID& navigation_id() const { return navigation_id_; }
PrefetchKeyType key_type() const { return key_type_; }
private:
friend class ResourcePrefetcherTest;
friend class TestResourcePrefetcher;
// Launches new prefetch requests if possible.
void TryToLaunchPrefetchRequests();
// Starts a net::URLRequest for the input |request|.
void SendRequest(Request* request);
// Called by |SendRequest| to start the |request|. This is necessary to stub
// out the Start() call to net::URLRequest for unittesting.
virtual void StartURLRequest(net::URLRequest* request);
// Marks the request as finished, with the given status.
void FinishRequest(net::URLRequest* request, Request::PrefetchStatus status);
// Reads the response data from the response - required for the resource to
// be cached correctly. Stubbed out during testing.
virtual void ReadFullResponse(net::URLRequest* request);
// Returns true if the request has more data that needs to be read. If it
// returns false, the request should not be referenced again.
bool ShouldContinueReadingRequest(net::URLRequest* request, int bytes_read);
// net::URLRequest::Delegate methods.
void OnReceivedRedirect(net::URLRequest* request,
const net::RedirectInfo& redirect_info,
bool* defer_redirect) override;
void OnAuthRequired(net::URLRequest* request,
net::AuthChallengeInfo* auth_info) override;
void OnCertificateRequested(
net::URLRequest* request,
net::SSLCertRequestInfo* cert_request_info) override;
void OnSSLCertificateError(net::URLRequest* request,
const net::SSLInfo& ssl_info,
bool fatal) override;
void OnResponseStarted(net::URLRequest* request) override;
void OnReadCompleted(net::URLRequest* request, int bytes_read) override;
enum PrefetcherState {
INITIALIZED = 0, // Prefetching hasn't started.
RUNNING = 1, // Prefetching started, allowed to add more requests.
STOPPED = 2, // Prefetching started, not allowed to add more requests.
FINISHED = 3 // No more inflight request, new requests not possible.
};
base::ThreadChecker thread_checker_;
PrefetcherState state_;
Delegate* const delegate_;
ResourcePrefetchPredictorConfig const config_;
NavigationID navigation_id_;
PrefetchKeyType key_type_;
scoped_ptr<RequestVector> request_vector_;
std::map<net::URLRequest*, Request*> inflight_requests_;
std::list<Request*> request_queue_;
std::map<std::string, size_t> host_inflight_counts_;
DISALLOW_COPY_AND_ASSIGN(ResourcePrefetcher);
};
} // namespace predictors
#endif // CHROME_BROWSER_PREDICTORS_RESOURCE_PREFETCHER_H_
|