OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. |
3 * Copyright (C) 2013, Intel Corporation | 3 * Copyright (C) 2013, Intel Corporation |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
7 * met: | 7 * met: |
8 * | 8 * |
9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 m_requestStartedSeconds = 0.0; | 408 m_requestStartedSeconds = 0.0; |
409 clearResource(); | 409 clearResource(); |
410 } | 410 } |
411 | 411 |
412 // In this method, we can clear |request| to tell content::WebURLLoaderImpl of | 412 // In this method, we can clear |request| to tell content::WebURLLoaderImpl of |
413 // Chromium not to follow the redirect. This works only when this method is | 413 // Chromium not to follow the redirect. This works only when this method is |
414 // called by RawResource::willSendRequest(). If called by | 414 // called by RawResource::willSendRequest(). If called by |
415 // RawResource::didAddClient(), clearing |request| won't be propagated | 415 // RawResource::didAddClient(), clearing |request| won't be propagated |
416 // to content::WebURLLoaderImpl. So, this loader must also get detached from | 416 // to content::WebURLLoaderImpl. So, this loader must also get detached from |
417 // the resource by calling clearResource(). | 417 // the resource by calling clearResource(). |
418 void DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequ
est& request, const ResourceResponse& redirectResponse) | 418 bool DocumentThreadableLoader::redirectReceived(Resource* resource, const Resour
ceRequest& request, const ResourceResponse& redirectResponse) |
419 { | 419 { |
420 DCHECK(m_client); | 420 DCHECK(m_client); |
421 DCHECK_EQ(resource, this->resource()); | 421 DCHECK_EQ(resource, this->resource()); |
422 DCHECK(m_async); | 422 DCHECK(m_async); |
423 | 423 |
424 m_checker.redirectReceived(); | 424 m_checker.redirectReceived(); |
425 | 425 |
426 if (!m_actualRequest.isNull()) { | 426 if (!m_actualRequest.isNull()) { |
427 reportResponseReceived(resource->identifier(), redirectResponse); | 427 reportResponseReceived(resource->identifier(), redirectResponse); |
428 | 428 |
429 handlePreflightFailure(redirectResponse.url().getString(), "Response for
preflight is invalid (redirect)"); | 429 handlePreflightFailure(redirectResponse.url().getString(), "Response for
preflight is invalid (redirect)"); |
430 | 430 |
431 request = ResourceRequest(); | 431 return false; |
432 | |
433 return; | |
434 } | 432 } |
435 | 433 |
436 if (m_redirectMode == WebURLRequest::FetchRedirectModeManual) { | 434 if (m_redirectMode == WebURLRequest::FetchRedirectModeManual) { |
437 // We use |m_redirectMode| to check the original redirect mode. | 435 // We use |m_redirectMode| to check the original redirect mode. |
438 // |request| is a new request for redirect. So we don't set the redirect | 436 // |request| is a new request for redirect. So we don't set the redirect |
439 // mode of it in WebURLLoaderImpl::Context::OnReceivedRedirect(). | 437 // mode of it in WebURLLoaderImpl::Context::OnReceivedRedirect(). |
440 DCHECK(request.useStreamOnResponse()); | 438 DCHECK(request.useStreamOnResponse()); |
441 // There is no need to read the body of redirect response because there | 439 // There is no need to read the body of redirect response because there |
442 // is no way to read the body of opaque-redirect filtered response's | 440 // is no way to read the body of opaque-redirect filtered response's |
443 // internal response. | 441 // internal response. |
444 // TODO(horo): If we support any API which expose the internal body, we | 442 // TODO(horo): If we support any API which expose the internal body, we |
445 // will have to read the body. And also HTTPCache changes will be needed | 443 // will have to read the body. And also HTTPCache changes will be needed |
446 // because it doesn't store the body of redirect responses. | 444 // because it doesn't store the body of redirect responses. |
447 responseReceived(resource, redirectResponse, wrapUnique(new EmptyDataHan
dle())); | 445 responseReceived(resource, redirectResponse, wrapUnique(new EmptyDataHan
dle())); |
448 | 446 |
449 if (m_client) { | 447 if (m_client) { |
450 DCHECK(m_actualRequest.isNull()); | 448 DCHECK(m_actualRequest.isNull()); |
451 notifyFinished(resource); | 449 notifyFinished(resource); |
452 } | 450 } |
453 | 451 |
454 request = ResourceRequest(); | 452 return false; |
455 | |
456 return; | |
457 } | 453 } |
458 | 454 |
459 if (m_redirectMode == WebURLRequest::FetchRedirectModeError) { | 455 if (m_redirectMode == WebURLRequest::FetchRedirectModeError) { |
460 ThreadableLoaderClient* client = m_client; | 456 ThreadableLoaderClient* client = m_client; |
461 clear(); | 457 clear(); |
462 client->didFailRedirectCheck(); | 458 client->didFailRedirectCheck(); |
463 | 459 |
464 request = ResourceRequest(); | 460 return false; |
465 | |
466 return; | |
467 } | 461 } |
468 | 462 |
469 // Allow same origin requests to continue after allowing clients to audit th
e redirect. | 463 // Allow same origin requests to continue after allowing clients to audit th
e redirect. |
470 if (isAllowedRedirect(request.url())) { | 464 if (isAllowedRedirect(request.url())) { |
471 if (m_client->isDocumentThreadableLoaderClient()) | 465 if (m_client->isDocumentThreadableLoaderClient()) |
472 static_cast<DocumentThreadableLoaderClient*>(m_client)->willFollowRe
direct(request, redirectResponse); | 466 return static_cast<DocumentThreadableLoaderClient*>(m_client)->willF
ollowRedirect(request, redirectResponse); |
473 return; | 467 return true; |
474 } | 468 } |
475 | 469 |
476 if (m_corsRedirectLimit <= 0) { | 470 if (m_corsRedirectLimit <= 0) { |
477 ThreadableLoaderClient* client = m_client; | 471 ThreadableLoaderClient* client = m_client; |
478 clear(); | 472 clear(); |
479 client->didFailRedirectCheck(); | 473 client->didFailRedirectCheck(); |
480 request = ResourceRequest(); | 474 return false; |
481 return; | |
482 } | 475 } |
483 | 476 |
484 --m_corsRedirectLimit; | 477 --m_corsRedirectLimit; |
485 | 478 |
486 InspectorInstrumentation::didReceiveCORSRedirectResponse(document().frame(),
resource->identifier(), document().frame()->loader().documentLoader(), redirect
Response, resource); | 479 InspectorInstrumentation::didReceiveCORSRedirectResponse(document().frame(),
resource->identifier(), document().frame()->loader().documentLoader(), redirect
Response, resource); |
487 | 480 |
488 bool allowRedirect = false; | 481 bool allowRedirect = false; |
489 String accessControlErrorDescription; | 482 String accessControlErrorDescription; |
490 | 483 |
491 if (m_crossOriginNonSimpleRequest) { | 484 if (m_crossOriginNonSimpleRequest) { |
492 // Non-simple cross origin requests (both preflight and actual one) are | 485 // Non-simple cross origin requests (both preflight and actual one) are |
493 // not allowed to follow redirect. | 486 // not allowed to follow redirect. |
494 accessControlErrorDescription = "Redirect from '" + redirectResponse.url
().getString()+ "' to '" + request.url().getString() + "' has been blocked by CO
RS policy: Request requires preflight, which is disallowed to follow cross-origi
n redirect."; | 487 accessControlErrorDescription = "Redirect from '" + redirectResponse.url
().getString()+ "' to '" + request.url().getString() + "' has been blocked by CO
RS policy: Request requires preflight, which is disallowed to follow cross-origi
n redirect."; |
495 } else if (!CrossOriginAccessControl::isLegalRedirectLocation(request.url(),
accessControlErrorDescription)) { | 488 } else if (!CrossOriginAccessControl::isLegalRedirectLocation(request.url(),
accessControlErrorDescription)) { |
496 accessControlErrorDescription = "Redirect from '" + redirectResponse.url
().getString() + "' has been blocked by CORS policy: " + accessControlErrorDescr
iption; | 489 accessControlErrorDescription = "Redirect from '" + redirectResponse.url
().getString() + "' has been blocked by CORS policy: " + accessControlErrorDescr
iption; |
497 } else if (!m_sameOriginRequest && !passesAccessControlCheck(redirectRespons
e, effectiveAllowCredentials(), getSecurityOrigin(), accessControlErrorDescripti
on, m_requestContext)) { | 490 } else if (!m_sameOriginRequest && !passesAccessControlCheck(redirectRespons
e, effectiveAllowCredentials(), getSecurityOrigin(), accessControlErrorDescripti
on, m_requestContext)) { |
498 // The redirect response must pass the access control check if the | 491 // The redirect response must pass the access control check if the |
499 // original request was not same-origin. | 492 // original request was not same-origin. |
500 accessControlErrorDescription = "Redirect from '" + redirectResponse.url
().getString()+ "' to '" + request.url().getString() + "' has been blocked by CO
RS policy: " + accessControlErrorDescription; | 493 accessControlErrorDescription = "Redirect from '" + redirectResponse.url
().getString()+ "' to '" + request.url().getString() + "' has been blocked by CO
RS policy: " + accessControlErrorDescription; |
501 } else { | 494 } else { |
502 allowRedirect = true; | 495 allowRedirect = true; |
503 } | 496 } |
504 | 497 |
505 if (!allowRedirect) { | 498 if (!allowRedirect) { |
506 ThreadableLoaderClient* client = m_client; | 499 ThreadableLoaderClient* client = m_client; |
507 clear(); | 500 clear(); |
508 client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal
, 0, redirectResponse.url().getString(), accessControlErrorDescription)); | 501 client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal
, 0, redirectResponse.url().getString(), accessControlErrorDescription)); |
509 request = ResourceRequest(); | 502 return false; |
510 return; | |
511 } | 503 } |
512 | 504 |
513 // FIXME: consider combining this with CORS redirect handling performed by | 505 // FIXME: consider combining this with CORS redirect handling performed by |
514 // CrossOriginAccessControl::handleRedirect(). | 506 // CrossOriginAccessControl::handleRedirect(). |
515 clearResource(); | 507 clearResource(); |
516 | 508 |
517 // If the original request wasn't same-origin, then if the request URL origi
n is not same origin with the original URL origin, | 509 // If the original request wasn't same-origin, then if the request URL origi
n is not same origin with the original URL origin, |
518 // set the source origin to a globally unique identifier. (If the original r
equest was same-origin, the origin of the new request | 510 // set the source origin to a globally unique identifier. (If the original r
equest was same-origin, the origin of the new request |
519 // should be the original URL origin.) | 511 // should be the original URL origin.) |
520 if (!m_sameOriginRequest) { | 512 if (!m_sameOriginRequest) { |
521 RefPtr<SecurityOrigin> originalOrigin = SecurityOrigin::create(redirectR
esponse.url()); | 513 RefPtr<SecurityOrigin> originalOrigin = SecurityOrigin::create(redirectR
esponse.url()); |
522 RefPtr<SecurityOrigin> requestOrigin = SecurityOrigin::create(request.ur
l()); | 514 RefPtr<SecurityOrigin> requestOrigin = SecurityOrigin::create(request.ur
l()); |
523 if (!originalOrigin->isSameSchemeHostPort(requestOrigin.get())) | 515 if (!originalOrigin->isSameSchemeHostPort(requestOrigin.get())) |
524 m_securityOrigin = SecurityOrigin::createUnique(); | 516 m_securityOrigin = SecurityOrigin::createUnique(); |
525 } | 517 } |
526 // Force any subsequent requests to use these checks. | 518 // Force any subsequent requests to use these checks. |
527 m_sameOriginRequest = false; | 519 m_sameOriginRequest = false; |
528 | 520 |
529 // Since the request is no longer same-origin, if the user didn't request cr
edentials in | 521 // Since the request is no longer same-origin, if the user didn't request cr
edentials in |
530 // the first place, update our state so we neither request them nor expect t
hey must be allowed. | 522 // the first place, update our state so we neither request them nor expect t
hey must be allowed. |
531 if (m_resourceLoaderOptions.credentialsRequested == ClientDidNotRequestCrede
ntials) | 523 if (m_resourceLoaderOptions.credentialsRequested == ClientDidNotRequestCrede
ntials) |
532 m_forceDoNotAllowStoredCredentials = true; | 524 m_forceDoNotAllowStoredCredentials = true; |
533 | 525 |
534 // Save the referrer to use when following the redirect. | 526 // Save the referrer to use when following the redirect. |
535 m_didRedirect = true; | 527 m_didRedirect = true; |
536 m_referrerAfterRedirect = Referrer(request.httpReferrer(), request.getReferr
erPolicy()); | 528 m_referrerAfterRedirect = Referrer(request.httpReferrer(), request.getReferr
erPolicy()); |
537 | 529 |
| 530 ResourceRequest crossOriginRequest(request); |
| 531 |
538 // Remove any headers that may have been added by the network layer that cau
se access control to fail. | 532 // Remove any headers that may have been added by the network layer that cau
se access control to fail. |
539 request.clearHTTPReferrer(); | 533 crossOriginRequest.clearHTTPReferrer(); |
540 request.clearHTTPOrigin(); | 534 crossOriginRequest.clearHTTPOrigin(); |
541 request.clearHTTPUserAgent(); | 535 crossOriginRequest.clearHTTPUserAgent(); |
542 // Add any CORS simple request headers which we previously saved from the or
iginal request. | 536 // Add any CORS simple request headers which we previously saved from the or
iginal request. |
543 for (const auto& header : m_simpleRequestHeaders) | 537 for (const auto& header : m_simpleRequestHeaders) |
544 request.setHTTPHeaderField(header.key, header.value); | 538 crossOriginRequest.setHTTPHeaderField(header.key, header.value); |
545 makeCrossOriginAccessRequest(request); | 539 makeCrossOriginAccessRequest(crossOriginRequest); |
546 // |this| may be dead here. | 540 // |this| may be dead here. |
| 541 |
| 542 return true; |
547 } | 543 } |
548 | 544 |
549 void DocumentThreadableLoader::redirectBlocked() | 545 void DocumentThreadableLoader::redirectBlocked() |
550 { | 546 { |
551 m_checker.redirectBlocked(); | 547 m_checker.redirectBlocked(); |
552 | 548 |
553 // Tells the client that a redirect was received but not followed (for an un
known reason). | 549 // Tells the client that a redirect was received but not followed (for an un
known reason). |
554 ThreadableLoaderClient* client = m_client; | 550 ThreadableLoaderClient* client = m_client; |
555 clear(); | 551 clear(); |
556 client->didFailRedirectCheck(); | 552 client->didFailRedirectCheck(); |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
972 | 968 |
973 DEFINE_TRACE(DocumentThreadableLoader) | 969 DEFINE_TRACE(DocumentThreadableLoader) |
974 { | 970 { |
975 visitor->trace(m_resource); | 971 visitor->trace(m_resource); |
976 visitor->trace(m_document); | 972 visitor->trace(m_document); |
977 ThreadableLoader::trace(visitor); | 973 ThreadableLoader::trace(visitor); |
978 RawResourceClient::trace(visitor); | 974 RawResourceClient::trace(visitor); |
979 } | 975 } |
980 | 976 |
981 } // namespace blink | 977 } // namespace blink |
OLD | NEW |