Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp

Issue 2420603003: Make DocumentThreadableLoader's cross origin logic clearer in terms of layering (Closed)
Patch Set: Rebase Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/core/loader/DocumentThreadableLoader.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/loader/DocumentThreadableLoader.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698