Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: chrome/browser/predictors/resource_prefetcher.cc

Issue 2365613002: predictors: Refactor the prefetcher in resource_prefetch_predictor. (Closed)
Patch Set: . Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/predictors/resource_prefetcher.h" 5 #include "chrome/browser/predictors/resource_prefetcher.h"
6 6
7 #include <iterator> 7 #include <iterator>
8 #include <utility> 8 #include <utility>
9 9
10 #include "content/public/browser/browser_thread.h" 10 #include "content/public/browser/browser_thread.h"
11 #include "net/base/io_buffer.h" 11 #include "net/base/io_buffer.h"
12 #include "net/base/load_flags.h" 12 #include "net/base/load_flags.h"
13 #include "net/base/request_priority.h" 13 #include "net/base/request_priority.h"
14 #include "net/url_request/url_request_context.h" 14 #include "net/url_request/url_request_context.h"
15 #include "url/origin.h" 15 #include "url/origin.h"
16 16
17 namespace { 17 namespace {
18 18
19 // The size of the buffer used to read the resource. 19 // The size of the buffer used to read the resource.
20 static const size_t kResourceBufferSizeBytes = 50000; 20 static const size_t kResourceBufferSizeBytes = 50000;
21 21
22 } // namespace 22 } // namespace
23 23
24 namespace predictors { 24 namespace predictors {
25
26 ResourcePrefetcher::Request::Request(const GURL& i_resource_url)
27 : resource_url(i_resource_url),
28 prefetch_status(PREFETCH_STATUS_NOT_STARTED),
29 usage_status(USAGE_STATUS_NOT_REQUESTED) {
30 }
31
32 ResourcePrefetcher::Request::Request(const Request& other)
33 : resource_url(other.resource_url),
34 prefetch_status(other.prefetch_status),
35 usage_status(other.usage_status) {
36 }
37
38 ResourcePrefetcher::ResourcePrefetcher( 25 ResourcePrefetcher::ResourcePrefetcher(
39 Delegate* delegate, 26 Delegate* delegate,
40 const ResourcePrefetchPredictorConfig& config, 27 const ResourcePrefetchPredictorConfig& config,
41 const NavigationID& navigation_id, 28 const NavigationID& navigation_id,
42 PrefetchKeyType key_type, 29 PrefetchKeyType key_type,
43 std::unique_ptr<RequestVector> requests) 30 const std::vector<GURL>& urls)
44 : state_(INITIALIZED), 31 : state_(INITIALIZED),
45 delegate_(delegate), 32 delegate_(delegate),
46 config_(config), 33 config_(config),
47 navigation_id_(navigation_id), 34 navigation_id_(navigation_id),
48 key_type_(key_type), 35 key_type_(key_type) {
49 request_vector_(std::move(requests)) {
50 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 36 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
51 DCHECK(request_vector_.get());
52 37
53 std::copy(request_vector_->begin(), request_vector_->end(), 38 std::copy(urls.begin(), urls.end(), std::back_inserter(request_queue_));
54 std::back_inserter(request_queue_));
55 } 39 }
56 40
57 ResourcePrefetcher::~ResourcePrefetcher() {} 41 ResourcePrefetcher::~ResourcePrefetcher() {}
58 42
59 void ResourcePrefetcher::Start() { 43 void ResourcePrefetcher::Start() {
60 DCHECK(thread_checker_.CalledOnValidThread()); 44 DCHECK(thread_checker_.CalledOnValidThread());
61 45
62 CHECK_EQ(state_, INITIALIZED); 46 CHECK_EQ(state_, INITIALIZED);
63 state_ = RUNNING; 47 state_ = RUNNING;
64 48
(...skipping 16 matching lines...) Expand all
81 if (state_ == RUNNING) { 65 if (state_ == RUNNING) {
82 bool request_available = true; 66 bool request_available = true;
83 67
84 // Loop through the requests while we are under the 68 // Loop through the requests while we are under the
85 // max_prefetches_inflight_per_host_per_navigation limit, looking for a URL 69 // max_prefetches_inflight_per_host_per_navigation limit, looking for a URL
86 // for which the max_prefetches_inflight_per_host_per_navigation limit has 70 // for which the max_prefetches_inflight_per_host_per_navigation limit has
87 // not been reached. Try to launch as many requests as possible. 71 // not been reached. Try to launch as many requests as possible.
88 while ((inflight_requests_.size() < 72 while ((inflight_requests_.size() <
89 config_.max_prefetches_inflight_per_navigation) && 73 config_.max_prefetches_inflight_per_navigation) &&
90 request_available) { 74 request_available) {
91 std::list<Request*>::iterator request_it = request_queue_.begin(); 75 auto request_it = request_queue_.begin();
92 for (; request_it != request_queue_.end(); ++request_it) { 76 for (; request_it != request_queue_.end(); ++request_it) {
93 const std::string& host = (*request_it)->resource_url.host(); 77 const std::string& host = request_it->host();
94 78
95 std::map<std::string, size_t>::iterator host_it = 79 std::map<std::string, size_t>::iterator host_it =
96 host_inflight_counts_.find(host); 80 host_inflight_counts_.find(host);
97 if (host_it == host_inflight_counts_.end() || 81 if (host_it == host_inflight_counts_.end() ||
98 host_it->second < 82 host_it->second <
99 config_.max_prefetches_inflight_per_host_per_navigation) 83 config_.max_prefetches_inflight_per_host_per_navigation)
100 break; 84 break;
101 } 85 }
102 request_available = request_it != request_queue_.end(); 86 request_available = request_it != request_queue_.end();
103 87
104 if (request_available) { 88 if (request_available) {
105 SendRequest(*request_it); 89 SendRequest(*request_it);
106 request_queue_.erase(request_it); 90 request_queue_.erase(request_it);
107 } 91 }
108 } 92 }
109 } 93 }
110 94
111 // If the inflight_requests_ is empty, we can't launch any more. Finish. 95 // If the inflight_requests_ is empty, we can't launch any more. Finish.
112 if (inflight_requests_.empty()) { 96 if (inflight_requests_.empty()) {
113 CHECK(host_inflight_counts_.empty()); 97 CHECK(host_inflight_counts_.empty());
114 CHECK(request_queue_.empty() || state_ == STOPPED); 98 CHECK(request_queue_.empty() || state_ == STOPPED);
115 99
116 state_ = FINISHED; 100 state_ = FINISHED;
117 delegate_->ResourcePrefetcherFinished(this, request_vector_.release()); 101 delegate_->ResourcePrefetcherFinished(this);
118 } 102 }
119 } 103 }
120 104
121 void ResourcePrefetcher::SendRequest(Request* request) { 105 void ResourcePrefetcher::SendRequest(const GURL& url) {
122 request->prefetch_status = Request::PREFETCH_STATUS_STARTED; 106 std::unique_ptr<net::URLRequest> url_request =
123 107 delegate_->GetURLRequestContext()->CreateRequest(url, net::LOW, this);
124 std::unique_ptr<net::URLRequest> url_request_ptr = 108 host_inflight_counts_[url.host()] += 1;
125 delegate_->GetURLRequestContext()->CreateRequest(request->resource_url,
126 net::LOW, this);
127 net::URLRequest* url_request = url_request_ptr.get();
128
129 inflight_requests_[url_request] = {std::move(url_request_ptr), request};
130 host_inflight_counts_[url_request->original_url().host()] += 1;
131 109
132 url_request->set_method("GET"); 110 url_request->set_method("GET");
133 url_request->set_first_party_for_cookies(navigation_id_.main_frame_url); 111 url_request->set_first_party_for_cookies(navigation_id_.main_frame_url);
134 url_request->set_initiator(url::Origin(navigation_id_.main_frame_url)); 112 url_request->set_initiator(url::Origin(navigation_id_.main_frame_url));
135 url_request->SetReferrer(navigation_id_.main_frame_url.spec()); 113 url_request->SetReferrer(navigation_id_.main_frame_url.spec());
136 url_request->SetLoadFlags(url_request->load_flags() | net::LOAD_PREFETCH); 114 url_request->SetLoadFlags(url_request->load_flags() | net::LOAD_PREFETCH);
137 StartURLRequest(url_request); 115 StartURLRequest(url_request.get());
116 inflight_requests_.insert(
117 std::make_pair(url_request.get(), std::move(url_request)));
138 } 118 }
139 119
140 void ResourcePrefetcher::StartURLRequest(net::URLRequest* request) { 120 void ResourcePrefetcher::StartURLRequest(net::URLRequest* request) {
141 request->Start(); 121 request->Start();
142 } 122 }
143 123
144 void ResourcePrefetcher::FinishRequest(net::URLRequest* request, 124 void ResourcePrefetcher::FinishRequest(net::URLRequest* request) {
145 Request::PrefetchStatus status) {
146 auto request_it = inflight_requests_.find(request); 125 auto request_it = inflight_requests_.find(request);
147 CHECK(request_it != inflight_requests_.end()); 126 CHECK(request_it != inflight_requests_.end());
148 127
149 const std::string host = request->original_url().host(); 128 const std::string host = request->original_url().host();
150 std::map<std::string, size_t>::iterator host_it = host_inflight_counts_.find( 129 std::map<std::string, size_t>::iterator host_it = host_inflight_counts_.find(
151 host); 130 host);
152 CHECK_GT(host_it->second, 0U); 131 CHECK_GT(host_it->second, 0U);
153 host_it->second -= 1; 132 host_it->second -= 1;
154 if (host_it->second == 0) 133 if (host_it->second == 0)
155 host_inflight_counts_.erase(host); 134 host_inflight_counts_.erase(host);
156 135
157 request_it->second.second->prefetch_status = status;
158 inflight_requests_.erase(request_it); 136 inflight_requests_.erase(request_it);
159 137
160 TryToLaunchPrefetchRequests(); 138 TryToLaunchPrefetchRequests();
161 } 139 }
162 140
163 void ResourcePrefetcher::ReadFullResponse(net::URLRequest* request) { 141 void ResourcePrefetcher::ReadFullResponse(net::URLRequest* request) {
164 bool status = true; 142 bool status = true;
165 while (status) { 143 while (status) {
166 int bytes_read = 0; 144 int bytes_read = 0;
167 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer( 145 scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(
168 kResourceBufferSizeBytes)); 146 kResourceBufferSizeBytes));
169 status = request->Read(buffer.get(), kResourceBufferSizeBytes, &bytes_read); 147 status = request->Read(buffer.get(), kResourceBufferSizeBytes, &bytes_read);
170 148
171 if (status) { 149 if (status) {
172 status = ShouldContinueReadingRequest(request, bytes_read); 150 status = ShouldContinueReadingRequest(request, bytes_read);
173 } else if (!request->status().is_success()) { 151 } else if (!request->status().is_success()) {
174 FinishRequest(request, Request::PREFETCH_STATUS_FAILED); 152 FinishRequest(request);
175 return; 153 return;
176 } 154 }
177 } 155 }
178 } 156 }
179 157
180 bool ResourcePrefetcher::ShouldContinueReadingRequest(net::URLRequest* request, 158 bool ResourcePrefetcher::ShouldContinueReadingRequest(net::URLRequest* request,
181 int bytes_read) { 159 int bytes_read) {
182 if (bytes_read == 0) { // When bytes_read == 0, no more data. 160 if (bytes_read == 0) { // When bytes_read == 0, no more data.
183 if (request->was_cached()) 161 if (request->was_cached())
184 FinishRequest(request, Request::PREFETCH_STATUS_FROM_CACHE); 162 FinishRequest(request);
185 else 163 else
186 FinishRequest(request, Request::PREFETCH_STATUS_FROM_NETWORK); 164 FinishRequest(request);
187 return false; 165 return false;
188 } 166 }
189 167
190 return true; 168 return true;
191 } 169 }
192 170
193 void ResourcePrefetcher::OnReceivedRedirect( 171 void ResourcePrefetcher::OnReceivedRedirect(
194 net::URLRequest* request, 172 net::URLRequest* request,
195 const net::RedirectInfo& redirect_info, 173 const net::RedirectInfo& redirect_info,
196 bool* defer_redirect) { 174 bool* defer_redirect) {
197 FinishRequest(request, Request::PREFETCH_STATUS_REDIRECTED); 175 FinishRequest(request);
198 } 176 }
199 177
200 void ResourcePrefetcher::OnAuthRequired(net::URLRequest* request, 178 void ResourcePrefetcher::OnAuthRequired(net::URLRequest* request,
201 net::AuthChallengeInfo* auth_info) { 179 net::AuthChallengeInfo* auth_info) {
202 FinishRequest(request, Request::PREFETCH_STATUS_AUTH_REQUIRED); 180 FinishRequest(request);
203 } 181 }
204 182
205 void ResourcePrefetcher::OnCertificateRequested( 183 void ResourcePrefetcher::OnCertificateRequested(
206 net::URLRequest* request, 184 net::URLRequest* request,
207 net::SSLCertRequestInfo* cert_request_info) { 185 net::SSLCertRequestInfo* cert_request_info) {
208 FinishRequest(request, Request::PREFETCH_STATUS_CERT_REQUIRED); 186 FinishRequest(request);
209 } 187 }
210 188
211 void ResourcePrefetcher::OnSSLCertificateError(net::URLRequest* request, 189 void ResourcePrefetcher::OnSSLCertificateError(net::URLRequest* request,
212 const net::SSLInfo& ssl_info, 190 const net::SSLInfo& ssl_info,
213 bool fatal) { 191 bool fatal) {
214 FinishRequest(request, Request::PREFETCH_STATUS_CERT_ERROR); 192 FinishRequest(request);
215 } 193 }
216 194
217 void ResourcePrefetcher::OnResponseStarted(net::URLRequest* request) { 195 void ResourcePrefetcher::OnResponseStarted(net::URLRequest* request) {
218 if (!request->status().is_success()) {
219 FinishRequest(request, Request::PREFETCH_STATUS_FAILED);
220 return;
221 }
222
223 // TODO(shishir): Do not read cached entries, or ones that are not cacheable. 196 // TODO(shishir): Do not read cached entries, or ones that are not cacheable.
224 ReadFullResponse(request); 197 if (request->status().is_success())
198 ReadFullResponse(request);
199 else
200 FinishRequest(request);
225 } 201 }
226 202
227 void ResourcePrefetcher::OnReadCompleted(net::URLRequest* request, 203 void ResourcePrefetcher::OnReadCompleted(net::URLRequest* request,
228 int bytes_read) { 204 int bytes_read) {
229 if (!request->status().is_success()) { 205 if (!request->status().is_success()) {
230 FinishRequest(request, Request::PREFETCH_STATUS_FAILED); 206 FinishRequest(request);
231 return; 207 return;
232 } 208 }
233 209
234 if (ShouldContinueReadingRequest(request, bytes_read)) 210 if (ShouldContinueReadingRequest(request, bytes_read))
235 ReadFullResponse(request); 211 ReadFullResponse(request);
236 } 212 }
237 213
238 } // namespace predictors 214 } // namespace predictors
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698