blob: a0713ebaab780dfe98993fc50d26c4094e65ae71 [file] [log] [blame]
[email protected]56f0b082012-06-14 07:12:321// Copyright (c) 2012 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
[email protected]678c0362012-12-05 08:02:445#include "content/browser/loader/resource_loader.h"
[email protected]56f0b082012-06-14 07:12:326
[email protected]bbdd1b20b2012-12-11 21:24:137#include "base/command_line.h"
[email protected]95f861e2013-07-18 02:07:178#include "base/message_loop/message_loop.h"
[email protected]5e3183482013-08-09 11:05:199#include "base/metrics/histogram.h"
[email protected]a43858f2013-06-28 15:18:3710#include "base/time/time.h"
[email protected]db3678052014-04-01 16:08:0311#include "content/browser/appcache/appcache_interceptor.h"
[email protected]56f0b082012-06-14 07:12:3212#include "content/browser/child_process_security_policy_impl.h"
[email protected]fc6c1872013-10-03 01:22:3513#include "content/browser/loader/cross_site_resource_handler.h"
[email protected]146b8b22013-11-20 03:59:1814#include "content/browser/loader/detachable_resource_handler.h"
[email protected]678c0362012-12-05 08:02:4415#include "content/browser/loader/resource_loader_delegate.h"
16#include "content/browser/loader/resource_request_info_impl.h"
[email protected]6ee72da12014-07-22 04:39:1017#include "content/browser/service_worker/service_worker_request_handler.h"
[email protected]56f0b082012-06-14 07:12:3218#include "content/browser/ssl/ssl_client_auth_handler.h"
19#include "content/browser/ssl/ssl_manager.h"
20#include "content/common/ssl_status_serialization.h"
21#include "content/public/browser/cert_store.h"
[email protected]1ccb6992013-10-30 04:46:2022#include "content/public/browser/resource_context.h"
[email protected]56f0b082012-06-14 07:12:3223#include "content/public/browser/resource_dispatcher_host_login_delegate.h"
[email protected]0bbd63b2013-11-29 00:02:1224#include "content/public/browser/signed_certificate_timestamp_store.h"
[email protected]bbdd1b20b2012-12-11 21:24:1325#include "content/public/common/content_client.h"
26#include "content/public/common/content_switches.h"
[email protected]f3b357692013-03-22 05:16:1327#include "content/public/common/process_type.h"
[email protected]56f0b082012-06-14 07:12:3228#include "content/public/common/resource_response.h"
[email protected]fc6c1872013-10-03 01:22:3529#include "net/base/io_buffer.h"
[email protected]56f0b082012-06-14 07:12:3230#include "net/base/load_flags.h"
31#include "net/http/http_response_headers.h"
[email protected]536fd0b2013-03-14 17:41:5732#include "net/ssl/client_cert_store.h"
[email protected]cba24642014-08-15 20:49:5933#include "net/url_request/redirect_info.h"
[email protected]3ed84722013-11-01 17:17:0734#include "net/url_request/url_request_status.h"
[email protected]56f0b082012-06-14 07:12:3235
36using base::TimeDelta;
37using base::TimeTicks;
38
39namespace content {
40namespace {
41
[email protected]3821f7a2014-08-13 16:40:0842void PopulateResourceResponse(ResourceRequestInfoImpl* info,
43 net::URLRequest* request,
[email protected]56f0b082012-06-14 07:12:3244 ResourceResponse* response) {
[email protected]2756a8e2012-09-07 18:24:2945 response->head.error_code = request->status().error();
[email protected]8df905e22012-06-25 08:15:4246 response->head.request_time = request->request_time();
47 response->head.response_time = request->response_time();
48 response->head.headers = request->response_headers();
49 request->GetCharset(&response->head.charset);
50 response->head.content_length = request->GetExpectedContentSize();
51 request->GetMimeType(&response->head.mime_type);
[email protected]56f0b082012-06-14 07:12:3252 net::HttpResponseInfo response_info = request->response_info();
[email protected]8df905e22012-06-25 08:15:4253 response->head.was_fetched_via_spdy = response_info.was_fetched_via_spdy;
54 response->head.was_npn_negotiated = response_info.was_npn_negotiated;
55 response->head.npn_negotiated_protocol =
56 response_info.npn_negotiated_protocol;
[email protected]92a98df92013-06-06 02:47:4257 response->head.connection_info = response_info.connection_info;
[email protected]8df905e22012-06-25 08:15:4258 response->head.was_fetched_via_proxy = request->was_fetched_via_proxy();
59 response->head.socket_address = request->GetSocketAddress();
[email protected]6ee72da12014-07-22 04:39:1060 if (ServiceWorkerRequestHandler* handler =
61 ServiceWorkerRequestHandler::GetHandler(request)) {
62 handler->GetExtraResponseInfo(
63 &response->head.was_fetched_via_service_worker,
64 &response->head.original_url_via_service_worker);
65 }
[email protected]db3678052014-04-01 16:08:0366 AppCacheInterceptor::GetExtraResponseInfo(
[email protected]56f0b082012-06-14 07:12:3267 request,
[email protected]8df905e22012-06-25 08:15:4268 &response->head.appcache_id,
69 &response->head.appcache_manifest_url);
[email protected]3821f7a2014-08-13 16:40:0870 if (info->is_load_timing_enabled())
[email protected]acca91d2013-06-04 13:51:2071 request->GetLoadTimingInfo(&response->head.load_timing);
[email protected]56f0b082012-06-14 07:12:3272}
73
74} // namespace
75
76ResourceLoader::ResourceLoader(scoped_ptr<net::URLRequest> request,
77 scoped_ptr<ResourceHandler> handler,
78 ResourceLoaderDelegate* delegate)
[email protected]1ccb6992013-10-30 04:46:2079 : deferred_stage_(DEFERRED_NONE),
80 request_(request.Pass()),
81 handler_(handler.Pass()),
82 delegate_(delegate),
83 last_upload_position_(0),
84 waiting_for_upload_progress_ack_(false),
85 is_transferring_(false),
86 weak_ptr_factory_(this) {
87 request_->set_delegate(this);
88 handler_->SetController(this);
[email protected]56f0b082012-06-14 07:12:3289}
90
91ResourceLoader::~ResourceLoader() {
[email protected]fc72bb12013-06-02 21:13:4692 if (login_delegate_.get())
[email protected]56f0b082012-06-14 07:12:3293 login_delegate_->OnRequestCancelled();
[email protected]fc72bb12013-06-02 21:13:4694 if (ssl_client_auth_handler_.get())
[email protected]56f0b082012-06-14 07:12:3295 ssl_client_auth_handler_->OnRequestCancelled();
96
97 // Run ResourceHandler destructor before we tear-down the rest of our state
98 // as the ResourceHandler may want to inspect the URLRequest and other state.
99 handler_.reset();
100}
101
102void ResourceLoader::StartRequest() {
103 if (delegate_->HandleExternalProtocol(this, request_->url())) {
[email protected]2756a8e2012-09-07 18:24:29104 CancelAndIgnore();
[email protected]56f0b082012-06-14 07:12:32105 return;
106 }
107
108 // Give the handler a chance to delay the URLRequest from being started.
109 bool defer_start = false;
[email protected]d22e800e2014-05-28 21:55:57110 if (!handler_->OnWillStart(request_->url(), &defer_start)) {
[email protected]56f0b082012-06-14 07:12:32111 Cancel();
112 return;
113 }
114
115 if (defer_start) {
116 deferred_stage_ = DEFERRED_START;
117 } else {
118 StartRequestInternal();
119 }
120}
121
122void ResourceLoader::CancelRequest(bool from_renderer) {
123 CancelRequestInternal(net::ERR_ABORTED, from_renderer);
124}
125
[email protected]2756a8e2012-09-07 18:24:29126void ResourceLoader::CancelAndIgnore() {
127 ResourceRequestInfoImpl* info = GetRequestInfo();
128 info->set_was_ignored_by_handler(true);
129 CancelRequest(false);
130}
131
[email protected]af3d4962012-10-19 10:57:26132void ResourceLoader::CancelWithError(int error_code) {
133 CancelRequestInternal(error_code, false);
134}
135
[email protected]56f0b082012-06-14 07:12:32136void ResourceLoader::ReportUploadProgress() {
[email protected]56f0b082012-06-14 07:12:32137 if (waiting_for_upload_progress_ack_)
138 return; // Send one progress event at a time.
139
[email protected]7335ab02012-08-30 22:30:42140 net::UploadProgress progress = request_->GetUploadProgress();
141 if (!progress.size())
[email protected]56f0b082012-06-14 07:12:32142 return; // Nothing to upload.
143
[email protected]7335ab02012-08-30 22:30:42144 if (progress.position() == last_upload_position_)
[email protected]56f0b082012-06-14 07:12:32145 return; // No progress made since last time.
146
147 const uint64 kHalfPercentIncrements = 200;
148 const TimeDelta kOneSecond = TimeDelta::FromMilliseconds(1000);
149
[email protected]7335ab02012-08-30 22:30:42150 uint64 amt_since_last = progress.position() - last_upload_position_;
[email protected]56f0b082012-06-14 07:12:32151 TimeDelta time_since_last = TimeTicks::Now() - last_upload_ticks_;
152
[email protected]7335ab02012-08-30 22:30:42153 bool is_finished = (progress.size() == progress.position());
154 bool enough_new_progress =
155 (amt_since_last > (progress.size() / kHalfPercentIncrements));
[email protected]56f0b082012-06-14 07:12:32156 bool too_much_time_passed = time_since_last > kOneSecond;
157
158 if (is_finished || enough_new_progress || too_much_time_passed) {
159 if (request_->load_flags() & net::LOAD_ENABLE_UPLOAD_PROGRESS) {
[email protected]d22e800e2014-05-28 21:55:57160 handler_->OnUploadProgress(progress.position(), progress.size());
[email protected]56f0b082012-06-14 07:12:32161 waiting_for_upload_progress_ack_ = true;
162 }
163 last_upload_ticks_ = TimeTicks::Now();
[email protected]7335ab02012-08-30 22:30:42164 last_upload_position_ = progress.position();
[email protected]56f0b082012-06-14 07:12:32165 }
166}
167
[email protected]f820d9c52013-12-18 18:42:36168void ResourceLoader::MarkAsTransferring() {
[email protected]6c1e05212014-07-31 00:59:40169 CHECK(IsResourceTypeFrame(GetRequestInfo()->GetResourceType()))
[email protected]46c704762013-12-18 18:10:24170 << "Can only transfer for navigations";
[email protected]56f0b082012-06-14 07:12:32171 is_transferring_ = true;
[email protected]56f0b082012-06-14 07:12:32172}
173
[email protected]1f291cd2013-09-25 22:05:14174void ResourceLoader::CompleteTransfer() {
[email protected]17b674e02014-05-10 04:30:02175 // Although CrossSiteResourceHandler defers at OnResponseStarted
176 // (DEFERRED_READ), it may be seeing a replay of events via
177 // BufferedResourceHandler, and so the request itself is actually deferred at
178 // a later read stage.
179 DCHECK(DEFERRED_READ == deferred_stage_ ||
180 DEFERRED_RESPONSE_COMPLETE == deferred_stage_);
[email protected]56f0b082012-06-14 07:12:32181
[email protected]56f0b082012-06-14 07:12:32182 is_transferring_ = false;
[email protected]fc6c1872013-10-03 01:22:35183 GetRequestInfo()->cross_site_handler()->ResumeResponse();
[email protected]56f0b082012-06-14 07:12:32184}
185
186ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() {
187 return ResourceRequestInfoImpl::ForRequest(request_.get());
188}
189
190void ResourceLoader::ClearLoginDelegate() {
191 login_delegate_ = NULL;
192}
193
194void ResourceLoader::ClearSSLClientAuthHandler() {
195 ssl_client_auth_handler_ = NULL;
196}
197
198void ResourceLoader::OnUploadProgressACK() {
199 waiting_for_upload_progress_ack_ = false;
200}
201
[email protected]56f0b082012-06-14 07:12:32202void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused,
[email protected]cba24642014-08-15 20:49:59203 const net::RedirectInfo& redirect_info,
[email protected]56f0b082012-06-14 07:12:32204 bool* defer) {
205 DCHECK_EQ(request_.get(), unused);
206
207 VLOG(1) << "OnReceivedRedirect: " << request_->url().spec();
208 DCHECK(request_->status().is_success());
209
210 ResourceRequestInfoImpl* info = GetRequestInfo();
211
[email protected]2d09a702014-01-19 23:41:24212 if (info->GetProcessType() != PROCESS_TYPE_PLUGIN &&
[email protected]56f0b082012-06-14 07:12:32213 !ChildProcessSecurityPolicyImpl::GetInstance()->
[email protected]cba24642014-08-15 20:49:59214 CanRequestURL(info->GetChildID(), redirect_info.new_url)) {
[email protected]56f0b082012-06-14 07:12:32215 VLOG(1) << "Denied unauthorized request for "
[email protected]cba24642014-08-15 20:49:59216 << redirect_info.new_url.possibly_invalid_spec();
[email protected]56f0b082012-06-14 07:12:32217
218 // Tell the renderer that this request was disallowed.
219 Cancel();
220 return;
221 }
222
[email protected]cba24642014-08-15 20:49:59223 delegate_->DidReceiveRedirect(this, redirect_info.new_url);
[email protected]56f0b082012-06-14 07:12:32224
[email protected]cba24642014-08-15 20:49:59225 if (delegate_->HandleExternalProtocol(this, redirect_info.new_url)) {
[email protected]56f0b082012-06-14 07:12:32226 // The request is complete so we can remove it.
[email protected]2756a8e2012-09-07 18:24:29227 CancelAndIgnore();
[email protected]56f0b082012-06-14 07:12:32228 return;
229 }
230
231 scoped_refptr<ResourceResponse> response(new ResourceResponse());
[email protected]3821f7a2014-08-13 16:40:08232 PopulateResourceResponse(info, request_.get(), response.get());
[email protected]56f0b082012-06-14 07:12:32233
[email protected]cba24642014-08-15 20:49:59234 if (!handler_->OnRequestRedirected(redirect_info, response.get(), defer)) {
[email protected]56f0b082012-06-14 07:12:32235 Cancel();
[email protected]926360f2012-06-29 04:45:02236 } else if (*defer) {
237 deferred_stage_ = DEFERRED_REDIRECT; // Follow redirect when resumed.
[email protected]56f0b082012-06-14 07:12:32238 }
[email protected]56f0b082012-06-14 07:12:32239}
240
241void ResourceLoader::OnAuthRequired(net::URLRequest* unused,
242 net::AuthChallengeInfo* auth_info) {
243 DCHECK_EQ(request_.get(), unused);
244
245 if (request_->load_flags() & net::LOAD_DO_NOT_PROMPT_FOR_LOGIN) {
246 request_->CancelAuth();
247 return;
248 }
249
[email protected]56f0b082012-06-14 07:12:32250 // Create a login dialog on the UI thread to get authentication data, or pull
251 // from cache and continue on the IO thread.
252
[email protected]fc72bb12013-06-02 21:13:46253 DCHECK(!login_delegate_.get())
254 << "OnAuthRequired called with login_delegate pending";
[email protected]56f0b082012-06-14 07:12:32255 login_delegate_ = delegate_->CreateLoginDelegate(this, auth_info);
[email protected]fc72bb12013-06-02 21:13:46256 if (!login_delegate_.get())
[email protected]56f0b082012-06-14 07:12:32257 request_->CancelAuth();
258}
259
260void ResourceLoader::OnCertificateRequested(
261 net::URLRequest* unused,
262 net::SSLCertRequestInfo* cert_info) {
263 DCHECK_EQ(request_.get(), unused);
264
[email protected]294084d2014-01-06 22:22:02265 if (request_->load_flags() & net::LOAD_PREFETCH) {
[email protected]56f0b082012-06-14 07:12:32266 request_->Cancel();
267 return;
268 }
269
[email protected]fc72bb12013-06-02 21:13:46270 DCHECK(!ssl_client_auth_handler_.get())
271 << "OnCertificateRequested called with ssl_client_auth_handler pending";
[email protected]1ccb6992013-10-30 04:46:20272 ssl_client_auth_handler_ = new SSLClientAuthHandler(
273 GetRequestInfo()->GetContext()->CreateClientCertStore(),
274 request_.get(),
275 cert_info);
[email protected]56f0b082012-06-14 07:12:32276 ssl_client_auth_handler_->SelectCertificate();
277}
278
279void ResourceLoader::OnSSLCertificateError(net::URLRequest* request,
280 const net::SSLInfo& ssl_info,
281 bool fatal) {
282 ResourceRequestInfoImpl* info = GetRequestInfo();
283
284 int render_process_id;
[email protected]1a4e9752013-12-31 20:10:58285 int render_frame_id;
286 if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id))
[email protected]56f0b082012-06-14 07:12:32287 NOTREACHED();
288
289 SSLManager::OnSSLCertificateError(
[email protected]5c1d3e52012-08-01 05:14:27290 weak_ptr_factory_.GetWeakPtr(),
[email protected]56f0b082012-06-14 07:12:32291 info->GetGlobalRequestID(),
292 info->GetResourceType(),
293 request_->url(),
294 render_process_id,
[email protected]1a4e9752013-12-31 20:10:58295 render_frame_id,
[email protected]56f0b082012-06-14 07:12:32296 ssl_info,
297 fatal);
298}
299
[email protected]5584eab2014-01-09 22:16:15300void ResourceLoader::OnBeforeNetworkStart(net::URLRequest* unused,
301 bool* defer) {
302 DCHECK_EQ(request_.get(), unused);
303
304 // Give the handler a chance to delay the URLRequest from using the network.
[email protected]d22e800e2014-05-28 21:55:57305 if (!handler_->OnBeforeNetworkStart(request_->url(), defer)) {
[email protected]5584eab2014-01-09 22:16:15306 Cancel();
307 return;
308 } else if (*defer) {
309 deferred_stage_ = DEFERRED_NETWORK_START;
310 }
311}
312
[email protected]56f0b082012-06-14 07:12:32313void ResourceLoader::OnResponseStarted(net::URLRequest* unused) {
314 DCHECK_EQ(request_.get(), unused);
315
316 VLOG(1) << "OnResponseStarted: " << request_->url().spec();
317
[email protected]bbdd1b20b2012-12-11 21:24:13318 // The CanLoadPage check should take place after any server redirects have
319 // finished, at the point in time that we know a page will commit in the
320 // renderer process.
321 ResourceRequestInfoImpl* info = GetRequestInfo();
322 ChildProcessSecurityPolicyImpl* policy =
323 ChildProcessSecurityPolicyImpl::GetInstance();
324 if (!policy->CanLoadPage(info->GetChildID(),
325 request_->url(),
326 info->GetResourceType())) {
327 Cancel();
328 return;
329 }
330
[email protected]926360f2012-06-29 04:45:02331 if (!request_->status().is_success()) {
332 ResponseCompleted();
333 return;
334 }
335
336 // We want to send a final upload progress message prior to sending the
337 // response complete message even if we're waiting for an ack to to a
338 // previous upload progress message.
339 waiting_for_upload_progress_ack_ = false;
340 ReportUploadProgress();
341
342 CompleteResponseStarted();
343
344 if (is_deferred())
345 return;
346
[email protected]56f0b082012-06-14 07:12:32347 if (request_->status().is_success()) {
[email protected]926360f2012-06-29 04:45:02348 StartReading(false); // Read the first chunk.
[email protected]56f0b082012-06-14 07:12:32349 } else {
350 ResponseCompleted();
351 }
352}
353
354void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) {
355 DCHECK_EQ(request_.get(), unused);
356 VLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\""
357 << " bytes_read = " << bytes_read;
358
[email protected]926360f2012-06-29 04:45:02359 // bytes_read == -1 always implies an error.
360 if (bytes_read == -1 || !request_->status().is_success()) {
[email protected]56f0b082012-06-14 07:12:32361 ResponseCompleted();
362 return;
363 }
364
[email protected]218d9d372014-04-16 18:34:55365 CompleteRead(bytes_read);
366
[email protected]d1222a62014-04-14 20:27:32367 // If the handler cancelled or deferred the request, do not continue
368 // processing the read. If cancelled, the URLRequest has already been
369 // cancelled and will schedule an erroring OnReadCompleted later. If deferred,
370 // do nothing until resumed.
371 //
372 // Note: if bytes_read is 0 (EOF) and the handler defers, resumption will call
[email protected]17b674e02014-05-10 04:30:02373 // ResponseCompleted().
[email protected]218d9d372014-04-16 18:34:55374 if (is_deferred() || !request_->status().is_success())
[email protected]56f0b082012-06-14 07:12:32375 return;
[email protected]56f0b082012-06-14 07:12:32376
[email protected]d1222a62014-04-14 20:27:32377 if (bytes_read > 0) {
[email protected]926360f2012-06-29 04:45:02378 StartReading(true); // Read the next chunk.
379 } else {
[email protected]d1222a62014-04-14 20:27:32380 // URLRequest reported an EOF. Call ResponseCompleted.
381 DCHECK_EQ(0, bytes_read);
[email protected]56f0b082012-06-14 07:12:32382 ResponseCompleted();
[email protected]926360f2012-06-29 04:45:02383 }
[email protected]56f0b082012-06-14 07:12:32384}
385
386void ResourceLoader::CancelSSLRequest(const GlobalRequestID& id,
387 int error,
388 const net::SSLInfo* ssl_info) {
389 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
390
391 // The request can be NULL if it was cancelled by the renderer (as the
392 // request of the user navigating to a new page from the location bar).
393 if (!request_->is_pending())
394 return;
395 DVLOG(1) << "CancelSSLRequest() url: " << request_->url().spec();
396
397 if (ssl_info) {
398 request_->CancelWithSSLError(error, *ssl_info);
399 } else {
400 request_->CancelWithError(error);
401 }
402}
403
404void ResourceLoader::ContinueSSLRequest(const GlobalRequestID& id) {
405 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
406
407 DVLOG(1) << "ContinueSSLRequest() url: " << request_->url().spec();
408
409 request_->ContinueDespiteLastError();
410}
411
412void ResourceLoader::Resume() {
413 DCHECK(!is_transferring_);
414
415 DeferredStage stage = deferred_stage_;
416 deferred_stage_ = DEFERRED_NONE;
417 switch (stage) {
418 case DEFERRED_NONE:
419 NOTREACHED();
420 break;
421 case DEFERRED_START:
422 StartRequestInternal();
423 break;
[email protected]5584eab2014-01-09 22:16:15424 case DEFERRED_NETWORK_START:
425 request_->ResumeNetworkStart();
426 break;
[email protected]56f0b082012-06-14 07:12:32427 case DEFERRED_REDIRECT:
428 request_->FollowDeferredRedirect();
429 break;
[email protected]56f0b082012-06-14 07:12:32430 case DEFERRED_READ:
[email protected]dd32b1272013-05-04 14:17:11431 base::MessageLoop::current()->PostTask(
[email protected]926360f2012-06-29 04:45:02432 FROM_HERE,
[email protected]5c1d3e52012-08-01 05:14:27433 base::Bind(&ResourceLoader::ResumeReading,
434 weak_ptr_factory_.GetWeakPtr()));
[email protected]56f0b082012-06-14 07:12:32435 break;
[email protected]17b674e02014-05-10 04:30:02436 case DEFERRED_RESPONSE_COMPLETE:
437 base::MessageLoop::current()->PostTask(
438 FROM_HERE,
439 base::Bind(&ResourceLoader::ResponseCompleted,
440 weak_ptr_factory_.GetWeakPtr()));
441 break;
[email protected]56f0b082012-06-14 07:12:32442 case DEFERRED_FINISH:
443 // Delay self-destruction since we don't know how we were reached.
[email protected]dd32b1272013-05-04 14:17:11444 base::MessageLoop::current()->PostTask(
[email protected]56f0b082012-06-14 07:12:32445 FROM_HERE,
[email protected]5c1d3e52012-08-01 05:14:27446 base::Bind(&ResourceLoader::CallDidFinishLoading,
447 weak_ptr_factory_.GetWeakPtr()));
[email protected]56f0b082012-06-14 07:12:32448 break;
449 }
450}
451
452void ResourceLoader::Cancel() {
453 CancelRequest(false);
454}
455
456void ResourceLoader::StartRequestInternal() {
457 DCHECK(!request_->is_pending());
[email protected]4c4092112014-02-26 23:29:12458
459 if (!request_->status().is_success()) {
460 return;
461 }
462
[email protected]56f0b082012-06-14 07:12:32463 request_->Start();
464
465 delegate_->DidStartRequest(this);
466}
467
468void ResourceLoader::CancelRequestInternal(int error, bool from_renderer) {
469 VLOG(1) << "CancelRequestInternal: " << request_->url().spec();
470
471 ResourceRequestInfoImpl* info = GetRequestInfo();
472
473 // WebKit will send us a cancel for downloads since it no longer handles
474 // them. In this case, ignore the cancel since we handle downloads in the
475 // browser.
[email protected]70983822013-11-27 14:33:59476 if (from_renderer && (info->IsDownload() || info->is_stream()))
[email protected]56f0b082012-06-14 07:12:32477 return;
478
[email protected]146b8b22013-11-20 03:59:18479 if (from_renderer && info->detachable_handler()) {
480 // TODO(davidben): Fix Blink handling of prefetches so they are not
481 // cancelled on navigate away and end up in the local cache.
482 info->detachable_handler()->Detach();
483 return;
484 }
485
[email protected]926360f2012-06-29 04:45:02486 // TODO(darin): Perhaps we should really be looking to see if the status is
487 // IO_PENDING?
[email protected]56f0b082012-06-14 07:12:32488 bool was_pending = request_->is_pending();
489
[email protected]fc72bb12013-06-02 21:13:46490 if (login_delegate_.get()) {
[email protected]56f0b082012-06-14 07:12:32491 login_delegate_->OnRequestCancelled();
492 login_delegate_ = NULL;
493 }
[email protected]fc72bb12013-06-02 21:13:46494 if (ssl_client_auth_handler_.get()) {
[email protected]56f0b082012-06-14 07:12:32495 ssl_client_auth_handler_->OnRequestCancelled();
496 ssl_client_auth_handler_ = NULL;
497 }
498
499 request_->CancelWithError(error);
500
501 if (!was_pending) {
502 // If the request isn't in flight, then we won't get an asynchronous
503 // notification from the request, so we have to signal ourselves to finish
504 // this request.
[email protected]dd32b1272013-05-04 14:17:11505 base::MessageLoop::current()->PostTask(
506 FROM_HERE,
507 base::Bind(&ResourceLoader::ResponseCompleted,
508 weak_ptr_factory_.GetWeakPtr()));
[email protected]56f0b082012-06-14 07:12:32509 }
510}
511
[email protected]0bbd63b2013-11-29 00:02:12512void ResourceLoader::StoreSignedCertificateTimestamps(
513 const net::SignedCertificateTimestampAndStatusList& sct_list,
514 int process_id,
515 SignedCertificateTimestampIDStatusList* sct_ids) {
516 SignedCertificateTimestampStore* sct_store(
517 SignedCertificateTimestampStore::GetInstance());
518
519 for (net::SignedCertificateTimestampAndStatusList::const_iterator iter =
520 sct_list.begin(); iter != sct_list.end(); ++iter) {
[email protected]b34f5962014-01-08 12:37:08521 const int sct_id(sct_store->Store(iter->sct, process_id));
[email protected]0bbd63b2013-11-29 00:02:12522 sct_ids->push_back(
[email protected]b34f5962014-01-08 12:37:08523 SignedCertificateTimestampIDAndStatus(sct_id, iter->status));
[email protected]0bbd63b2013-11-29 00:02:12524 }
525}
526
[email protected]926360f2012-06-29 04:45:02527void ResourceLoader::CompleteResponseStarted() {
[email protected]56f0b082012-06-14 07:12:32528 ResourceRequestInfoImpl* info = GetRequestInfo();
529
530 scoped_refptr<ResourceResponse> response(new ResourceResponse());
[email protected]3821f7a2014-08-13 16:40:08531 PopulateResourceResponse(info, request_.get(), response.get());
[email protected]56f0b082012-06-14 07:12:32532
[email protected]fc72bb12013-06-02 21:13:46533 if (request_->ssl_info().cert.get()) {
534 int cert_id = CertStore::GetInstance()->StoreCert(
535 request_->ssl_info().cert.get(), info->GetChildID());
[email protected]0bbd63b2013-11-29 00:02:12536
537 SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
538 StoreSignedCertificateTimestamps(
539 request_->ssl_info().signed_certificate_timestamps,
540 info->GetChildID(),
541 &signed_certificate_timestamp_ids);
542
[email protected]8df905e22012-06-25 08:15:42543 response->head.security_info = SerializeSecurityInfo(
[email protected]56f0b082012-06-14 07:12:32544 cert_id,
545 request_->ssl_info().cert_status,
546 request_->ssl_info().security_bits,
[email protected]0bbd63b2013-11-29 00:02:12547 request_->ssl_info().connection_status,
548 signed_certificate_timestamp_ids);
[email protected]56f0b082012-06-14 07:12:32549 } else {
550 // We should not have any SSL state.
551 DCHECK(!request_->ssl_info().cert_status &&
552 request_->ssl_info().security_bits == -1 &&
553 !request_->ssl_info().connection_status);
554 }
555
556 delegate_->DidReceiveResponse(this);
[email protected]56f0b082012-06-14 07:12:32557
558 bool defer = false;
[email protected]d22e800e2014-05-28 21:55:57559 if (!handler_->OnResponseStarted(response.get(), &defer)) {
[email protected]926360f2012-06-29 04:45:02560 Cancel();
561 } else if (defer) {
[email protected]5e3183482013-08-09 11:05:19562 read_deferral_start_time_ = base::TimeTicks::Now();
[email protected]926360f2012-06-29 04:45:02563 deferred_stage_ = DEFERRED_READ; // Read first chunk when resumed.
[email protected]56f0b082012-06-14 07:12:32564 }
[email protected]56f0b082012-06-14 07:12:32565}
566
[email protected]926360f2012-06-29 04:45:02567void ResourceLoader::StartReading(bool is_continuation) {
[email protected]56f0b082012-06-14 07:12:32568 int bytes_read = 0;
[email protected]926360f2012-06-29 04:45:02569 ReadMore(&bytes_read);
570
571 // If IO is pending, wait for the URLRequest to call OnReadCompleted.
572 if (request_->status().is_io_pending())
573 return;
574
575 if (!is_continuation || bytes_read <= 0) {
[email protected]56f0b082012-06-14 07:12:32576 OnReadCompleted(request_.get(), bytes_read);
[email protected]926360f2012-06-29 04:45:02577 } else {
578 // Else, trigger OnReadCompleted asynchronously to avoid starving the IO
579 // thread in case the URLRequest can provide data synchronously.
[email protected]dd32b1272013-05-04 14:17:11580 base::MessageLoop::current()->PostTask(
[email protected]926360f2012-06-29 04:45:02581 FROM_HERE,
[email protected]5c1d3e52012-08-01 05:14:27582 base::Bind(&ResourceLoader::OnReadCompleted,
583 weak_ptr_factory_.GetWeakPtr(),
[email protected]dd32b1272013-05-04 14:17:11584 request_.get(),
585 bytes_read));
[email protected]926360f2012-06-29 04:45:02586 }
587}
588
589void ResourceLoader::ResumeReading() {
590 DCHECK(!is_deferred());
591
[email protected]5e3183482013-08-09 11:05:19592 if (!read_deferral_start_time_.is_null()) {
593 UMA_HISTOGRAM_TIMES("Net.ResourceLoader.ReadDeferral",
594 base::TimeTicks::Now() - read_deferral_start_time_);
595 read_deferral_start_time_ = base::TimeTicks();
596 }
[email protected]926360f2012-06-29 04:45:02597 if (request_->status().is_success()) {
598 StartReading(false); // Read the next chunk (OK to complete synchronously).
599 } else {
[email protected]56f0b082012-06-14 07:12:32600 ResponseCompleted();
601 }
602}
603
[email protected]926360f2012-06-29 04:45:02604void ResourceLoader::ReadMore(int* bytes_read) {
[email protected]926360f2012-06-29 04:45:02605 DCHECK(!is_deferred());
[email protected]56f0b082012-06-14 07:12:32606
[email protected]ef5306e2013-10-15 19:38:18607 // Make sure we track the buffer in at least one place. This ensures it gets
608 // deleted even in the case the request has already finished its job and
609 // doesn't use the buffer.
610 scoped_refptr<net::IOBuffer> buf;
[email protected]56f0b082012-06-14 07:12:32611 int buf_size;
[email protected]d22e800e2014-05-28 21:55:57612 if (!handler_->OnWillRead(&buf, &buf_size, -1)) {
[email protected]926360f2012-06-29 04:45:02613 Cancel();
614 return;
615 }
[email protected]56f0b082012-06-14 07:12:32616
617 DCHECK(buf);
618 DCHECK(buf_size > 0);
619
[email protected]ef5306e2013-10-15 19:38:18620 request_->Read(buf.get(), buf_size, bytes_read);
[email protected]926360f2012-06-29 04:45:02621
622 // No need to check the return value here as we'll detect errors by
623 // inspecting the URLRequest's status.
[email protected]56f0b082012-06-14 07:12:32624}
625
[email protected]218d9d372014-04-16 18:34:55626void ResourceLoader::CompleteRead(int bytes_read) {
[email protected]926360f2012-06-29 04:45:02627 DCHECK(bytes_read >= 0);
628 DCHECK(request_->status().is_success());
[email protected]56f0b082012-06-14 07:12:32629
[email protected]56f0b082012-06-14 07:12:32630 bool defer = false;
[email protected]d22e800e2014-05-28 21:55:57631 if (!handler_->OnReadCompleted(bytes_read, &defer)) {
[email protected]56f0b082012-06-14 07:12:32632 Cancel();
[email protected]926360f2012-06-29 04:45:02633 } else if (defer) {
[email protected]17b674e02014-05-10 04:30:02634 deferred_stage_ =
635 bytes_read > 0 ? DEFERRED_READ : DEFERRED_RESPONSE_COMPLETE;
[email protected]56f0b082012-06-14 07:12:32636 }
[email protected]218d9d372014-04-16 18:34:55637
638 // Note: the request may still have been cancelled while OnReadCompleted
639 // returns true if OnReadCompleted caused request to get cancelled
640 // out-of-band. (In AwResourceDispatcherHostDelegate::DownloadStarting, for
641 // instance.)
[email protected]56f0b082012-06-14 07:12:32642}
643
644void ResourceLoader::ResponseCompleted() {
645 VLOG(1) << "ResponseCompleted: " << request_->url().spec();
[email protected]3ed84722013-11-01 17:17:07646 RecordHistograms();
[email protected]56f0b082012-06-14 07:12:32647 ResourceRequestInfoImpl* info = GetRequestInfo();
648
649 std::string security_info;
650 const net::SSLInfo& ssl_info = request_->ssl_info();
[email protected]fc72bb12013-06-02 21:13:46651 if (ssl_info.cert.get() != NULL) {
652 int cert_id = CertStore::GetInstance()->StoreCert(ssl_info.cert.get(),
[email protected]56f0b082012-06-14 07:12:32653 info->GetChildID());
[email protected]0bbd63b2013-11-29 00:02:12654 SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
655 StoreSignedCertificateTimestamps(ssl_info.signed_certificate_timestamps,
656 info->GetChildID(),
657 &signed_certificate_timestamp_ids);
658
[email protected]56f0b082012-06-14 07:12:32659 security_info = SerializeSecurityInfo(
660 cert_id, ssl_info.cert_status, ssl_info.security_bits,
[email protected]0bbd63b2013-11-29 00:02:12661 ssl_info.connection_status, signed_certificate_timestamp_ids);
[email protected]56f0b082012-06-14 07:12:32662 }
663
[email protected]3780874a2013-11-18 05:49:03664 bool defer = false;
[email protected]d22e800e2014-05-28 21:55:57665 handler_->OnResponseCompleted(request_->status(), security_info, &defer);
[email protected]3780874a2013-11-18 05:49:03666 if (defer) {
[email protected]56f0b082012-06-14 07:12:32667 // The handler is not ready to die yet. We will call DidFinishLoading when
668 // we resume.
669 deferred_stage_ = DEFERRED_FINISH;
[email protected]3780874a2013-11-18 05:49:03670 } else {
671 // This will result in our destruction.
672 CallDidFinishLoading();
[email protected]56f0b082012-06-14 07:12:32673 }
674}
675
[email protected]56f0b082012-06-14 07:12:32676void ResourceLoader::CallDidFinishLoading() {
677 delegate_->DidFinishLoading(this);
678}
679
[email protected]3ed84722013-11-01 17:17:07680void ResourceLoader::RecordHistograms() {
681 ResourceRequestInfoImpl* info = GetRequestInfo();
682
[email protected]6c1e05212014-07-31 00:59:40683 if (info->GetResourceType() == RESOURCE_TYPE_PREFETCH) {
[email protected]3ed84722013-11-01 17:17:07684 PrefetchStatus status = STATUS_UNDEFINED;
685 TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time();
686
687 switch (request_->status().status()) {
688 case net::URLRequestStatus::SUCCESS:
689 if (request_->was_cached()) {
690 status = STATUS_SUCCESS_FROM_CACHE;
691 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromCache",
692 total_time);
693 } else {
694 status = STATUS_SUCCESS_FROM_NETWORK;
695 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromNetwork",
696 total_time);
697 }
698 break;
699 case net::URLRequestStatus::CANCELED:
700 status = STATUS_CANCELED;
701 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeBeforeCancel", total_time);
702 break;
703 case net::URLRequestStatus::IO_PENDING:
704 case net::URLRequestStatus::FAILED:
705 status = STATUS_UNDEFINED;
706 break;
707 }
708
709 UMA_HISTOGRAM_ENUMERATION("Net.Prefetch.Pattern", status, STATUS_MAX);
710 }
711}
712
[email protected]56f0b082012-06-14 07:12:32713} // namespace content