blob: 2f2182c4a13b9d4f8680f5dfaf39c84021c41198 [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]56f0b082012-06-14 07:12:3211#include "content/browser/child_process_security_policy_impl.h"
[email protected]fc6c1872013-10-03 01:22:3512#include "content/browser/loader/cross_site_resource_handler.h"
[email protected]146b8b22013-11-20 03:59:1813#include "content/browser/loader/detachable_resource_handler.h"
[email protected]678c0362012-12-05 08:02:4414#include "content/browser/loader/resource_loader_delegate.h"
15#include "content/browser/loader/resource_request_info_impl.h"
[email protected]56f0b082012-06-14 07:12:3216#include "content/browser/ssl/ssl_client_auth_handler.h"
17#include "content/browser/ssl/ssl_manager.h"
18#include "content/common/ssl_status_serialization.h"
19#include "content/public/browser/cert_store.h"
[email protected]1ccb6992013-10-30 04:46:2020#include "content/public/browser/resource_context.h"
[email protected]56f0b082012-06-14 07:12:3221#include "content/public/browser/resource_dispatcher_host_login_delegate.h"
[email protected]0bbd63b2013-11-29 00:02:1222#include "content/public/browser/signed_certificate_timestamp_store.h"
[email protected]bbdd1b20b2012-12-11 21:24:1323#include "content/public/common/content_client.h"
24#include "content/public/common/content_switches.h"
[email protected]f3b357692013-03-22 05:16:1325#include "content/public/common/process_type.h"
[email protected]56f0b082012-06-14 07:12:3226#include "content/public/common/resource_response.h"
[email protected]fc6c1872013-10-03 01:22:3527#include "net/base/io_buffer.h"
[email protected]56f0b082012-06-14 07:12:3228#include "net/base/load_flags.h"
29#include "net/http/http_response_headers.h"
[email protected]536fd0b2013-03-14 17:41:5730#include "net/ssl/client_cert_store.h"
[email protected]3ed84722013-11-01 17:17:0731#include "net/url_request/url_request_status.h"
[email protected]d5b2fdf2013-06-05 09:36:5532#include "webkit/browser/appcache/appcache_interceptor.h"
[email protected]56f0b082012-06-14 07:12:3233
34using base::TimeDelta;
35using base::TimeTicks;
36
37namespace content {
38namespace {
39
40void PopulateResourceResponse(net::URLRequest* request,
41 ResourceResponse* response) {
[email protected]2756a8e2012-09-07 18:24:2942 response->head.error_code = request->status().error();
[email protected]8df905e22012-06-25 08:15:4243 response->head.request_time = request->request_time();
44 response->head.response_time = request->response_time();
45 response->head.headers = request->response_headers();
46 request->GetCharset(&response->head.charset);
47 response->head.content_length = request->GetExpectedContentSize();
48 request->GetMimeType(&response->head.mime_type);
[email protected]56f0b082012-06-14 07:12:3249 net::HttpResponseInfo response_info = request->response_info();
[email protected]8df905e22012-06-25 08:15:4250 response->head.was_fetched_via_spdy = response_info.was_fetched_via_spdy;
51 response->head.was_npn_negotiated = response_info.was_npn_negotiated;
52 response->head.npn_negotiated_protocol =
53 response_info.npn_negotiated_protocol;
[email protected]92a98df92013-06-06 02:47:4254 response->head.connection_info = response_info.connection_info;
[email protected]8df905e22012-06-25 08:15:4255 response->head.was_fetched_via_proxy = request->was_fetched_via_proxy();
56 response->head.socket_address = request->GetSocketAddress();
[email protected]56f0b082012-06-14 07:12:3257 appcache::AppCacheInterceptor::GetExtraResponseInfo(
58 request,
[email protected]8df905e22012-06-25 08:15:4259 &response->head.appcache_id,
60 &response->head.appcache_manifest_url);
[email protected]acca91d2013-06-04 13:51:2061 // TODO(mmenke): Figure out if LOAD_ENABLE_LOAD_TIMING is safe to remove.
62 if (request->load_flags() & net::LOAD_ENABLE_LOAD_TIMING)
63 request->GetLoadTimingInfo(&response->head.load_timing);
[email protected]56f0b082012-06-14 07:12:3264}
65
66} // namespace
67
68ResourceLoader::ResourceLoader(scoped_ptr<net::URLRequest> request,
69 scoped_ptr<ResourceHandler> handler,
70 ResourceLoaderDelegate* delegate)
[email protected]1ccb6992013-10-30 04:46:2071 : deferred_stage_(DEFERRED_NONE),
72 request_(request.Pass()),
73 handler_(handler.Pass()),
74 delegate_(delegate),
75 last_upload_position_(0),
76 waiting_for_upload_progress_ack_(false),
77 is_transferring_(false),
78 weak_ptr_factory_(this) {
79 request_->set_delegate(this);
80 handler_->SetController(this);
[email protected]56f0b082012-06-14 07:12:3281}
82
83ResourceLoader::~ResourceLoader() {
[email protected]fc72bb12013-06-02 21:13:4684 if (login_delegate_.get())
[email protected]56f0b082012-06-14 07:12:3285 login_delegate_->OnRequestCancelled();
[email protected]fc72bb12013-06-02 21:13:4686 if (ssl_client_auth_handler_.get())
[email protected]56f0b082012-06-14 07:12:3287 ssl_client_auth_handler_->OnRequestCancelled();
88
89 // Run ResourceHandler destructor before we tear-down the rest of our state
90 // as the ResourceHandler may want to inspect the URLRequest and other state.
91 handler_.reset();
92}
93
94void ResourceLoader::StartRequest() {
95 if (delegate_->HandleExternalProtocol(this, request_->url())) {
[email protected]2756a8e2012-09-07 18:24:2996 CancelAndIgnore();
[email protected]56f0b082012-06-14 07:12:3297 return;
98 }
99
100 // Give the handler a chance to delay the URLRequest from being started.
101 bool defer_start = false;
102 if (!handler_->OnWillStart(GetRequestInfo()->GetRequestID(), request_->url(),
103 &defer_start)) {
104 Cancel();
105 return;
106 }
107
108 if (defer_start) {
109 deferred_stage_ = DEFERRED_START;
110 } else {
111 StartRequestInternal();
112 }
113}
114
115void ResourceLoader::CancelRequest(bool from_renderer) {
116 CancelRequestInternal(net::ERR_ABORTED, from_renderer);
117}
118
[email protected]2756a8e2012-09-07 18:24:29119void ResourceLoader::CancelAndIgnore() {
120 ResourceRequestInfoImpl* info = GetRequestInfo();
121 info->set_was_ignored_by_handler(true);
122 CancelRequest(false);
123}
124
[email protected]af3d4962012-10-19 10:57:26125void ResourceLoader::CancelWithError(int error_code) {
126 CancelRequestInternal(error_code, false);
127}
128
[email protected]56f0b082012-06-14 07:12:32129void ResourceLoader::ReportUploadProgress() {
130 ResourceRequestInfoImpl* info = GetRequestInfo();
131
132 if (waiting_for_upload_progress_ack_)
133 return; // Send one progress event at a time.
134
[email protected]7335ab02012-08-30 22:30:42135 net::UploadProgress progress = request_->GetUploadProgress();
136 if (!progress.size())
[email protected]56f0b082012-06-14 07:12:32137 return; // Nothing to upload.
138
[email protected]7335ab02012-08-30 22:30:42139 if (progress.position() == last_upload_position_)
[email protected]56f0b082012-06-14 07:12:32140 return; // No progress made since last time.
141
142 const uint64 kHalfPercentIncrements = 200;
143 const TimeDelta kOneSecond = TimeDelta::FromMilliseconds(1000);
144
[email protected]7335ab02012-08-30 22:30:42145 uint64 amt_since_last = progress.position() - last_upload_position_;
[email protected]56f0b082012-06-14 07:12:32146 TimeDelta time_since_last = TimeTicks::Now() - last_upload_ticks_;
147
[email protected]7335ab02012-08-30 22:30:42148 bool is_finished = (progress.size() == progress.position());
149 bool enough_new_progress =
150 (amt_since_last > (progress.size() / kHalfPercentIncrements));
[email protected]56f0b082012-06-14 07:12:32151 bool too_much_time_passed = time_since_last > kOneSecond;
152
153 if (is_finished || enough_new_progress || too_much_time_passed) {
154 if (request_->load_flags() & net::LOAD_ENABLE_UPLOAD_PROGRESS) {
[email protected]7335ab02012-08-30 22:30:42155 handler_->OnUploadProgress(
156 info->GetRequestID(), progress.position(), progress.size());
[email protected]56f0b082012-06-14 07:12:32157 waiting_for_upload_progress_ack_ = true;
158 }
159 last_upload_ticks_ = TimeTicks::Now();
[email protected]7335ab02012-08-30 22:30:42160 last_upload_position_ = progress.position();
[email protected]56f0b082012-06-14 07:12:32161 }
162}
163
[email protected]fbaccee2013-08-12 23:24:02164void ResourceLoader::MarkAsTransferring(const GURL& target_url) {
[email protected]46c704762013-12-18 18:10:24165 CHECK(ResourceType::IsFrame(GetRequestInfo()->GetResourceType()))
166 << "Can only transfer for navigations";
[email protected]56f0b082012-06-14 07:12:32167 is_transferring_ = true;
168
[email protected]fbaccee2013-08-12 23:24:02169 // When transferring a request to another process, the renderer doesn't get
170 // a chance to update the cookie policy URL. Do it here instead.
[email protected]46c704762013-12-18 18:10:24171 // TODO(creis): Remove this in https://codereview.chromium.org/117623003/.
172 if (GetRequestInfo()->GetResourceType() == ResourceType::MAIN_FRAME)
173 request()->set_first_party_for_cookies(target_url);
[email protected]56f0b082012-06-14 07:12:32174}
175
[email protected]1f291cd2013-09-25 22:05:14176void ResourceLoader::CompleteTransfer() {
[email protected]fc6c1872013-10-03 01:22:35177 DCHECK_EQ(DEFERRED_READ, deferred_stage_);
[email protected]56f0b082012-06-14 07:12:32178
[email protected]56f0b082012-06-14 07:12:32179 is_transferring_ = false;
[email protected]fc6c1872013-10-03 01:22:35180 GetRequestInfo()->cross_site_handler()->ResumeResponse();
[email protected]56f0b082012-06-14 07:12:32181}
182
183ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() {
184 return ResourceRequestInfoImpl::ForRequest(request_.get());
185}
186
187void ResourceLoader::ClearLoginDelegate() {
188 login_delegate_ = NULL;
189}
190
191void ResourceLoader::ClearSSLClientAuthHandler() {
192 ssl_client_auth_handler_ = NULL;
193}
194
195void ResourceLoader::OnUploadProgressACK() {
196 waiting_for_upload_progress_ack_ = false;
197}
198
[email protected]56f0b082012-06-14 07:12:32199void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused,
200 const GURL& new_url,
201 bool* defer) {
202 DCHECK_EQ(request_.get(), unused);
203
204 VLOG(1) << "OnReceivedRedirect: " << request_->url().spec();
205 DCHECK(request_->status().is_success());
206
207 ResourceRequestInfoImpl* info = GetRequestInfo();
208
209 if (info->process_type() != PROCESS_TYPE_PLUGIN &&
210 !ChildProcessSecurityPolicyImpl::GetInstance()->
211 CanRequestURL(info->GetChildID(), new_url)) {
212 VLOG(1) << "Denied unauthorized request for "
213 << new_url.possibly_invalid_spec();
214
215 // Tell the renderer that this request was disallowed.
216 Cancel();
217 return;
218 }
219
220 delegate_->DidReceiveRedirect(this, new_url);
221
222 if (delegate_->HandleExternalProtocol(this, new_url)) {
223 // The request is complete so we can remove it.
[email protected]2756a8e2012-09-07 18:24:29224 CancelAndIgnore();
[email protected]56f0b082012-06-14 07:12:32225 return;
226 }
227
228 scoped_refptr<ResourceResponse> response(new ResourceResponse());
[email protected]fc72bb12013-06-02 21:13:46229 PopulateResourceResponse(request_.get(), response.get());
[email protected]56f0b082012-06-14 07:12:32230
[email protected]fc72bb12013-06-02 21:13:46231 if (!handler_->OnRequestRedirected(
232 info->GetRequestID(), new_url, response.get(), defer)) {
[email protected]56f0b082012-06-14 07:12:32233 Cancel();
[email protected]926360f2012-06-29 04:45:02234 } else if (*defer) {
235 deferred_stage_ = DEFERRED_REDIRECT; // Follow redirect when resumed.
[email protected]56f0b082012-06-14 07:12:32236 }
[email protected]56f0b082012-06-14 07:12:32237}
238
239void ResourceLoader::OnAuthRequired(net::URLRequest* unused,
240 net::AuthChallengeInfo* auth_info) {
241 DCHECK_EQ(request_.get(), unused);
242
243 if (request_->load_flags() & net::LOAD_DO_NOT_PROMPT_FOR_LOGIN) {
244 request_->CancelAuth();
245 return;
246 }
247
248 if (!delegate_->AcceptAuthRequest(this, auth_info)) {
249 request_->CancelAuth();
250 return;
251 }
252
253 // Create a login dialog on the UI thread to get authentication data, or pull
254 // from cache and continue on the IO thread.
255
[email protected]fc72bb12013-06-02 21:13:46256 DCHECK(!login_delegate_.get())
257 << "OnAuthRequired called with login_delegate pending";
[email protected]56f0b082012-06-14 07:12:32258 login_delegate_ = delegate_->CreateLoginDelegate(this, auth_info);
[email protected]fc72bb12013-06-02 21:13:46259 if (!login_delegate_.get())
[email protected]56f0b082012-06-14 07:12:32260 request_->CancelAuth();
261}
262
263void ResourceLoader::OnCertificateRequested(
264 net::URLRequest* unused,
265 net::SSLCertRequestInfo* cert_info) {
266 DCHECK_EQ(request_.get(), unused);
267
268 if (!delegate_->AcceptSSLClientCertificateRequest(this, cert_info)) {
269 request_->Cancel();
270 return;
271 }
272
[email protected]fc72bb12013-06-02 21:13:46273 DCHECK(!ssl_client_auth_handler_.get())
274 << "OnCertificateRequested called with ssl_client_auth_handler pending";
[email protected]1ccb6992013-10-30 04:46:20275 ssl_client_auth_handler_ = new SSLClientAuthHandler(
276 GetRequestInfo()->GetContext()->CreateClientCertStore(),
277 request_.get(),
278 cert_info);
[email protected]56f0b082012-06-14 07:12:32279 ssl_client_auth_handler_->SelectCertificate();
280}
281
282void ResourceLoader::OnSSLCertificateError(net::URLRequest* request,
283 const net::SSLInfo& ssl_info,
284 bool fatal) {
285 ResourceRequestInfoImpl* info = GetRequestInfo();
286
287 int render_process_id;
288 int render_view_id;
289 if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id))
290 NOTREACHED();
291
292 SSLManager::OnSSLCertificateError(
[email protected]5c1d3e52012-08-01 05:14:27293 weak_ptr_factory_.GetWeakPtr(),
[email protected]56f0b082012-06-14 07:12:32294 info->GetGlobalRequestID(),
295 info->GetResourceType(),
296 request_->url(),
297 render_process_id,
298 render_view_id,
299 ssl_info,
300 fatal);
301}
302
303void ResourceLoader::OnResponseStarted(net::URLRequest* unused) {
304 DCHECK_EQ(request_.get(), unused);
305
306 VLOG(1) << "OnResponseStarted: " << request_->url().spec();
307
[email protected]bbdd1b20b2012-12-11 21:24:13308 // The CanLoadPage check should take place after any server redirects have
309 // finished, at the point in time that we know a page will commit in the
310 // renderer process.
311 ResourceRequestInfoImpl* info = GetRequestInfo();
312 ChildProcessSecurityPolicyImpl* policy =
313 ChildProcessSecurityPolicyImpl::GetInstance();
314 if (!policy->CanLoadPage(info->GetChildID(),
315 request_->url(),
316 info->GetResourceType())) {
317 Cancel();
318 return;
319 }
320
[email protected]926360f2012-06-29 04:45:02321 if (!request_->status().is_success()) {
322 ResponseCompleted();
323 return;
324 }
325
326 // We want to send a final upload progress message prior to sending the
327 // response complete message even if we're waiting for an ack to to a
328 // previous upload progress message.
329 waiting_for_upload_progress_ack_ = false;
330 ReportUploadProgress();
331
332 CompleteResponseStarted();
333
334 if (is_deferred())
335 return;
336
[email protected]56f0b082012-06-14 07:12:32337 if (request_->status().is_success()) {
[email protected]926360f2012-06-29 04:45:02338 StartReading(false); // Read the first chunk.
[email protected]56f0b082012-06-14 07:12:32339 } else {
340 ResponseCompleted();
341 }
342}
343
344void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) {
345 DCHECK_EQ(request_.get(), unused);
346 VLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\""
347 << " bytes_read = " << bytes_read;
348
[email protected]926360f2012-06-29 04:45:02349 // bytes_read == -1 always implies an error.
350 if (bytes_read == -1 || !request_->status().is_success()) {
[email protected]56f0b082012-06-14 07:12:32351 ResponseCompleted();
352 return;
353 }
354
[email protected]926360f2012-06-29 04:45:02355 CompleteRead(bytes_read);
[email protected]56f0b082012-06-14 07:12:32356
[email protected]926360f2012-06-29 04:45:02357 if (is_deferred())
[email protected]56f0b082012-06-14 07:12:32358 return;
[email protected]56f0b082012-06-14 07:12:32359
[email protected]926360f2012-06-29 04:45:02360 if (request_->status().is_success() && bytes_read > 0) {
361 StartReading(true); // Read the next chunk.
362 } else {
[email protected]56f0b082012-06-14 07:12:32363 ResponseCompleted();
[email protected]926360f2012-06-29 04:45:02364 }
[email protected]56f0b082012-06-14 07:12:32365}
366
367void ResourceLoader::CancelSSLRequest(const GlobalRequestID& id,
368 int error,
369 const net::SSLInfo* ssl_info) {
370 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
371
372 // The request can be NULL if it was cancelled by the renderer (as the
373 // request of the user navigating to a new page from the location bar).
374 if (!request_->is_pending())
375 return;
376 DVLOG(1) << "CancelSSLRequest() url: " << request_->url().spec();
377
378 if (ssl_info) {
379 request_->CancelWithSSLError(error, *ssl_info);
380 } else {
381 request_->CancelWithError(error);
382 }
383}
384
385void ResourceLoader::ContinueSSLRequest(const GlobalRequestID& id) {
386 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
387
388 DVLOG(1) << "ContinueSSLRequest() url: " << request_->url().spec();
389
390 request_->ContinueDespiteLastError();
391}
392
393void ResourceLoader::Resume() {
394 DCHECK(!is_transferring_);
395
396 DeferredStage stage = deferred_stage_;
397 deferred_stage_ = DEFERRED_NONE;
398 switch (stage) {
399 case DEFERRED_NONE:
400 NOTREACHED();
401 break;
402 case DEFERRED_START:
403 StartRequestInternal();
404 break;
405 case DEFERRED_REDIRECT:
406 request_->FollowDeferredRedirect();
407 break;
[email protected]56f0b082012-06-14 07:12:32408 case DEFERRED_READ:
[email protected]dd32b1272013-05-04 14:17:11409 base::MessageLoop::current()->PostTask(
[email protected]926360f2012-06-29 04:45:02410 FROM_HERE,
[email protected]5c1d3e52012-08-01 05:14:27411 base::Bind(&ResourceLoader::ResumeReading,
412 weak_ptr_factory_.GetWeakPtr()));
[email protected]56f0b082012-06-14 07:12:32413 break;
414 case DEFERRED_FINISH:
415 // Delay self-destruction since we don't know how we were reached.
[email protected]dd32b1272013-05-04 14:17:11416 base::MessageLoop::current()->PostTask(
[email protected]56f0b082012-06-14 07:12:32417 FROM_HERE,
[email protected]5c1d3e52012-08-01 05:14:27418 base::Bind(&ResourceLoader::CallDidFinishLoading,
419 weak_ptr_factory_.GetWeakPtr()));
[email protected]56f0b082012-06-14 07:12:32420 break;
421 }
422}
423
424void ResourceLoader::Cancel() {
425 CancelRequest(false);
426}
427
428void ResourceLoader::StartRequestInternal() {
429 DCHECK(!request_->is_pending());
430 request_->Start();
431
432 delegate_->DidStartRequest(this);
433}
434
435void ResourceLoader::CancelRequestInternal(int error, bool from_renderer) {
436 VLOG(1) << "CancelRequestInternal: " << request_->url().spec();
437
438 ResourceRequestInfoImpl* info = GetRequestInfo();
439
440 // WebKit will send us a cancel for downloads since it no longer handles
441 // them. In this case, ignore the cancel since we handle downloads in the
442 // browser.
[email protected]70983822013-11-27 14:33:59443 if (from_renderer && (info->IsDownload() || info->is_stream()))
[email protected]56f0b082012-06-14 07:12:32444 return;
445
[email protected]146b8b22013-11-20 03:59:18446 if (from_renderer && info->detachable_handler()) {
447 // TODO(davidben): Fix Blink handling of prefetches so they are not
448 // cancelled on navigate away and end up in the local cache.
449 info->detachable_handler()->Detach();
450 return;
451 }
452
[email protected]926360f2012-06-29 04:45:02453 // TODO(darin): Perhaps we should really be looking to see if the status is
454 // IO_PENDING?
[email protected]56f0b082012-06-14 07:12:32455 bool was_pending = request_->is_pending();
456
[email protected]fc72bb12013-06-02 21:13:46457 if (login_delegate_.get()) {
[email protected]56f0b082012-06-14 07:12:32458 login_delegate_->OnRequestCancelled();
459 login_delegate_ = NULL;
460 }
[email protected]fc72bb12013-06-02 21:13:46461 if (ssl_client_auth_handler_.get()) {
[email protected]56f0b082012-06-14 07:12:32462 ssl_client_auth_handler_->OnRequestCancelled();
463 ssl_client_auth_handler_ = NULL;
464 }
465
466 request_->CancelWithError(error);
467
468 if (!was_pending) {
469 // If the request isn't in flight, then we won't get an asynchronous
470 // notification from the request, so we have to signal ourselves to finish
471 // this request.
[email protected]dd32b1272013-05-04 14:17:11472 base::MessageLoop::current()->PostTask(
473 FROM_HERE,
474 base::Bind(&ResourceLoader::ResponseCompleted,
475 weak_ptr_factory_.GetWeakPtr()));
[email protected]56f0b082012-06-14 07:12:32476 }
477}
478
[email protected]0bbd63b2013-11-29 00:02:12479void ResourceLoader::StoreSignedCertificateTimestamps(
480 const net::SignedCertificateTimestampAndStatusList& sct_list,
481 int process_id,
482 SignedCertificateTimestampIDStatusList* sct_ids) {
483 SignedCertificateTimestampStore* sct_store(
484 SignedCertificateTimestampStore::GetInstance());
485
486 for (net::SignedCertificateTimestampAndStatusList::const_iterator iter =
487 sct_list.begin(); iter != sct_list.end(); ++iter) {
488 const int sct_id(sct_store->Store(iter->sct_, process_id));
489 sct_ids->push_back(
490 SignedCertificateTimestampIDAndStatus(sct_id, iter->status_));
491 }
492}
493
[email protected]926360f2012-06-29 04:45:02494void ResourceLoader::CompleteResponseStarted() {
[email protected]56f0b082012-06-14 07:12:32495 ResourceRequestInfoImpl* info = GetRequestInfo();
496
497 scoped_refptr<ResourceResponse> response(new ResourceResponse());
[email protected]fc72bb12013-06-02 21:13:46498 PopulateResourceResponse(request_.get(), response.get());
[email protected]56f0b082012-06-14 07:12:32499
[email protected]fc72bb12013-06-02 21:13:46500 if (request_->ssl_info().cert.get()) {
501 int cert_id = CertStore::GetInstance()->StoreCert(
502 request_->ssl_info().cert.get(), info->GetChildID());
[email protected]0bbd63b2013-11-29 00:02:12503
504 SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
505 StoreSignedCertificateTimestamps(
506 request_->ssl_info().signed_certificate_timestamps,
507 info->GetChildID(),
508 &signed_certificate_timestamp_ids);
509
[email protected]8df905e22012-06-25 08:15:42510 response->head.security_info = SerializeSecurityInfo(
[email protected]56f0b082012-06-14 07:12:32511 cert_id,
512 request_->ssl_info().cert_status,
513 request_->ssl_info().security_bits,
[email protected]0bbd63b2013-11-29 00:02:12514 request_->ssl_info().connection_status,
515 signed_certificate_timestamp_ids);
[email protected]56f0b082012-06-14 07:12:32516 } else {
517 // We should not have any SSL state.
518 DCHECK(!request_->ssl_info().cert_status &&
519 request_->ssl_info().security_bits == -1 &&
520 !request_->ssl_info().connection_status);
521 }
522
523 delegate_->DidReceiveResponse(this);
[email protected]56f0b082012-06-14 07:12:32524
525 bool defer = false;
[email protected]fc72bb12013-06-02 21:13:46526 if (!handler_->OnResponseStarted(
527 info->GetRequestID(), response.get(), &defer)) {
[email protected]926360f2012-06-29 04:45:02528 Cancel();
529 } else if (defer) {
[email protected]5e3183482013-08-09 11:05:19530 read_deferral_start_time_ = base::TimeTicks::Now();
[email protected]926360f2012-06-29 04:45:02531 deferred_stage_ = DEFERRED_READ; // Read first chunk when resumed.
[email protected]56f0b082012-06-14 07:12:32532 }
[email protected]56f0b082012-06-14 07:12:32533}
534
[email protected]926360f2012-06-29 04:45:02535void ResourceLoader::StartReading(bool is_continuation) {
[email protected]56f0b082012-06-14 07:12:32536 int bytes_read = 0;
[email protected]926360f2012-06-29 04:45:02537 ReadMore(&bytes_read);
538
539 // If IO is pending, wait for the URLRequest to call OnReadCompleted.
540 if (request_->status().is_io_pending())
541 return;
542
543 if (!is_continuation || bytes_read <= 0) {
[email protected]56f0b082012-06-14 07:12:32544 OnReadCompleted(request_.get(), bytes_read);
[email protected]926360f2012-06-29 04:45:02545 } else {
546 // Else, trigger OnReadCompleted asynchronously to avoid starving the IO
547 // thread in case the URLRequest can provide data synchronously.
[email protected]dd32b1272013-05-04 14:17:11548 base::MessageLoop::current()->PostTask(
[email protected]926360f2012-06-29 04:45:02549 FROM_HERE,
[email protected]5c1d3e52012-08-01 05:14:27550 base::Bind(&ResourceLoader::OnReadCompleted,
551 weak_ptr_factory_.GetWeakPtr(),
[email protected]dd32b1272013-05-04 14:17:11552 request_.get(),
553 bytes_read));
[email protected]926360f2012-06-29 04:45:02554 }
555}
556
557void ResourceLoader::ResumeReading() {
558 DCHECK(!is_deferred());
559
[email protected]5e3183482013-08-09 11:05:19560 if (!read_deferral_start_time_.is_null()) {
561 UMA_HISTOGRAM_TIMES("Net.ResourceLoader.ReadDeferral",
562 base::TimeTicks::Now() - read_deferral_start_time_);
563 read_deferral_start_time_ = base::TimeTicks();
564 }
[email protected]926360f2012-06-29 04:45:02565 if (request_->status().is_success()) {
566 StartReading(false); // Read the next chunk (OK to complete synchronously).
567 } else {
[email protected]56f0b082012-06-14 07:12:32568 ResponseCompleted();
569 }
570}
571
[email protected]926360f2012-06-29 04:45:02572void ResourceLoader::ReadMore(int* bytes_read) {
[email protected]56f0b082012-06-14 07:12:32573 ResourceRequestInfoImpl* info = GetRequestInfo();
[email protected]926360f2012-06-29 04:45:02574 DCHECK(!is_deferred());
[email protected]56f0b082012-06-14 07:12:32575
[email protected]ef5306e2013-10-15 19:38:18576 // Make sure we track the buffer in at least one place. This ensures it gets
577 // deleted even in the case the request has already finished its job and
578 // doesn't use the buffer.
579 scoped_refptr<net::IOBuffer> buf;
[email protected]56f0b082012-06-14 07:12:32580 int buf_size;
[email protected]926360f2012-06-29 04:45:02581 if (!handler_->OnWillRead(info->GetRequestID(), &buf, &buf_size, -1)) {
582 Cancel();
583 return;
584 }
[email protected]56f0b082012-06-14 07:12:32585
586 DCHECK(buf);
587 DCHECK(buf_size > 0);
588
[email protected]ef5306e2013-10-15 19:38:18589 request_->Read(buf.get(), buf_size, bytes_read);
[email protected]926360f2012-06-29 04:45:02590
591 // No need to check the return value here as we'll detect errors by
592 // inspecting the URLRequest's status.
[email protected]56f0b082012-06-14 07:12:32593}
594
[email protected]926360f2012-06-29 04:45:02595void ResourceLoader::CompleteRead(int bytes_read) {
596 DCHECK(bytes_read >= 0);
597 DCHECK(request_->status().is_success());
[email protected]56f0b082012-06-14 07:12:32598
599 ResourceRequestInfoImpl* info = GetRequestInfo();
600
601 bool defer = false;
602 if (!handler_->OnReadCompleted(info->GetRequestID(), bytes_read, &defer)) {
603 Cancel();
[email protected]926360f2012-06-29 04:45:02604 } else if (defer) {
605 deferred_stage_ = DEFERRED_READ; // Read next chunk when resumed.
[email protected]56f0b082012-06-14 07:12:32606 }
[email protected]56f0b082012-06-14 07:12:32607}
608
609void ResourceLoader::ResponseCompleted() {
610 VLOG(1) << "ResponseCompleted: " << request_->url().spec();
[email protected]3ed84722013-11-01 17:17:07611 RecordHistograms();
[email protected]56f0b082012-06-14 07:12:32612 ResourceRequestInfoImpl* info = GetRequestInfo();
613
614 std::string security_info;
615 const net::SSLInfo& ssl_info = request_->ssl_info();
[email protected]fc72bb12013-06-02 21:13:46616 if (ssl_info.cert.get() != NULL) {
617 int cert_id = CertStore::GetInstance()->StoreCert(ssl_info.cert.get(),
[email protected]56f0b082012-06-14 07:12:32618 info->GetChildID());
[email protected]0bbd63b2013-11-29 00:02:12619 SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
620 StoreSignedCertificateTimestamps(ssl_info.signed_certificate_timestamps,
621 info->GetChildID(),
622 &signed_certificate_timestamp_ids);
623
[email protected]56f0b082012-06-14 07:12:32624 security_info = SerializeSecurityInfo(
625 cert_id, ssl_info.cert_status, ssl_info.security_bits,
[email protected]0bbd63b2013-11-29 00:02:12626 ssl_info.connection_status, signed_certificate_timestamp_ids);
[email protected]56f0b082012-06-14 07:12:32627 }
628
[email protected]3780874a2013-11-18 05:49:03629 bool defer = false;
630 handler_->OnResponseCompleted(info->GetRequestID(), request_->status(),
631 security_info, &defer);
632 if (defer) {
[email protected]56f0b082012-06-14 07:12:32633 // The handler is not ready to die yet. We will call DidFinishLoading when
634 // we resume.
635 deferred_stage_ = DEFERRED_FINISH;
[email protected]3780874a2013-11-18 05:49:03636 } else {
637 // This will result in our destruction.
638 CallDidFinishLoading();
[email protected]56f0b082012-06-14 07:12:32639 }
640}
641
[email protected]56f0b082012-06-14 07:12:32642void ResourceLoader::CallDidFinishLoading() {
643 delegate_->DidFinishLoading(this);
644}
645
[email protected]3ed84722013-11-01 17:17:07646void ResourceLoader::RecordHistograms() {
647 ResourceRequestInfoImpl* info = GetRequestInfo();
648
649 if (info->GetResourceType() == ResourceType::PREFETCH) {
650 PrefetchStatus status = STATUS_UNDEFINED;
651 TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time();
652
653 switch (request_->status().status()) {
654 case net::URLRequestStatus::SUCCESS:
655 if (request_->was_cached()) {
656 status = STATUS_SUCCESS_FROM_CACHE;
657 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromCache",
658 total_time);
659 } else {
660 status = STATUS_SUCCESS_FROM_NETWORK;
661 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromNetwork",
662 total_time);
663 }
664 break;
665 case net::URLRequestStatus::CANCELED:
666 status = STATUS_CANCELED;
667 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeBeforeCancel", total_time);
668 break;
669 case net::URLRequestStatus::IO_PENDING:
670 case net::URLRequestStatus::FAILED:
671 status = STATUS_UNDEFINED;
672 break;
673 }
674
675 UMA_HISTOGRAM_ENUMERATION("Net.Prefetch.Pattern", status, STATUS_MAX);
676 }
677}
678
[email protected]56f0b082012-06-14 07:12:32679} // namespace content