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

Side by Side Diff: content/browser/loader/async_revalidation_driver.cc

Issue 1041993004: content::ResourceDispatcherHostImpl changes for stale-while-revalidate (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@s-w-r-yhirano-patch
Patch Set: Remove unnecessary copied comment. Created 5 years, 1 month 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
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/loader/async_revalidation_driver.h"
6
7 #include "base/location.h" // For FROM_HERE
kinuko 2015/11/19 07:00:28 nit: I see you added these comments per review fee
Adam Rice 2015/11/19 21:13:52 Done.
Bence 2015/11/20 13:18:35 I genuinely couldn't find what these headers were
Adam Rice 2015/11/20 13:23:51 Absolutely no problem. I follow the philosophy tha
8 #include "base/logging.h"
9 #include "base/metrics/user_metrics_action.h"
10 #include "base/single_thread_task_runner.h" // Gets a SingleThreadTaskRunner
11 #include "base/thread_task_runner_handle.h" // from ThreadTaskRunnerHandle.
kinuko 2015/11/19 07:00:28 These seem obvious from header names.
Adam Rice 2015/11/19 21:13:52 What's not obvious is that the SingleThreadTaskRun
Bence 2015/11/20 13:18:35 Ditto.
12 #include "base/time/time.h"
13 #include "content/public/browser/user_metrics.h"
14 #include "net/base/net_errors.h"
15 #include "net/cert/cert_status_flags.h"
16 #include "net/ssl/ssl_info.h"
17 #include "net/url_request/url_request_context.h"
18 #include "net/url_request/url_request_status.h"
19
20 namespace content {
21
22 namespace {
23 // This matches the maximum allocation size of AsyncResourceHandler.
24 const int kReadBufSize = 32 * 1024;
25 const int kReadTimeoutSeconds = 5 * 60;
kinuko 2015/11/19 08:38:34 How is this timeout value chosen?
Adam Rice 2015/11/19 21:13:52 I don't remember. The most likely place is kDefaul
26 }
27
28 // The use of base::Unretained() in the initialisation of read_timer_ is safe
29 // because base::Timer guarantees not to call the callback after being
30 // destroyed.
31 AsyncRevalidationDriver::AsyncRevalidationDriver(
32 scoped_ptr<net::URLRequest> request,
33 scoped_ptr<ResourceThrottle> throttle,
34 const base::Closure& completion_callback)
35 : read_timer_(FROM_HERE,
36 base::TimeDelta::FromSeconds(kReadTimeoutSeconds),
37 base::Bind(&AsyncRevalidationDriver::OnReadTimeout,
38 base::Unretained(this)),
39 false),
40 request_(request.Pass()),
41 throttle_(throttle.Pass()),
kinuko 2015/11/19 07:00:28 nit: you could now use std::move for these
Adam Rice 2015/11/19 21:13:52 Done.
42 completion_callback_(completion_callback),
43 weak_ptr_factory_(this) {
44 request_->set_delegate(this);
45 throttle_->set_controller(this);
46 }
47
48 AsyncRevalidationDriver::~AsyncRevalidationDriver() {
49 weak_ptr_factory_.InvalidateWeakPtrs();
50 // Run ResourceThrottle destructor before we tear-down the rest of our state
51 // as the ResourceThrottle may want to inspect the URLRequest and other state.
52 throttle_.reset();
53 }
54
55 void AsyncRevalidationDriver::StartRequest() {
56 RecordAction(base::UserMetricsAction("AsyncRevalidationCreated"));
57 // Give the handler a chance to delay the URLRequest from being started.
58 bool defer_start = false;
59 throttle_->WillStartRequest(&defer_start);
60
61 if (defer_start) {
62 RecordDefer();
63 } else {
64 StartRequestInternal();
65 }
66 }
67
68 void AsyncRevalidationDriver::CancelRequest() {
69 CancelRequestInternal(net::ERR_ABORTED);
70 }
71
72 void AsyncRevalidationDriver::OnReceivedRedirect(
73 net::URLRequest* unused,
74 const net::RedirectInfo& redirect_info,
75 bool* defer) {
76 DCHECK_EQ(request_.get(), unused);
77
78 // The async revalidation should not follow redirects, because caching is
79 // a property of an individual HTTP resource.
80 DVLOG(1) << "OnReceivedRedirect: " << request_->url().spec();
81 RecordAction(base::UserMetricsAction("AsyncRevalidationRedirected"));
82 CancelRequest();
83 }
84
85 void AsyncRevalidationDriver::OnAuthRequired(
86 net::URLRequest* unused,
87 net::AuthChallengeInfo* auth_info) {
88 DCHECK_EQ(request_.get(), unused);
89 // This error code doesn't have exactly the right semantics, but it should
90 // be sufficient to narrow down the problem in net logs.
91 request_->CancelWithError(net::ERR_ACCESS_DENIED);
kinuko 2015/11/19 07:00:28 Help me understand: for this case we don't need/wa
Adam Rice 2015/11/19 21:13:52 CancelRequest() would use ERR_ABORTED, which is ve
92 }
93
94 void AsyncRevalidationDriver::OnBeforeNetworkStart(net::URLRequest* unused,
95 bool* defer) {
96 DCHECK_EQ(request_.get(), unused);
97
98 // Verify that the ResourceScheduler does not defer here.
99 throttle_->WillStartUsingNetwork(defer);
100 DCHECK(!defer);
kinuko 2015/11/19 07:00:29 !*defer ?
Adam Rice 2015/11/19 21:13:52 Oh. The tests in https://codereview.chromium.org/1
101 }
102
103 void AsyncRevalidationDriver::OnResponseStarted(net::URLRequest* unused) {
104 DCHECK_EQ(request_.get(), unused);
105
106 DVLOG(1) << "OnResponseStarted: " << request_->url().spec();
107
108 if (!request_->status().is_success()) {
109 ResponseCompleted();
110 return;
111 }
112
113 const net::HttpResponseInfo& response_info = request_->response_info();
114 if (!response_info.response_time.is_null() && response_info.was_cached) {
115 // The cached entry was revalidated. No need to read it in.
116 ResponseCompleted();
117 return;
118 }
119
120 bool defer = false;
121 throttle_->WillProcessResponse(&defer);
122 DCHECK(!defer);
123
124 if (request_->status().is_success()) {
125 StartReading(false); // Read the first chunk.
126 } else {
127 ResponseCompleted();
128 }
129 }
130
131 void AsyncRevalidationDriver::OnReadCompleted(net::URLRequest* unused,
132 int bytes_read) {
133 DCHECK_EQ(request_.get(), unused);
134 DVLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\""
135 << " bytes_read = " << bytes_read;
136
137 // bytes_read == -1 always implies an error.
138 if (bytes_read == -1 || !request_->status().is_success()) {
139 ResponseCompleted();
140 return;
141 }
142
143 DCHECK_GE(bytes_read, 0);
144 DCHECK(request_->status().is_success());
145 DCHECK(!is_deferred_);
146
147 if (bytes_read > 0) {
148 StartReading(true); // Read the next chunk.
149 } else {
150 // URLRequest reported an EOF.
151 DCHECK_EQ(0, bytes_read);
kinuko 2015/11/19 07:00:28 nit: feels a bit verbose to me
Adam Rice 2015/11/19 21:13:52 I have made it less verbose. PTAL.
152 ResponseCompleted();
153 }
154 }
155
156 void AsyncRevalidationDriver::Resume() {
157 DCHECK(is_deferred_);
158 is_deferred_ = false;
159 StartRequestInternal();
160 }
161
162 void AsyncRevalidationDriver::Cancel() {
163 NOTREACHED();
164 }
165
166 void AsyncRevalidationDriver::CancelAndIgnore() {
167 NOTREACHED();
168 }
169
170 void AsyncRevalidationDriver::CancelWithError(int error_code) {
171 NOTREACHED();
172 }
173
174 void AsyncRevalidationDriver::StartRequestInternal() {
175 DCHECK(!request_->is_pending());
176
177 // This can happen if Resume() is called after CancelRequest().
178 // Since CancelRequest() will have called ResponseCompleted() asynchronously,
179 // it's not necessary to call it again.
180 if (!request_->status().is_success())
181 return;
182
183 request_->Start();
184 }
185
186 void AsyncRevalidationDriver::CancelRequestInternal(int error) {
187 DVLOG(1) << "CancelRequestInternal: " << request_->url().spec();
188
189 bool was_pending = request_->is_pending();
190
191 request_->CancelWithError(error);
192
193 if (!was_pending) {
194 // If the request isn't in flight, then we won't get an asynchronous
195 // notification from the request, so we have to signal ourselves to finish
196 // this request.
197 base::ThreadTaskRunnerHandle::Get()->PostTask(
198 FROM_HERE, base::Bind(&AsyncRevalidationDriver::ResponseCompleted,
199 weak_ptr_factory_.GetWeakPtr()));
200 }
201 }
202
203 void AsyncRevalidationDriver::CompleteResponseStarted() {
kinuko 2015/11/19 07:00:28 Where is this used?
Adam Rice 2015/11/19 21:13:52 It's not. Thank you for checking. I moved the impl
204 bool defer = false;
205 throttle_->WillProcessResponse(&defer);
206 DCHECK(!defer);
207 }
208
209 void AsyncRevalidationDriver::StartReading(bool is_continuation) {
210 int bytes_read = 0;
211 ReadMore(&bytes_read);
212
213 // If IO is pending, wait for the URLRequest to call OnReadCompleted.
214 if (request_->status().is_io_pending())
215 return;
216
217 if (!is_continuation || bytes_read <= 0) {
218 OnReadCompleted(request_.get(), bytes_read);
219 } else {
220 // Else, trigger OnReadCompleted asynchronously to avoid starving the IO
221 // thread in case the URLRequest can provide data synchronously.
222 base::ThreadTaskRunnerHandle::Get()->PostTask(
223 FROM_HERE,
224 base::Bind(&AsyncRevalidationDriver::OnReadCompleted,
225 weak_ptr_factory_.GetWeakPtr(), request_.get(), bytes_read));
226 }
227 }
228
229 void AsyncRevalidationDriver::ReadMore(int* bytes_read) {
230 DCHECK(!is_deferred_);
231
232 if (!read_buffer_)
233 read_buffer_ = new net::IOBuffer(kReadBufSize);
234
235 read_timer_.Reset();
236 request_->Read(read_buffer_.get(), kReadBufSize, bytes_read);
237
238 // No need to check the return value here as we'll detect errors by
239 // inspecting the URLRequest's status.
240 }
241
242 void AsyncRevalidationDriver::ResponseCompleted() {
243 DVLOG(1) << "ResponseCompleted: " << request_->url().spec();
244 // When this class cancels a redirect, URLRequest calls both the
245 // OnResponseStarted() and OnReadCompleted() callbacks. This class should not
246 // run |completion_callback_| twice.
247 //
248 // TODO(ricea): Work out why URLRequest calls both methods on cancellation and
249 // make it stop.
250 if (completion_callback_.is_null())
251 return;
252 base::Closure completion_callback(completion_callback_);
253 completion_callback_.Reset();
254 completion_callback.Run();
255 }
256
257 void AsyncRevalidationDriver::OnReadTimeout() {
258 RecordAction(base::UserMetricsAction("AsyncRevalidationTimeout"));
259 CancelRequestInternal(net::ERR_TIMED_OUT);
260 }
261
262 void AsyncRevalidationDriver::RecordDefer() {
263 request_->LogBlockedBy(throttle_->GetNameForLogging());
264 DCHECK(!is_deferred_);
265 is_deferred_ = true;
266 }
267
268 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698