| 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 |