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
165
|
// 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);
virtual ~ResourcePrefetcher();
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.
virtual void OnReceivedRedirect(net::URLRequest* request,
const net::RedirectInfo& redirect_info,
bool* defer_redirect) OVERRIDE;
virtual void OnAuthRequired(net::URLRequest* request,
net::AuthChallengeInfo* auth_info) OVERRIDE;
virtual void OnCertificateRequested(
net::URLRequest* request,
net::SSLCertRequestInfo* cert_request_info) OVERRIDE;
virtual void OnSSLCertificateError(net::URLRequest* request,
const net::SSLInfo& ssl_info,
bool fatal) OVERRIDE;
virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE;
virtual 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_
|