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);
        }
    }
}
예제 #2
0
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);
    }
  }
}