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, ResourceRequ
est& 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 // Keep |this| alive even if the client release a reference in | 435 // Keep |this| alive even if the client release a reference in |
438 // responseReceived(). | 436 // responseReceived(). |
439 WeakPtr<DocumentThreadableLoader> self(m_weakFactory.createWeakPtr()); | 437 WeakPtr<DocumentThreadableLoader> self(m_weakFactory.createWeakPtr()); |
440 | 438 |
441 // We use |m_redirectMode| to check the original redirect mode. | 439 // We use |m_redirectMode| to check the original redirect mode. |
442 // |request| is a new request for redirect. So we don't set the redirect | 440 // |request| is a new request for redirect. So we don't set the redirect |
443 // mode of it in WebURLLoaderImpl::Context::OnReceivedRedirect(). | 441 // mode of it in WebURLLoaderImpl::Context::OnReceivedRedirect(). |
444 DCHECK(request.useStreamOnResponse()); | 442 DCHECK(request.useStreamOnResponse()); |
445 // There is no need to read the body of redirect response because there | 443 // There is no need to read the body of redirect response because there |
446 // is no way to read the body of opaque-redirect filtered response's | 444 // is no way to read the body of opaque-redirect filtered response's |
447 // internal response. | 445 // internal response. |
448 // TODO(horo): If we support any API which expose the internal body, we | 446 // TODO(horo): If we support any API which expose the internal body, we |
449 // will have to read the body. And also HTTPCache changes will be needed | 447 // will have to read the body. And also HTTPCache changes will be needed |
450 // because it doesn't store the body of redirect responses. | 448 // because it doesn't store the body of redirect responses. |
451 responseReceived(resource, redirectResponse, wrapUnique(new EmptyDataHan
dle())); | 449 responseReceived(resource, redirectResponse, wrapUnique(new EmptyDataHan
dle())); |
452 | 450 |
453 if (!self) { | 451 if (!self) { |
454 request = ResourceRequest(); | 452 return false; |
455 return; | |
456 } | 453 } |
457 | 454 |
458 if (m_client) { | 455 if (m_client) { |
459 DCHECK(m_actualRequest.isNull()); | 456 DCHECK(m_actualRequest.isNull()); |
460 notifyFinished(resource); | 457 notifyFinished(resource); |
461 } | 458 } |
462 | 459 |
463 request = ResourceRequest(); | 460 return false; |
464 | |
465 return; | |
466 } | 461 } |
467 | 462 |
468 if (m_redirectMode == WebURLRequest::FetchRedirectModeError) { | 463 if (m_redirectMode == WebURLRequest::FetchRedirectModeError) { |
469 ThreadableLoaderClient* client = m_client; | 464 ThreadableLoaderClient* client = m_client; |
470 clear(); | 465 clear(); |
471 client->didFailRedirectCheck(); | 466 client->didFailRedirectCheck(); |
472 | 467 |
473 request = ResourceRequest(); | 468 return false; |
474 | |
475 return; | |
476 } | 469 } |
477 | 470 |
478 // Allow same origin requests to continue after allowing clients to audit th
e redirect. | 471 // Allow same origin requests to continue after allowing clients to audit th
e redirect. |
479 if (isAllowedRedirect(request.url())) { | 472 if (isAllowedRedirect(request.url())) { |
480 if (m_client->isDocumentThreadableLoaderClient()) | 473 if (m_client->isDocumentThreadableLoaderClient()) |
481 static_cast<DocumentThreadableLoaderClient*>(m_client)->willFollowRe
direct(request, redirectResponse); | 474 return static_cast<DocumentThreadableLoaderClient*>(m_client)->willF
ollowRedirect(request, redirectResponse); |
482 return; | 475 return true; |
483 } | 476 } |
484 | 477 |
485 if (m_corsRedirectLimit <= 0) { | 478 if (m_corsRedirectLimit <= 0) { |
486 ThreadableLoaderClient* client = m_client; | 479 ThreadableLoaderClient* client = m_client; |
487 clear(); | 480 clear(); |
488 client->didFailRedirectCheck(); | 481 client->didFailRedirectCheck(); |
489 request = ResourceRequest(); | 482 return false; |
490 return; | |
491 } | 483 } |
492 | 484 |
493 --m_corsRedirectLimit; | 485 --m_corsRedirectLimit; |
494 | 486 |
495 InspectorInstrumentation::didReceiveCORSRedirectResponse(document().frame(),
resource->identifier(), document().frame()->loader().documentLoader(), redirect
Response, resource); | 487 InspectorInstrumentation::didReceiveCORSRedirectResponse(document().frame(),
resource->identifier(), document().frame()->loader().documentLoader(), redirect
Response, resource); |
496 | 488 |
497 bool allowRedirect = false; | 489 bool allowRedirect = false; |
498 String accessControlErrorDescription; | 490 String accessControlErrorDescription; |
499 | 491 |
500 if (m_crossOriginNonSimpleRequest) { | 492 if (m_crossOriginNonSimpleRequest) { |
501 // Non-simple cross origin requests (both preflight and actual one) are | 493 // Non-simple cross origin requests (both preflight and actual one) are |
502 // not allowed to follow redirect. | 494 // not allowed to follow redirect. |
503 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 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."; |
504 } else if (!CrossOriginAccessControl::isLegalRedirectLocation(request.url(),
accessControlErrorDescription)) { | 496 } else if (!CrossOriginAccessControl::isLegalRedirectLocation(request.url(),
accessControlErrorDescription)) { |
505 accessControlErrorDescription = "Redirect from '" + redirectResponse.url
().getString() + "' has been blocked by CORS policy: " + accessControlErrorDescr
iption; | 497 accessControlErrorDescription = "Redirect from '" + redirectResponse.url
().getString() + "' has been blocked by CORS policy: " + accessControlErrorDescr
iption; |
506 } else if (!m_sameOriginRequest && !passesAccessControlCheck(redirectRespons
e, effectiveAllowCredentials(), getSecurityOrigin(), accessControlErrorDescripti
on, m_requestContext)) { | 498 } else if (!m_sameOriginRequest && !passesAccessControlCheck(redirectRespons
e, effectiveAllowCredentials(), getSecurityOrigin(), accessControlErrorDescripti
on, m_requestContext)) { |
507 // The redirect response must pass the access control check if the | 499 // The redirect response must pass the access control check if the |
508 // original request was not same-origin. | 500 // original request was not same-origin. |
509 accessControlErrorDescription = "Redirect from '" + redirectResponse.url
().getString()+ "' to '" + request.url().getString() + "' has been blocked by CO
RS policy: " + accessControlErrorDescription; | 501 accessControlErrorDescription = "Redirect from '" + redirectResponse.url
().getString()+ "' to '" + request.url().getString() + "' has been blocked by CO
RS policy: " + accessControlErrorDescription; |
510 } else { | 502 } else { |
511 allowRedirect = true; | 503 allowRedirect = true; |
512 } | 504 } |
513 | 505 |
514 if (!allowRedirect) { | 506 if (!allowRedirect) { |
515 ThreadableLoaderClient* client = m_client; | 507 ThreadableLoaderClient* client = m_client; |
516 clear(); | 508 clear(); |
517 client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal
, 0, redirectResponse.url().getString(), accessControlErrorDescription)); | 509 client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal
, 0, redirectResponse.url().getString(), accessControlErrorDescription)); |
518 request = ResourceRequest(); | 510 return false; |
519 return; | |
520 } | 511 } |
521 | 512 |
522 // FIXME: consider combining this with CORS redirect handling performed by | 513 // FIXME: consider combining this with CORS redirect handling performed by |
523 // CrossOriginAccessControl::handleRedirect(). | 514 // CrossOriginAccessControl::handleRedirect(). |
524 clearResource(); | 515 clearResource(); |
525 | 516 |
526 // If the original request wasn't same-origin, then if the request URL origi
n is not same origin with the original URL origin, | 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, |
527 // set the source origin to a globally unique identifier. (If the original r
equest was same-origin, the origin of the new request | 518 // set the source origin to a globally unique identifier. (If the original r
equest was same-origin, the origin of the new request |
528 // should be the original URL origin.) | 519 // should be the original URL origin.) |
529 if (!m_sameOriginRequest) { | 520 if (!m_sameOriginRequest) { |
(...skipping 16 matching lines...) Expand all Loading... |
546 | 537 |
547 // Remove any headers that may have been added by the network layer that cau
se access control to fail. | 538 // Remove any headers that may have been added by the network layer that cau
se access control to fail. |
548 request.clearHTTPReferrer(); | 539 request.clearHTTPReferrer(); |
549 request.clearHTTPOrigin(); | 540 request.clearHTTPOrigin(); |
550 request.clearHTTPUserAgent(); | 541 request.clearHTTPUserAgent(); |
551 // Add any CORS simple request headers which we previously saved from the or
iginal request. | 542 // Add any CORS simple request headers which we previously saved from the or
iginal request. |
552 for (const auto& header : m_simpleRequestHeaders) | 543 for (const auto& header : m_simpleRequestHeaders) |
553 request.setHTTPHeaderField(header.key, header.value); | 544 request.setHTTPHeaderField(header.key, header.value); |
554 makeCrossOriginAccessRequest(request); | 545 makeCrossOriginAccessRequest(request); |
555 // |this| may be dead here. | 546 // |this| may be dead here. |
| 547 |
| 548 return true; |
556 } | 549 } |
557 | 550 |
558 void DocumentThreadableLoader::redirectBlocked() | 551 void DocumentThreadableLoader::redirectBlocked() |
559 { | 552 { |
560 m_checker.redirectBlocked(); | 553 m_checker.redirectBlocked(); |
561 | 554 |
562 // Tells the client that a redirect was received but not followed (for an un
known reason). | 555 // Tells the client that a redirect was received but not followed (for an un
known reason). |
563 ThreadableLoaderClient* client = m_client; | 556 ThreadableLoaderClient* client = m_client; |
564 clear(); | 557 clear(); |
565 client->didFailRedirectCheck(); | 558 client->didFailRedirectCheck(); |
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
987 | 980 |
988 DEFINE_TRACE(DocumentThreadableLoader) | 981 DEFINE_TRACE(DocumentThreadableLoader) |
989 { | 982 { |
990 visitor->trace(m_resource); | 983 visitor->trace(m_resource); |
991 visitor->trace(m_document); | 984 visitor->trace(m_document); |
992 ThreadableLoader::trace(visitor); | 985 ThreadableLoader::trace(visitor); |
993 RawResourceClient::trace(visitor); | 986 RawResourceClient::trace(visitor); |
994 } | 987 } |
995 | 988 |
996 } // namespace blink | 989 } // namespace blink |
OLD | NEW |