void DocumentThreadableLoader::makeCrossOriginAccessRequest(const ResourceRequest& request) { ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); ASSERT(m_client); ASSERT(!resource()); // Cross-origin requests are only allowed certain registered schemes. // We would catch this when checking response headers later, but there // is no reason to send a request, preflighted or not, that's guaranteed // to be denied. if (!SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(request.url().protocol())) { ThreadableLoaderClient* client = m_client; clear(); client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal, 0, request.url().string(), "Cross origin requests are only supported for protocol schemes: " + SchemeRegistry::listOfCORSEnabledURLSchemes() + ".")); // |this| may be dead here in async mode. return; } // We use isSimpleOrForbiddenRequest() here since |request| may have been // modified in the process of loading (not from the user's input). For // example, referrer. We need to accept them. For security, we must reject // forbidden headers/methods at the point we accept user's input. Not here. if ((m_options.preflightPolicy == ConsiderPreflight && FetchUtils::isSimpleOrForbiddenRequest(request.httpMethod(), request.httpHeaderFields())) || m_options.preflightPolicy == PreventPreflight) { ResourceRequest crossOriginRequest(request); ResourceLoaderOptions crossOriginOptions(m_resourceLoaderOptions); updateRequestForAccessControl(crossOriginRequest, securityOrigin(), effectiveAllowCredentials()); // We update the credentials mode according to effectiveAllowCredentials() here for backward compatibility. But this is not correct. // FIXME: We should set it in the caller of DocumentThreadableLoader. crossOriginRequest.setFetchCredentialsMode(effectiveAllowCredentials() == AllowStoredCredentials ? WebURLRequest::FetchCredentialsModeInclude : WebURLRequest::FetchCredentialsModeOmit); loadRequest(crossOriginRequest, crossOriginOptions); } else { m_crossOriginNonSimpleRequest = true; ResourceRequest crossOriginRequest(request); ResourceLoaderOptions crossOriginOptions(m_resourceLoaderOptions); // Do not set the Origin header for preflight requests. updateRequestForAccessControl(crossOriginRequest, 0, effectiveAllowCredentials()); // We update the credentials mode according to effectiveAllowCredentials() here for backward compatibility. But this is not correct. // FIXME: We should set it in the caller of DocumentThreadableLoader. crossOriginRequest.setFetchCredentialsMode(effectiveAllowCredentials() == AllowStoredCredentials ? WebURLRequest::FetchCredentialsModeInclude : WebURLRequest::FetchCredentialsModeOmit); m_actualRequest = crossOriginRequest; m_actualOptions = crossOriginOptions; bool shouldForcePreflight = InspectorInstrumentation::shouldForceCORSPreflight(m_document); bool canSkipPreflight = CrossOriginPreflightResultCache::shared().canSkipPreflight(securityOrigin()->toString(), m_actualRequest.url(), effectiveAllowCredentials(), m_actualRequest.httpMethod(), m_actualRequest.httpHeaderFields()); if (canSkipPreflight && !shouldForcePreflight) { loadActualRequest(); } else { ResourceRequest preflightRequest = createAccessControlPreflightRequest(m_actualRequest, securityOrigin()); // Create a ResourceLoaderOptions for preflight. ResourceLoaderOptions preflightOptions = m_actualOptions; preflightOptions.allowCredentials = DoNotAllowStoredCredentials; loadRequest(preflightRequest, preflightOptions); } } }
void DocumentThreadableLoader::makeCrossOriginAccessRequest( const ResourceRequest& request) { DCHECK(m_options.crossOriginRequestPolicy == UseAccessControl || request.isExternalRequest()); DCHECK(m_client); DCHECK(!resource()); // Cross-origin requests are only allowed certain registered schemes. We would // catch this when checking response headers later, but there is no reason to // send a request, preflighted or not, that's guaranteed to be denied. if (!SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled( request.url().protocol())) { InspectorInstrumentation:: documentThreadableLoaderFailedToStartLoadingForClient(m_document, m_client); ThreadableLoaderClient* client = m_client; clear(); client->didFailAccessControlCheck(ResourceError( errorDomainBlinkInternal, 0, request.url().getString(), "Cross origin requests are only supported for protocol schemes: " + SchemeRegistry::listOfCORSEnabledURLSchemes() + ".")); return; } // Non-secure origins may not make "external requests": // https://mikewest.github.io/cors-rfc1918/#integration-fetch if (!document().isSecureContext() && request.isExternalRequest()) { ThreadableLoaderClient* client = m_client; clear(); client->didFailAccessControlCheck( ResourceError(errorDomainBlinkInternal, 0, request.url().getString(), "Requests to internal network resources are not allowed " "from non-secure contexts (see https://goo.gl/Y0ZkNV). " "This is an experimental restriction which is part of " "'https://mikewest.github.io/cors-rfc1918/'.")); return; } ResourceRequest crossOriginRequest(request); ResourceLoaderOptions crossOriginOptions(m_resourceLoaderOptions); crossOriginRequest.removeCredentials(); crossOriginRequest.setAllowStoredCredentials(effectiveAllowCredentials() == AllowStoredCredentials); // We update the credentials mode according to effectiveAllowCredentials() // here for backward compatibility. But this is not correct. // FIXME: We should set it in the caller of DocumentThreadableLoader. crossOriginRequest.setFetchCredentialsMode( effectiveAllowCredentials() == AllowStoredCredentials ? WebURLRequest::FetchCredentialsModeInclude : WebURLRequest::FetchCredentialsModeOmit); // We use isSimpleOrForbiddenRequest() here since |request| may have been // modified in the process of loading (not from the user's input). For // example, referrer. We need to accept them. For security, we must reject // forbidden headers/methods at the point we accept user's input. Not here. if (!request.isExternalRequest() && ((m_options.preflightPolicy == ConsiderPreflight && FetchUtils::isSimpleOrForbiddenRequest(request.httpMethod(), request.httpHeaderFields())) || m_options.preflightPolicy == PreventPreflight)) { prepareCrossOriginRequest(crossOriginRequest); loadRequest(crossOriginRequest, crossOriginOptions); } else { bool shouldForcePreflight = request.isExternalRequest() || InspectorInstrumentation::shouldForceCORSPreflight(m_document); bool canSkipPreflight = CrossOriginPreflightResultCache::shared().canSkipPreflight( getSecurityOrigin()->toString(), crossOriginRequest.url(), effectiveAllowCredentials(), crossOriginRequest.httpMethod(), crossOriginRequest.httpHeaderFields()); if (canSkipPreflight && !shouldForcePreflight) { if (getSecurityOrigin()) crossOriginRequest.setHTTPOrigin(getSecurityOrigin()); if (m_overrideReferrer) crossOriginRequest.setHTTPReferrer(m_referrerAfterRedirect); prepareCrossOriginRequest(crossOriginRequest); loadRequest(crossOriginRequest, crossOriginOptions); } else { ResourceRequest preflightRequest = createAccessControlPreflightRequest( crossOriginRequest, getSecurityOrigin()); // Create a ResourceLoaderOptions for preflight. ResourceLoaderOptions preflightOptions = crossOriginOptions; preflightOptions.allowCredentials = DoNotAllowStoredCredentials; m_actualRequest = crossOriginRequest; m_actualOptions = crossOriginOptions; prepareCrossOriginRequest(crossOriginRequest); loadRequest(preflightRequest, preflightOptions); } } }