void DocumentThreadableLoader::redirectReceived(CachedResource* resource, ResourceRequest& request, const ResourceResponse& redirectResponse) { ASSERT(m_client); ASSERT_UNUSED(resource, resource == m_resource); RefPtr<DocumentThreadableLoader> protect(this); // Allow same origin requests to continue after allowing clients to audit the redirect. if (isAllowedRedirect(request.url())) { if (m_client->isDocumentThreadableLoaderClient()) static_cast<DocumentThreadableLoaderClient*>(m_client)->willSendRequest(request, redirectResponse); return; } // When using access control, only simple cross origin requests are allowed to redirect. The new request URL must have a supported // scheme and not contain the userinfo production. In addition, the redirect response must pass the access control check. if (m_options.crossOriginRequestPolicy == UseAccessControl) { bool allowRedirect = false; if (m_simpleRequest) { String accessControlErrorDescription; allowRedirect = SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(request.url().protocol()) && request.url().user().isEmpty() && request.url().pass().isEmpty() && passesAccessControlCheck(redirectResponse, m_options.allowCredentials, securityOrigin(), accessControlErrorDescription); } if (allowRedirect) { if (m_resource) clearResource(); RefPtr<SecurityOrigin> originalOrigin = SecurityOrigin::createFromString(redirectResponse.url()); RefPtr<SecurityOrigin> requestOrigin = SecurityOrigin::createFromString(request.url()); // If the request URL origin is not same origin with the original URL origin, set source origin to a globally unique identifier. if (!originalOrigin->isSameSchemeHostPort(requestOrigin.get())) m_options.securityOrigin = SecurityOrigin::createUnique(); // Force any subsequent requests to use these checks. m_sameOriginRequest = false; // Remove any headers that may have been added by the network layer that cause access control to fail. request.clearHTTPContentType(); request.clearHTTPReferrer(); request.clearHTTPOrigin(); request.clearHTTPUserAgent(); request.clearHTTPAccept(); makeCrossOriginAccessRequest(request); return; } } m_client->didFailRedirectCheck(); request = ResourceRequest(); }
void DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequest& request, const ResourceResponse& redirectResponse) { ASSERT(m_client); ASSERT_UNUSED(resource, resource == this->resource()); RefPtr<DocumentThreadableLoader> protect(this); if (!isAllowedByPolicy(request.url())) { m_client->didFailRedirectCheck(); request = ResourceRequest(); return; } // Allow same origin requests to continue after allowing clients to audit the redirect. if (isAllowedRedirect(request.url())) { if (m_client->isDocumentThreadableLoaderClient()) static_cast<DocumentThreadableLoaderClient*>(m_client)->willSendRequest(request, redirectResponse); return; } // When using access control, only simple cross origin requests are allowed to redirect. The new request URL must have a supported // scheme and not contain the userinfo production. In addition, the redirect response must pass the access control check if the // original request was not same-origin. if (m_options.crossOriginRequestPolicy == UseAccessControl) { InspectorInstrumentation::didReceiveCORSRedirectResponse(m_document->frame(), resource->identifier(), m_document->frame()->loader().documentLoader(), redirectResponse, 0); bool allowRedirect = false; String accessControlErrorDescription; if (m_simpleRequest) { allowRedirect = CrossOriginAccessControl::isLegalRedirectLocation(request.url(), accessControlErrorDescription) && (m_sameOriginRequest || passesAccessControlCheck(redirectResponse, m_options.allowCredentials, securityOrigin(), accessControlErrorDescription)); } else { accessControlErrorDescription = "The request was redirected to '"+ request.url().string() + "', which is disallowed for cross-origin requests that require preflight."; } if (allowRedirect) { // FIXME: consider combining this with CORS redirect handling performed by // CrossOriginAccessControl::handleRedirect(). clearResource(); RefPtr<SecurityOrigin> originalOrigin = SecurityOrigin::create(redirectResponse.url()); RefPtr<SecurityOrigin> requestOrigin = SecurityOrigin::create(request.url()); // If the original request wasn't same-origin, then if the request URL origin is not same origin with the original URL origin, // set the source origin to a globally unique identifier. (If the original request was same-origin, the origin of the new request // should be the original URL origin.) if (!m_sameOriginRequest && !originalOrigin->isSameSchemeHostPort(requestOrigin.get())) m_options.securityOrigin = SecurityOrigin::createUnique(); // Force any subsequent requests to use these checks. m_sameOriginRequest = false; // Since the request is no longer same-origin, if the user didn't request credentials in // the first place, update our state so we neither request them nor expect they must be allowed. if (m_options.credentialsRequested == ClientDidNotRequestCredentials) m_options.allowCredentials = DoNotAllowStoredCredentials; // Remove any headers that may have been added by the network layer that cause access control to fail. request.clearHTTPContentType(); request.clearHTTPReferrer(); request.clearHTTPOrigin(); request.clearHTTPUserAgent(); request.clearHTTPAccept(); makeCrossOriginAccessRequest(request); return; } ResourceError error(errorDomainBlinkInternal, 0, redirectResponse.url().string(), accessControlErrorDescription); m_client->didFailAccessControlCheck(error); } else { m_client->didFailRedirectCheck(); } request = ResourceRequest(); }