| 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 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 m_crossOriginNonSimpleRequest(false), | 164 m_crossOriginNonSimpleRequest(false), |
| 165 m_isUsingDataConsumerHandle(false), | 165 m_isUsingDataConsumerHandle(false), |
| 166 m_async(blockingBehavior == LoadAsynchronously), | 166 m_async(blockingBehavior == LoadAsynchronously), |
| 167 m_requestContext(WebURLRequest::RequestContextUnspecified), | 167 m_requestContext(WebURLRequest::RequestContextUnspecified), |
| 168 m_timeoutTimer(this, &DocumentThreadableLoader::didTimeout), | 168 m_timeoutTimer(this, &DocumentThreadableLoader::didTimeout), |
| 169 m_requestStartedSeconds(0.0), | 169 m_requestStartedSeconds(0.0), |
| 170 m_corsRedirectLimit(m_options.crossOriginRequestPolicy == UseAccessControl | 170 m_corsRedirectLimit(m_options.crossOriginRequestPolicy == UseAccessControl |
| 171 ? kMaxCORSRedirects | 171 ? kMaxCORSRedirects |
| 172 : 0), | 172 : 0), |
| 173 m_redirectMode(WebURLRequest::FetchRedirectModeFollow), | 173 m_redirectMode(WebURLRequest::FetchRedirectModeFollow), |
| 174 m_didRedirect(false) { | 174 m_overrideReferrer(false) { |
| 175 DCHECK(client); | 175 DCHECK(client); |
| 176 } | 176 } |
| 177 | 177 |
| 178 void DocumentThreadableLoader::start(const ResourceRequest& request) { | 178 void DocumentThreadableLoader::start(const ResourceRequest& request) { |
| 179 // Setting an outgoing referer is only supported in the async code path. | 179 // Setting an outgoing referer is only supported in the async code path. |
| 180 DCHECK(m_async || request.httpReferrer().isEmpty()); | 180 DCHECK(m_async || request.httpReferrer().isEmpty()); |
| 181 | 181 |
| 182 m_sameOriginRequest = | 182 m_sameOriginRequest = |
| 183 getSecurityOrigin()->canRequestNoSuborigin(request.url()); | 183 getSecurityOrigin()->canRequestNoSuborigin(request.url()); |
| 184 m_requestContext = request.requestContext(); | 184 m_requestContext = request.requestContext(); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 loadRequest(request, m_resourceLoaderOptions); | 305 loadRequest(request, m_resourceLoaderOptions); |
| 306 return; | 306 return; |
| 307 } | 307 } |
| 308 | 308 |
| 309 DCHECK(m_options.crossOriginRequestPolicy == UseAccessControl || | 309 DCHECK(m_options.crossOriginRequestPolicy == UseAccessControl || |
| 310 request.isExternalRequest()); | 310 request.isExternalRequest()); |
| 311 | 311 |
| 312 makeCrossOriginAccessRequest(request); | 312 makeCrossOriginAccessRequest(request); |
| 313 } | 313 } |
| 314 | 314 |
| 315 void DocumentThreadableLoader::prepareCrossOriginRequest( |
| 316 ResourceRequest& request) { |
| 317 if (getSecurityOrigin()) |
| 318 request.setHTTPOrigin(getSecurityOrigin()); |
| 319 if (m_overrideReferrer) |
| 320 request.setHTTPReferrer(m_referrerAfterRedirect); |
| 321 } |
| 322 |
| 315 void DocumentThreadableLoader::makeCrossOriginAccessRequest( | 323 void DocumentThreadableLoader::makeCrossOriginAccessRequest( |
| 316 const ResourceRequest& request) { | 324 const ResourceRequest& request) { |
| 317 DCHECK(m_options.crossOriginRequestPolicy == UseAccessControl || | 325 DCHECK(m_options.crossOriginRequestPolicy == UseAccessControl || |
| 318 request.isExternalRequest()); | 326 request.isExternalRequest()); |
| 319 DCHECK(m_client); | 327 DCHECK(m_client); |
| 320 DCHECK(!resource()); | 328 DCHECK(!resource()); |
| 321 | 329 |
| 322 // Cross-origin requests are only allowed certain registered schemes. We would | 330 // Cross-origin requests are only allowed certain registered schemes. We would |
| 323 // catch this when checking response headers later, but there is no reason to | 331 // catch this when checking response headers later, but there is no reason to |
| 324 // send a request, preflighted or not, that's guaranteed to be denied. | 332 // send a request, preflighted or not, that's guaranteed to be denied. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 346 "Requests to internal network resources are not allowed " | 354 "Requests to internal network resources are not allowed " |
| 347 "from non-secure contexts (see https://goo.gl/Y0ZkNV). " | 355 "from non-secure contexts (see https://goo.gl/Y0ZkNV). " |
| 348 "This is an experimental restriction which is part of " | 356 "This is an experimental restriction which is part of " |
| 349 "'https://mikewest.github.io/cors-rfc1918/'.")); | 357 "'https://mikewest.github.io/cors-rfc1918/'.")); |
| 350 return; | 358 return; |
| 351 } | 359 } |
| 352 | 360 |
| 353 ResourceRequest crossOriginRequest(request); | 361 ResourceRequest crossOriginRequest(request); |
| 354 ResourceLoaderOptions crossOriginOptions(m_resourceLoaderOptions); | 362 ResourceLoaderOptions crossOriginOptions(m_resourceLoaderOptions); |
| 355 | 363 |
| 364 crossOriginRequest.removeCredentials(); |
| 365 |
| 366 crossOriginRequest.setAllowStoredCredentials(effectiveAllowCredentials() == |
| 367 AllowStoredCredentials); |
| 368 |
| 369 // We update the credentials mode according to effectiveAllowCredentials() |
| 370 // here for backward compatibility. But this is not correct. |
| 371 // FIXME: We should set it in the caller of DocumentThreadableLoader. |
| 372 crossOriginRequest.setFetchCredentialsMode( |
| 373 effectiveAllowCredentials() == AllowStoredCredentials |
| 374 ? WebURLRequest::FetchCredentialsModeInclude |
| 375 : WebURLRequest::FetchCredentialsModeOmit); |
| 376 |
| 356 // We use isSimpleOrForbiddenRequest() here since |request| may have been | 377 // We use isSimpleOrForbiddenRequest() here since |request| may have been |
| 357 // modified in the process of loading (not from the user's input). For | 378 // modified in the process of loading (not from the user's input). For |
| 358 // example, referrer. We need to accept them. For security, we must reject | 379 // example, referrer. We need to accept them. For security, we must reject |
| 359 // forbidden headers/methods at the point we accept user's input. Not here. | 380 // forbidden headers/methods at the point we accept user's input. Not here. |
| 360 if (!request.isExternalRequest() && | 381 if (!request.isExternalRequest() && |
| 361 ((m_options.preflightPolicy == ConsiderPreflight && | 382 ((m_options.preflightPolicy == ConsiderPreflight && |
| 362 FetchUtils::isSimpleOrForbiddenRequest(request.httpMethod(), | 383 FetchUtils::isSimpleOrForbiddenRequest(request.httpMethod(), |
| 363 request.httpHeaderFields())) || | 384 request.httpHeaderFields())) || |
| 364 m_options.preflightPolicy == PreventPreflight)) { | 385 m_options.preflightPolicy == PreventPreflight)) { |
| 365 updateRequestForAccessControl(crossOriginRequest, getSecurityOrigin(), | 386 prepareCrossOriginRequest(crossOriginRequest); |
| 366 effectiveAllowCredentials()); | |
| 367 // We update the credentials mode according to effectiveAllowCredentials() | |
| 368 // here for backward compatibility. But this is not correct. | |
| 369 // FIXME: We should set it in the caller of DocumentThreadableLoader. | |
| 370 crossOriginRequest.setFetchCredentialsMode( | |
| 371 effectiveAllowCredentials() == AllowStoredCredentials | |
| 372 ? WebURLRequest::FetchCredentialsModeInclude | |
| 373 : WebURLRequest::FetchCredentialsModeOmit); | |
| 374 if (m_didRedirect) { | |
| 375 crossOriginRequest.setHTTPReferrer(m_referrerAfterRedirect); | |
| 376 } | |
| 377 loadRequest(crossOriginRequest, crossOriginOptions); | 387 loadRequest(crossOriginRequest, crossOriginOptions); |
| 378 } else { | 388 } else { |
| 379 m_crossOriginNonSimpleRequest = true; | 389 m_crossOriginNonSimpleRequest = true; |
| 380 // Do not set the Origin header for preflight requests. | |
| 381 updateRequestForAccessControl(crossOriginRequest, 0, | |
| 382 effectiveAllowCredentials()); | |
| 383 // We update the credentials mode according to effectiveAllowCredentials() | |
| 384 // here for backward compatibility. But this is not correct. | |
| 385 // FIXME: We should set it in the caller of DocumentThreadableLoader. | |
| 386 crossOriginRequest.setFetchCredentialsMode( | |
| 387 effectiveAllowCredentials() == AllowStoredCredentials | |
| 388 ? WebURLRequest::FetchCredentialsModeInclude | |
| 389 : WebURLRequest::FetchCredentialsModeOmit); | |
| 390 m_actualRequest = crossOriginRequest; | |
| 391 m_actualOptions = crossOriginOptions; | |
| 392 | |
| 393 if (m_didRedirect) { | |
| 394 m_actualRequest.setHTTPReferrer(m_referrerAfterRedirect); | |
| 395 } | |
| 396 | 390 |
| 397 bool shouldForcePreflight = | 391 bool shouldForcePreflight = |
| 398 request.isExternalRequest() || | 392 request.isExternalRequest() || |
| 399 InspectorInstrumentation::shouldForceCORSPreflight(m_document); | 393 InspectorInstrumentation::shouldForceCORSPreflight(m_document); |
| 400 bool canSkipPreflight = | 394 bool canSkipPreflight = |
| 401 CrossOriginPreflightResultCache::shared().canSkipPreflight( | 395 CrossOriginPreflightResultCache::shared().canSkipPreflight( |
| 402 getSecurityOrigin()->toString(), m_actualRequest.url(), | 396 getSecurityOrigin()->toString(), crossOriginRequest.url(), |
| 403 effectiveAllowCredentials(), m_actualRequest.httpMethod(), | 397 effectiveAllowCredentials(), crossOriginRequest.httpMethod(), |
| 404 m_actualRequest.httpHeaderFields()); | 398 crossOriginRequest.httpHeaderFields()); |
| 405 if (canSkipPreflight && !shouldForcePreflight) { | 399 if (canSkipPreflight && !shouldForcePreflight) { |
| 406 loadActualRequest(); | 400 if (getSecurityOrigin()) |
| 401 crossOriginRequest.setHTTPOrigin(getSecurityOrigin()); |
| 402 if (m_overrideReferrer) |
| 403 crossOriginRequest.setHTTPReferrer(m_referrerAfterRedirect); |
| 404 |
| 405 prepareCrossOriginRequest(crossOriginRequest); |
| 406 loadRequest(crossOriginRequest, crossOriginOptions); |
| 407 } else { | 407 } else { |
| 408 ResourceRequest preflightRequest = createAccessControlPreflightRequest( | 408 ResourceRequest preflightRequest = createAccessControlPreflightRequest( |
| 409 m_actualRequest, getSecurityOrigin()); | 409 crossOriginRequest, getSecurityOrigin()); |
| 410 |
| 410 // Create a ResourceLoaderOptions for preflight. | 411 // Create a ResourceLoaderOptions for preflight. |
| 411 ResourceLoaderOptions preflightOptions = m_actualOptions; | 412 ResourceLoaderOptions preflightOptions = crossOriginOptions; |
| 412 preflightOptions.allowCredentials = DoNotAllowStoredCredentials; | 413 preflightOptions.allowCredentials = DoNotAllowStoredCredentials; |
| 414 |
| 415 m_actualRequest = crossOriginRequest; |
| 416 m_actualOptions = crossOriginOptions; |
| 417 |
| 418 prepareCrossOriginRequest(crossOriginRequest); |
| 413 loadRequest(preflightRequest, preflightOptions); | 419 loadRequest(preflightRequest, preflightOptions); |
| 414 } | 420 } |
| 415 } | 421 } |
| 416 } | 422 } |
| 417 | 423 |
| 418 DocumentThreadableLoader::~DocumentThreadableLoader() { | 424 DocumentThreadableLoader::~DocumentThreadableLoader() { |
| 419 CHECK(!m_client); | 425 CHECK(!m_client); |
| 420 DCHECK(!m_resource); | 426 DCHECK(!m_resource); |
| 421 } | 427 } |
| 422 | 428 |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 624 m_sameOriginRequest = false; | 630 m_sameOriginRequest = false; |
| 625 | 631 |
| 626 // Since the request is no longer same-origin, if the user didn't request | 632 // Since the request is no longer same-origin, if the user didn't request |
| 627 // credentials in the first place, update our state so we neither request them | 633 // credentials in the first place, update our state so we neither request them |
| 628 // nor expect they must be allowed. | 634 // nor expect they must be allowed. |
| 629 if (m_resourceLoaderOptions.credentialsRequested == | 635 if (m_resourceLoaderOptions.credentialsRequested == |
| 630 ClientDidNotRequestCredentials) | 636 ClientDidNotRequestCredentials) |
| 631 m_forceDoNotAllowStoredCredentials = true; | 637 m_forceDoNotAllowStoredCredentials = true; |
| 632 | 638 |
| 633 // Save the referrer to use when following the redirect. | 639 // Save the referrer to use when following the redirect. |
| 634 m_didRedirect = true; | 640 m_overrideReferrer = true; |
| 635 m_referrerAfterRedirect = | 641 m_referrerAfterRedirect = |
| 636 Referrer(request.httpReferrer(), request.getReferrerPolicy()); | 642 Referrer(request.httpReferrer(), request.getReferrerPolicy()); |
| 637 | 643 |
| 638 ResourceRequest crossOriginRequest(request); | 644 ResourceRequest crossOriginRequest(request); |
| 639 | 645 |
| 640 // Remove any headers that may have been added by the network layer that cause | 646 // Remove any headers that may have been added by the network layer that cause |
| 641 // access control to fail. | 647 // access control to fail. |
| 642 crossOriginRequest.clearHTTPReferrer(); | 648 crossOriginRequest.clearHTTPReferrer(); |
| 643 crossOriginRequest.clearHTTPOrigin(); | 649 crossOriginRequest.clearHTTPOrigin(); |
| 644 crossOriginRequest.clearHTTPUserAgent(); | 650 crossOriginRequest.clearHTTPUserAgent(); |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 928 m_fallbackRequestForServiceWorker = ResourceRequest(); | 934 m_fallbackRequestForServiceWorker = ResourceRequest(); |
| 929 dispatchInitialRequest(fallbackRequest); | 935 dispatchInitialRequest(fallbackRequest); |
| 930 } | 936 } |
| 931 | 937 |
| 932 void DocumentThreadableLoader::loadActualRequest() { | 938 void DocumentThreadableLoader::loadActualRequest() { |
| 933 ResourceRequest actualRequest = m_actualRequest; | 939 ResourceRequest actualRequest = m_actualRequest; |
| 934 ResourceLoaderOptions actualOptions = m_actualOptions; | 940 ResourceLoaderOptions actualOptions = m_actualOptions; |
| 935 m_actualRequest = ResourceRequest(); | 941 m_actualRequest = ResourceRequest(); |
| 936 m_actualOptions = ResourceLoaderOptions(); | 942 m_actualOptions = ResourceLoaderOptions(); |
| 937 | 943 |
| 938 actualRequest.setHTTPOrigin(getSecurityOrigin()); | |
| 939 | |
| 940 clearResource(); | 944 clearResource(); |
| 941 | 945 |
| 942 // Explicitly set the SkipServiceWorker flag here. Even if the page was not | 946 // Explicitly set the SkipServiceWorker flag here. Even if the page was not |
| 943 // controlled by a SW when the preflight request was sent, a new SW may be | 947 // controlled by a SW when the preflight request was sent, a new SW may be |
| 944 // controlling the page now by calling clients.claim(). We should not send | 948 // controlling the page now by calling clients.claim(). We should not send |
| 945 // the actual request to the SW. https://crbug.com/604583 | 949 // the actual request to the SW. https://crbug.com/604583 |
| 946 actualRequest.setSkipServiceWorker(WebURLRequest::SkipServiceWorker::All); | 950 actualRequest.setSkipServiceWorker(WebURLRequest::SkipServiceWorker::All); |
| 947 | 951 |
| 952 prepareCrossOriginRequest(actualRequest); |
| 948 loadRequest(actualRequest, actualOptions); | 953 loadRequest(actualRequest, actualOptions); |
| 949 } | 954 } |
| 950 | 955 |
| 951 void DocumentThreadableLoader::handlePreflightFailure( | 956 void DocumentThreadableLoader::handlePreflightFailure( |
| 952 const String& url, | 957 const String& url, |
| 953 const String& errorDescription) { | 958 const String& errorDescription) { |
| 954 ResourceError error(errorDomainBlinkInternal, 0, url, errorDescription); | 959 ResourceError error(errorDomainBlinkInternal, 0, url, errorDescription); |
| 955 | 960 |
| 956 // Prevent handleSuccessfulFinish() from bypassing access check. | 961 // Prevent handleSuccessfulFinish() from bypassing access check. |
| 957 m_actualRequest = ResourceRequest(); | 962 m_actualRequest = ResourceRequest(); |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1131 } | 1136 } |
| 1132 | 1137 |
| 1133 DEFINE_TRACE(DocumentThreadableLoader) { | 1138 DEFINE_TRACE(DocumentThreadableLoader) { |
| 1134 visitor->trace(m_resource); | 1139 visitor->trace(m_resource); |
| 1135 visitor->trace(m_document); | 1140 visitor->trace(m_document); |
| 1136 ThreadableLoader::trace(visitor); | 1141 ThreadableLoader::trace(visitor); |
| 1137 RawResourceClient::trace(visitor); | 1142 RawResourceClient::trace(visitor); |
| 1138 } | 1143 } |
| 1139 | 1144 |
| 1140 } // namespace blink | 1145 } // namespace blink |
| OLD | NEW |