| 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 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 | 119 |
| 120 // Max number of CORS redirects handled in DocumentThreadableLoader. | 120 // Max number of CORS redirects handled in DocumentThreadableLoader. |
| 121 // Same number as net/url_request/url_request.cc, and | 121 // Same number as net/url_request/url_request.cc, and |
| 122 // same number as https://fetch.spec.whatwg.org/#concept-http-fetch, Step 4. | 122 // same number as https://fetch.spec.whatwg.org/#concept-http-fetch, Step 4. |
| 123 // FIXME: currently the number of redirects is counted and limited here and in | 123 // FIXME: currently the number of redirects is counted and limited here and in |
| 124 // net/url_request/url_request.cc separately. | 124 // net/url_request/url_request.cc separately. |
| 125 static const int kMaxCORSRedirects = 20; | 125 static const int kMaxCORSRedirects = 20; |
| 126 | 126 |
| 127 void DocumentThreadableLoader::loadResourceSynchronously(Document& document, con
st ResourceRequest& request, ThreadableLoaderClient& client, const ThreadableLoa
derOptions& options, const ResourceLoaderOptions& resourceLoaderOptions) | 127 void DocumentThreadableLoader::loadResourceSynchronously(Document& document, con
st ResourceRequest& request, ThreadableLoaderClient& client, const ThreadableLoa
derOptions& options, const ResourceLoaderOptions& resourceLoaderOptions) |
| 128 { | 128 { |
| 129 // The loader will be deleted as soon as this function exits. | 129 (new DocumentThreadableLoader(document, &client, LoadSynchronously, options,
resourceLoaderOptions))->start(request); |
| 130 std::unique_ptr<DocumentThreadableLoader> loader = wrapUnique(new DocumentTh
readableLoader(document, &client, LoadSynchronously, options, resourceLoaderOpti
ons)); | |
| 131 loader->start(request); | |
| 132 } | 130 } |
| 133 | 131 |
| 134 std::unique_ptr<DocumentThreadableLoader> DocumentThreadableLoader::create(Docum
ent& document, ThreadableLoaderClient* client, const ThreadableLoaderOptions& op
tions, const ResourceLoaderOptions& resourceLoaderOptions) | 132 DocumentThreadableLoader* DocumentThreadableLoader::create(Document& document, T
hreadableLoaderClient* client, const ThreadableLoaderOptions& options, const Res
ourceLoaderOptions& resourceLoaderOptions) |
| 135 { | 133 { |
| 136 return wrapUnique(new DocumentThreadableLoader(document, client, LoadAsynchr
onously, options, resourceLoaderOptions)); | 134 return new DocumentThreadableLoader(document, client, LoadAsynchronously, op
tions, resourceLoaderOptions); |
| 137 } | 135 } |
| 138 | 136 |
| 139 DocumentThreadableLoader::DocumentThreadableLoader(Document& document, Threadabl
eLoaderClient* client, BlockingBehavior blockingBehavior, const ThreadableLoader
Options& options, const ResourceLoaderOptions& resourceLoaderOptions) | 137 DocumentThreadableLoader::DocumentThreadableLoader(Document& document, Threadabl
eLoaderClient* client, BlockingBehavior blockingBehavior, const ThreadableLoader
Options& options, const ResourceLoaderOptions& resourceLoaderOptions) |
| 140 : m_client(client) | 138 : m_client(client) |
| 141 , m_document(&document) | 139 , m_document(&document) |
| 142 , m_options(options) | 140 , m_options(options) |
| 143 , m_resourceLoaderOptions(resourceLoaderOptions) | 141 , m_resourceLoaderOptions(resourceLoaderOptions) |
| 144 , m_forceDoNotAllowStoredCredentials(false) | 142 , m_forceDoNotAllowStoredCredentials(false) |
| 145 , m_securityOrigin(m_resourceLoaderOptions.securityOrigin) | 143 , m_securityOrigin(m_resourceLoaderOptions.securityOrigin) |
| 146 , m_sameOriginRequest(false) | 144 , m_sameOriginRequest(false) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 165 | 163 |
| 166 m_sameOriginRequest = getSecurityOrigin()->canRequestNoSuborigin(request.url
()); | 164 m_sameOriginRequest = getSecurityOrigin()->canRequestNoSuborigin(request.url
()); |
| 167 m_requestContext = request.requestContext(); | 165 m_requestContext = request.requestContext(); |
| 168 m_redirectMode = request.fetchRedirectMode(); | 166 m_redirectMode = request.fetchRedirectMode(); |
| 169 | 167 |
| 170 if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == DenyCrossO
riginRequests) { | 168 if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == DenyCrossO
riginRequests) { |
| 171 InspectorInstrumentation::documentThreadableLoaderFailedToStartLoadingFo
rClient(m_document, m_client); | 169 InspectorInstrumentation::documentThreadableLoaderFailedToStartLoadingFo
rClient(m_document, m_client); |
| 172 ThreadableLoaderClient* client = m_client; | 170 ThreadableLoaderClient* client = m_client; |
| 173 clear(); | 171 clear(); |
| 174 client->didFail(ResourceError(errorDomainBlinkInternal, 0, request.url()
.getString(), "Cross origin requests are not supported.")); | 172 client->didFail(ResourceError(errorDomainBlinkInternal, 0, request.url()
.getString(), "Cross origin requests are not supported.")); |
| 175 // |this| may be dead here. | |
| 176 return; | 173 return; |
| 177 } | 174 } |
| 178 | 175 |
| 179 m_requestStartedSeconds = monotonicallyIncreasingTime(); | 176 m_requestStartedSeconds = monotonicallyIncreasingTime(); |
| 180 | 177 |
| 181 // Save any CORS simple headers on the request here. If this request redirec
ts cross-origin, we cancel the old request | 178 // Save any CORS simple headers on the request here. If this request redirec
ts cross-origin, we cancel the old request |
| 182 // create a new one, and copy these headers. | 179 // create a new one, and copy these headers. |
| 183 const HTTPHeaderMap& headerMap = request.httpHeaderFields(); | 180 const HTTPHeaderMap& headerMap = request.httpHeaderFields(); |
| 184 for (const auto& header : headerMap) { | 181 for (const auto& header : headerMap) { |
| 185 if (FetchUtils::isSimpleHeader(header.key, header.value)) { | 182 if (FetchUtils::isSimpleHeader(header.key, header.value)) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 // m_fallbackRequestForServiceWorker is used when a regular controll
ing | 243 // m_fallbackRequestForServiceWorker is used when a regular controll
ing |
| 247 // service worker doesn't handle a cross origin request. When this h
appens | 244 // service worker doesn't handle a cross origin request. When this h
appens |
| 248 // we still want to give foreign fetch a chance to handle the reques
t, so | 245 // we still want to give foreign fetch a chance to handle the reques
t, so |
| 249 // only skip the controlling service worker for the fallback request
. | 246 // only skip the controlling service worker for the fallback request
. |
| 250 // This is currently safe because of http://crbug.com/604084 the | 247 // This is currently safe because of http://crbug.com/604084 the |
| 251 // wasFallbackRequiredByServiceWorker flag is never set when foreign
fetch | 248 // wasFallbackRequiredByServiceWorker flag is never set when foreign
fetch |
| 252 // handled a request. | 249 // handled a request. |
| 253 m_fallbackRequestForServiceWorker.setSkipServiceWorker(WebURLRequest
::SkipServiceWorker::Controlling); | 250 m_fallbackRequestForServiceWorker.setSkipServiceWorker(WebURLRequest
::SkipServiceWorker::Controlling); |
| 254 } | 251 } |
| 255 loadRequest(newRequest, m_resourceLoaderOptions); | 252 loadRequest(newRequest, m_resourceLoaderOptions); |
| 256 // |this| may be dead here. | |
| 257 return; | 253 return; |
| 258 } | 254 } |
| 259 | 255 |
| 260 dispatchInitialRequest(newRequest); | 256 dispatchInitialRequest(newRequest); |
| 261 // |this| may be dead here in async mode. | |
| 262 } | 257 } |
| 263 | 258 |
| 264 void DocumentThreadableLoader::dispatchInitialRequest(const ResourceRequest& req
uest) | 259 void DocumentThreadableLoader::dispatchInitialRequest(const ResourceRequest& req
uest) |
| 265 { | 260 { |
| 266 if (!request.isExternalRequest() && (m_sameOriginRequest || m_options.crossO
riginRequestPolicy == AllowCrossOriginRequests)) { | 261 if (!request.isExternalRequest() && (m_sameOriginRequest || m_options.crossO
riginRequestPolicy == AllowCrossOriginRequests)) { |
| 267 loadRequest(request, m_resourceLoaderOptions); | 262 loadRequest(request, m_resourceLoaderOptions); |
| 268 // |this| may be dead here in async mode. | |
| 269 return; | 263 return; |
| 270 } | 264 } |
| 271 | 265 |
| 272 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl || request.isE
xternalRequest()); | 266 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl || request.isE
xternalRequest()); |
| 273 | 267 |
| 274 makeCrossOriginAccessRequest(request); | 268 makeCrossOriginAccessRequest(request); |
| 275 // |this| may be dead here in async mode. | |
| 276 } | 269 } |
| 277 | 270 |
| 278 void DocumentThreadableLoader::makeCrossOriginAccessRequest(const ResourceReques
t& request) | 271 void DocumentThreadableLoader::makeCrossOriginAccessRequest(const ResourceReques
t& request) |
| 279 { | 272 { |
| 280 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl || request.isE
xternalRequest()); | 273 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl || request.isE
xternalRequest()); |
| 281 ASSERT(m_client); | 274 ASSERT(m_client); |
| 282 ASSERT(!resource()); | 275 ASSERT(!resource()); |
| 283 | 276 |
| 284 // Cross-origin requests are only allowed certain registered schemes. | 277 // Cross-origin requests are only allowed certain registered schemes. |
| 285 // We would catch this when checking response headers later, but there | 278 // We would catch this when checking response headers later, but there |
| 286 // is no reason to send a request, preflighted or not, that's guaranteed | 279 // is no reason to send a request, preflighted or not, that's guaranteed |
| 287 // to be denied. | 280 // to be denied. |
| 288 if (!SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(request.url().protoco
l())) { | 281 if (!SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(request.url().protoco
l())) { |
| 289 InspectorInstrumentation::documentThreadableLoaderFailedToStartLoadingFo
rClient(m_document, m_client); | 282 InspectorInstrumentation::documentThreadableLoaderFailedToStartLoadingFo
rClient(m_document, m_client); |
| 290 ThreadableLoaderClient* client = m_client; | 283 ThreadableLoaderClient* client = m_client; |
| 291 clear(); | 284 clear(); |
| 292 client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal
, 0, request.url().getString(), "Cross origin requests are only supported for pr
otocol schemes: " + SchemeRegistry::listOfCORSEnabledURLSchemes() + ".")); | 285 client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal
, 0, request.url().getString(), "Cross origin requests are only supported for pr
otocol schemes: " + SchemeRegistry::listOfCORSEnabledURLSchemes() + ".")); |
| 293 // |this| may be dead here in async mode. | |
| 294 return; | 286 return; |
| 295 } | 287 } |
| 296 | 288 |
| 297 // Non-secure origins may not make "external requests": https://mikewest.git
hub.io/cors-rfc1918/#integration-fetch | 289 // Non-secure origins may not make "external requests": https://mikewest.git
hub.io/cors-rfc1918/#integration-fetch |
| 298 if (!document().isSecureContext() && request.isExternalRequest()) { | 290 if (!document().isSecureContext() && request.isExternalRequest()) { |
| 299 ThreadableLoaderClient* client = m_client; | 291 ThreadableLoaderClient* client = m_client; |
| 300 clear(); | 292 clear(); |
| 301 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 experim
ental restriction which is part of 'https://mikewest.github.io/cors-rfc1918/'.")
); | 293 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 experim
ental restriction which is part of 'https://mikewest.github.io/cors-rfc1918/'.")
); |
| 302 // |this| may be dead here in async mode. | |
| 303 return; | 294 return; |
| 304 } | 295 } |
| 305 | 296 |
| 306 ResourceRequest crossOriginRequest(request); | 297 ResourceRequest crossOriginRequest(request); |
| 307 ResourceLoaderOptions crossOriginOptions(m_resourceLoaderOptions); | 298 ResourceLoaderOptions crossOriginOptions(m_resourceLoaderOptions); |
| 308 | 299 |
| 309 // We use isSimpleOrForbiddenRequest() here since |request| may have been | 300 // We use isSimpleOrForbiddenRequest() here since |request| may have been |
| 310 // modified in the process of loading (not from the user's input). For | 301 // modified in the process of loading (not from the user's input). For |
| 311 // example, referrer. We need to accept them. For security, we must reject | 302 // example, referrer. We need to accept them. For security, we must reject |
| 312 // forbidden headers/methods at the point we accept user's input. Not here. | 303 // forbidden headers/methods at the point we accept user's input. Not here. |
| 313 if (!request.isExternalRequest() && ((m_options.preflightPolicy == ConsiderP
reflight && FetchUtils::isSimpleOrForbiddenRequest(request.httpMethod(), request
.httpHeaderFields())) || m_options.preflightPolicy == PreventPreflight)) { | 304 if (!request.isExternalRequest() && ((m_options.preflightPolicy == ConsiderP
reflight && FetchUtils::isSimpleOrForbiddenRequest(request.httpMethod(), request
.httpHeaderFields())) || m_options.preflightPolicy == PreventPreflight)) { |
| 314 updateRequestForAccessControl(crossOriginRequest, getSecurityOrigin(), e
ffectiveAllowCredentials()); | 305 updateRequestForAccessControl(crossOriginRequest, getSecurityOrigin(), e
ffectiveAllowCredentials()); |
| 315 // We update the credentials mode according to effectiveAllowCredentials
() here for backward compatibility. But this is not correct. | 306 // We update the credentials mode according to effectiveAllowCredentials
() here for backward compatibility. But this is not correct. |
| 316 // FIXME: We should set it in the caller of DocumentThreadableLoader. | 307 // FIXME: We should set it in the caller of DocumentThreadableLoader. |
| 317 crossOriginRequest.setFetchCredentialsMode(effectiveAllowCredentials() =
= AllowStoredCredentials ? WebURLRequest::FetchCredentialsModeInclude : WebURLRe
quest::FetchCredentialsModeOmit); | 308 crossOriginRequest.setFetchCredentialsMode(effectiveAllowCredentials() =
= AllowStoredCredentials ? WebURLRequest::FetchCredentialsModeInclude : WebURLRe
quest::FetchCredentialsModeOmit); |
| 318 if (m_didRedirect) { | 309 if (m_didRedirect) { |
| 319 crossOriginRequest.setHTTPReferrer(SecurityPolicy::generateReferrer(
m_referrerAfterRedirect.referrerPolicy, crossOriginRequest.url(), m_referrerAfte
rRedirect.referrer)); | 310 crossOriginRequest.setHTTPReferrer(SecurityPolicy::generateReferrer(
m_referrerAfterRedirect.referrerPolicy, crossOriginRequest.url(), m_referrerAfte
rRedirect.referrer)); |
| 320 } | 311 } |
| 321 loadRequest(crossOriginRequest, crossOriginOptions); | 312 loadRequest(crossOriginRequest, crossOriginOptions); |
| 322 // |this| may be dead here in async mode. | |
| 323 } else { | 313 } else { |
| 324 m_crossOriginNonSimpleRequest = true; | 314 m_crossOriginNonSimpleRequest = true; |
| 325 // Do not set the Origin header for preflight requests. | 315 // Do not set the Origin header for preflight requests. |
| 326 updateRequestForAccessControl(crossOriginRequest, 0, effectiveAllowCrede
ntials()); | 316 updateRequestForAccessControl(crossOriginRequest, 0, effectiveAllowCrede
ntials()); |
| 327 // We update the credentials mode according to effectiveAllowCredentials
() here for backward compatibility. But this is not correct. | 317 // We update the credentials mode according to effectiveAllowCredentials
() here for backward compatibility. But this is not correct. |
| 328 // FIXME: We should set it in the caller of DocumentThreadableLoader. | 318 // FIXME: We should set it in the caller of DocumentThreadableLoader. |
| 329 crossOriginRequest.setFetchCredentialsMode(effectiveAllowCredentials() =
= AllowStoredCredentials ? WebURLRequest::FetchCredentialsModeInclude : WebURLRe
quest::FetchCredentialsModeOmit); | 319 crossOriginRequest.setFetchCredentialsMode(effectiveAllowCredentials() =
= AllowStoredCredentials ? WebURLRequest::FetchCredentialsModeInclude : WebURLRe
quest::FetchCredentialsModeOmit); |
| 330 m_actualRequest = crossOriginRequest; | 320 m_actualRequest = crossOriginRequest; |
| 331 m_actualOptions = crossOriginOptions; | 321 m_actualOptions = crossOriginOptions; |
| 332 | 322 |
| 333 if (m_didRedirect) { | 323 if (m_didRedirect) { |
| 334 m_actualRequest.setHTTPReferrer(SecurityPolicy::generateReferrer(m_r
eferrerAfterRedirect.referrerPolicy, m_actualRequest.url(), m_referrerAfterRedir
ect.referrer)); | 324 m_actualRequest.setHTTPReferrer(SecurityPolicy::generateReferrer(m_r
eferrerAfterRedirect.referrerPolicy, m_actualRequest.url(), m_referrerAfterRedir
ect.referrer)); |
| 335 } | 325 } |
| 336 | 326 |
| 337 bool shouldForcePreflight = request.isExternalRequest() || InspectorInst
rumentation::shouldForceCORSPreflight(m_document); | 327 bool shouldForcePreflight = request.isExternalRequest() || InspectorInst
rumentation::shouldForceCORSPreflight(m_document); |
| 338 bool canSkipPreflight = CrossOriginPreflightResultCache::shared().canSki
pPreflight(getSecurityOrigin()->toString(), m_actualRequest.url(), effectiveAllo
wCredentials(), m_actualRequest.httpMethod(), m_actualRequest.httpHeaderFields()
); | 328 bool canSkipPreflight = CrossOriginPreflightResultCache::shared().canSki
pPreflight(getSecurityOrigin()->toString(), m_actualRequest.url(), effectiveAllo
wCredentials(), m_actualRequest.httpMethod(), m_actualRequest.httpHeaderFields()
); |
| 339 if (canSkipPreflight && !shouldForcePreflight) { | 329 if (canSkipPreflight && !shouldForcePreflight) { |
| 340 loadActualRequest(); | 330 loadActualRequest(); |
| 341 // |this| may be dead here in async mode. | |
| 342 } else { | 331 } else { |
| 343 ResourceRequest preflightRequest = createAccessControlPreflightReque
st(m_actualRequest, getSecurityOrigin()); | 332 ResourceRequest preflightRequest = createAccessControlPreflightReque
st(m_actualRequest, getSecurityOrigin()); |
| 344 // Create a ResourceLoaderOptions for preflight. | 333 // Create a ResourceLoaderOptions for preflight. |
| 345 ResourceLoaderOptions preflightOptions = m_actualOptions; | 334 ResourceLoaderOptions preflightOptions = m_actualOptions; |
| 346 preflightOptions.allowCredentials = DoNotAllowStoredCredentials; | 335 preflightOptions.allowCredentials = DoNotAllowStoredCredentials; |
| 347 loadRequest(preflightRequest, preflightOptions); | 336 loadRequest(preflightRequest, preflightOptions); |
| 348 // |this| may be dead here in async mode. | |
| 349 } | 337 } |
| 350 } | 338 } |
| 351 } | 339 } |
| 352 | 340 |
| 353 DocumentThreadableLoader::~DocumentThreadableLoader() | 341 DocumentThreadableLoader::~DocumentThreadableLoader() |
| 354 { | 342 { |
| 355 CHECK(!m_client); | 343 CHECK(!m_client); |
| 356 DCHECK(!m_resource); | 344 DCHECK(!m_resource); |
| 357 } | 345 } |
| 358 | 346 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 378 double elapsedTime = monotonicallyIncreasingTime() - m_requestStartedSec
onds; | 366 double elapsedTime = monotonicallyIncreasingTime() - m_requestStartedSec
onds; |
| 379 double nextFire = timeoutMilliseconds / 1000.0; | 367 double nextFire = timeoutMilliseconds / 1000.0; |
| 380 double resolvedTime = std::max(nextFire - elapsedTime, 0.0); | 368 double resolvedTime = std::max(nextFire - elapsedTime, 0.0); |
| 381 m_timeoutTimer.startOneShot(resolvedTime, BLINK_FROM_HERE); | 369 m_timeoutTimer.startOneShot(resolvedTime, BLINK_FROM_HERE); |
| 382 } | 370 } |
| 383 } | 371 } |
| 384 | 372 |
| 385 void DocumentThreadableLoader::cancel() | 373 void DocumentThreadableLoader::cancel() |
| 386 { | 374 { |
| 387 cancelWithError(ResourceError()); | 375 cancelWithError(ResourceError()); |
| 388 // |this| may be dead here. | |
| 389 } | 376 } |
| 390 | 377 |
| 391 void DocumentThreadableLoader::cancelWithError(const ResourceError& error) | 378 void DocumentThreadableLoader::cancelWithError(const ResourceError& error) |
| 392 { | 379 { |
| 393 // Cancel can re-enter and m_resource might be null here as a result. | 380 // Cancel can re-enter and m_resource might be null here as a result. |
| 394 if (!m_client || !resource()) { | 381 if (!m_client || !resource()) { |
| 395 clear(); | 382 clear(); |
| 396 return; | 383 return; |
| 397 } | 384 } |
| 398 | 385 |
| 399 ResourceError errorForCallback = error; | 386 ResourceError errorForCallback = error; |
| 400 if (errorForCallback.isNull()) { | 387 if (errorForCallback.isNull()) { |
| 401 // FIXME: This error is sent to the client in didFail(), so it should no
t be an internal one. Use FrameLoaderClient::cancelledError() instead. | 388 // FIXME: This error is sent to the client in didFail(), so it should no
t be an internal one. Use FrameLoaderClient::cancelledError() instead. |
| 402 errorForCallback = ResourceError(errorDomainBlinkInternal, 0, resource()
->url().getString(), "Load cancelled"); | 389 errorForCallback = ResourceError(errorDomainBlinkInternal, 0, resource()
->url().getString(), "Load cancelled"); |
| 403 errorForCallback.setIsCancellation(true); | 390 errorForCallback.setIsCancellation(true); |
| 404 } | 391 } |
| 405 | 392 |
| 406 ThreadableLoaderClient* client = m_client; | 393 ThreadableLoaderClient* client = m_client; |
| 407 clear(); | 394 clear(); |
| 408 client->didFail(errorForCallback); | 395 client->didFail(errorForCallback); |
| 409 // |this| may be dead here in async mode. | |
| 410 } | 396 } |
| 411 | 397 |
| 412 void DocumentThreadableLoader::setDefersLoading(bool value) | 398 void DocumentThreadableLoader::setDefersLoading(bool value) |
| 413 { | 399 { |
| 414 if (resource()) | 400 if (resource()) |
| 415 resource()->setDefersLoading(value); | 401 resource()->setDefersLoading(value); |
| 416 } | 402 } |
| 417 | 403 |
| 418 void DocumentThreadableLoader::clear() | 404 void DocumentThreadableLoader::clear() |
| 419 { | 405 { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 432 void DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequ
est& request, const ResourceResponse& redirectResponse) | 418 void DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequ
est& request, const ResourceResponse& redirectResponse) |
| 433 { | 419 { |
| 434 ASSERT(m_client); | 420 ASSERT(m_client); |
| 435 ASSERT_UNUSED(resource, resource == this->resource()); | 421 ASSERT_UNUSED(resource, resource == this->resource()); |
| 436 ASSERT(m_async); | 422 ASSERT(m_async); |
| 437 | 423 |
| 438 if (!m_actualRequest.isNull()) { | 424 if (!m_actualRequest.isNull()) { |
| 439 reportResponseReceived(resource->identifier(), redirectResponse); | 425 reportResponseReceived(resource->identifier(), redirectResponse); |
| 440 | 426 |
| 441 handlePreflightFailure(redirectResponse.url().getString(), "Response for
preflight is invalid (redirect)"); | 427 handlePreflightFailure(redirectResponse.url().getString(), "Response for
preflight is invalid (redirect)"); |
| 442 // |this| may be dead here. | |
| 443 | 428 |
| 444 request = ResourceRequest(); | 429 request = ResourceRequest(); |
| 445 | 430 |
| 446 return; | 431 return; |
| 447 } | 432 } |
| 448 | 433 |
| 449 if (m_redirectMode == WebURLRequest::FetchRedirectModeManual) { | 434 if (m_redirectMode == WebURLRequest::FetchRedirectModeManual) { |
| 450 // Keep |this| alive even if the client release a reference in | 435 // Keep |this| alive even if the client release a reference in |
| 451 // responseReceived(). | 436 // responseReceived(). |
| 452 WeakPtr<DocumentThreadableLoader> self(m_weakFactory.createWeakPtr()); | 437 WeakPtr<DocumentThreadableLoader> self(m_weakFactory.createWeakPtr()); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 475 | 460 |
| 476 request = ResourceRequest(); | 461 request = ResourceRequest(); |
| 477 | 462 |
| 478 return; | 463 return; |
| 479 } | 464 } |
| 480 | 465 |
| 481 if (m_redirectMode == WebURLRequest::FetchRedirectModeError) { | 466 if (m_redirectMode == WebURLRequest::FetchRedirectModeError) { |
| 482 ThreadableLoaderClient* client = m_client; | 467 ThreadableLoaderClient* client = m_client; |
| 483 clear(); | 468 clear(); |
| 484 client->didFailRedirectCheck(); | 469 client->didFailRedirectCheck(); |
| 485 // |this| may be dead here. | |
| 486 | 470 |
| 487 request = ResourceRequest(); | 471 request = ResourceRequest(); |
| 488 | 472 |
| 489 return; | 473 return; |
| 490 } | 474 } |
| 491 | 475 |
| 492 // Allow same origin requests to continue after allowing clients to audit th
e redirect. | 476 // Allow same origin requests to continue after allowing clients to audit th
e redirect. |
| 493 if (isAllowedRedirect(request.url())) { | 477 if (isAllowedRedirect(request.url())) { |
| 494 if (m_client->isDocumentThreadableLoaderClient()) | 478 if (m_client->isDocumentThreadableLoaderClient()) |
| 495 static_cast<DocumentThreadableLoaderClient*>(m_client)->willFollowRe
direct(request, redirectResponse); | 479 static_cast<DocumentThreadableLoaderClient*>(m_client)->willFollowRe
direct(request, redirectResponse); |
| 496 return; | 480 return; |
| 497 } | 481 } |
| 498 | 482 |
| 499 if (m_corsRedirectLimit <= 0) { | 483 if (m_corsRedirectLimit <= 0) { |
| 500 ThreadableLoaderClient* client = m_client; | 484 ThreadableLoaderClient* client = m_client; |
| 501 clear(); | 485 clear(); |
| 502 client->didFailRedirectCheck(); | 486 client->didFailRedirectCheck(); |
| 503 // |this| may be dead here. | |
| 504 | |
| 505 request = ResourceRequest(); | 487 request = ResourceRequest(); |
| 506 | |
| 507 return; | 488 return; |
| 508 } | 489 } |
| 509 | 490 |
| 510 --m_corsRedirectLimit; | 491 --m_corsRedirectLimit; |
| 511 | 492 |
| 512 InspectorInstrumentation::didReceiveCORSRedirectResponse(document().frame(),
resource->identifier(), document().frame()->loader().documentLoader(), redirect
Response, resource); | 493 InspectorInstrumentation::didReceiveCORSRedirectResponse(document().frame(),
resource->identifier(), document().frame()->loader().documentLoader(), redirect
Response, resource); |
| 513 | 494 |
| 514 bool allowRedirect = false; | 495 bool allowRedirect = false; |
| 515 String accessControlErrorDescription; | 496 String accessControlErrorDescription; |
| 516 | 497 |
| 517 if (m_crossOriginNonSimpleRequest) { | 498 if (m_crossOriginNonSimpleRequest) { |
| 518 // Non-simple cross origin requests (both preflight and actual one) are | 499 // Non-simple cross origin requests (both preflight and actual one) are |
| 519 // not allowed to follow redirect. | 500 // not allowed to follow redirect. |
| 520 accessControlErrorDescription = "Redirect from '" + redirectResponse.url
().getString()+ "' to '" + request.url().getString() + "' has been blocked by CO
RS policy: Request requires preflight, which is disallowed to follow cross-origi
n redirect."; | 501 accessControlErrorDescription = "Redirect from '" + redirectResponse.url
().getString()+ "' to '" + request.url().getString() + "' has been blocked by CO
RS policy: Request requires preflight, which is disallowed to follow cross-origi
n redirect."; |
| 521 } else if (!CrossOriginAccessControl::isLegalRedirectLocation(request.url(),
accessControlErrorDescription)) { | 502 } else if (!CrossOriginAccessControl::isLegalRedirectLocation(request.url(),
accessControlErrorDescription)) { |
| 522 accessControlErrorDescription = "Redirect from '" + redirectResponse.url
().getString() + "' has been blocked by CORS policy: " + accessControlErrorDescr
iption; | 503 accessControlErrorDescription = "Redirect from '" + redirectResponse.url
().getString() + "' has been blocked by CORS policy: " + accessControlErrorDescr
iption; |
| 523 } else if (!m_sameOriginRequest && !passesAccessControlCheck(redirectRespons
e, effectiveAllowCredentials(), getSecurityOrigin(), accessControlErrorDescripti
on, m_requestContext)) { | 504 } else if (!m_sameOriginRequest && !passesAccessControlCheck(redirectRespons
e, effectiveAllowCredentials(), getSecurityOrigin(), accessControlErrorDescripti
on, m_requestContext)) { |
| 524 // The redirect response must pass the access control check if the | 505 // The redirect response must pass the access control check if the |
| 525 // original request was not same-origin. | 506 // original request was not same-origin. |
| 526 accessControlErrorDescription = "Redirect from '" + redirectResponse.url
().getString()+ "' to '" + request.url().getString() + "' has been blocked by CO
RS policy: " + accessControlErrorDescription; | 507 accessControlErrorDescription = "Redirect from '" + redirectResponse.url
().getString()+ "' to '" + request.url().getString() + "' has been blocked by CO
RS policy: " + accessControlErrorDescription; |
| 527 } else { | 508 } else { |
| 528 allowRedirect = true; | 509 allowRedirect = true; |
| 529 } | 510 } |
| 530 | 511 |
| 531 if (!allowRedirect) { | 512 if (!allowRedirect) { |
| 532 ThreadableLoaderClient* client = m_client; | 513 ThreadableLoaderClient* client = m_client; |
| 533 clear(); | 514 clear(); |
| 534 client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal
, 0, redirectResponse.url().getString(), accessControlErrorDescription)); | 515 client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal
, 0, redirectResponse.url().getString(), accessControlErrorDescription)); |
| 535 // |this| may be dead here. | |
| 536 | |
| 537 request = ResourceRequest(); | 516 request = ResourceRequest(); |
| 538 | |
| 539 return; | 517 return; |
| 540 } | 518 } |
| 541 | 519 |
| 542 // FIXME: consider combining this with CORS redirect handling performed by | 520 // FIXME: consider combining this with CORS redirect handling performed by |
| 543 // CrossOriginAccessControl::handleRedirect(). | 521 // CrossOriginAccessControl::handleRedirect(). |
| 544 clearResource(); | 522 clearResource(); |
| 545 | 523 |
| 546 // If the original request wasn't same-origin, then if the request URL origi
n is not same origin with the original URL origin, | 524 // If the original request wasn't same-origin, then if the request URL origi
n is not same origin with the original URL origin, |
| 547 // set the source origin to a globally unique identifier. (If the original r
equest was same-origin, the origin of the new request | 525 // set the source origin to a globally unique identifier. (If the original r
equest was same-origin, the origin of the new request |
| 548 // should be the original URL origin.) | 526 // should be the original URL origin.) |
| (...skipping 25 matching lines...) Expand all Loading... |
| 574 makeCrossOriginAccessRequest(request); | 552 makeCrossOriginAccessRequest(request); |
| 575 // |this| may be dead here. | 553 // |this| may be dead here. |
| 576 } | 554 } |
| 577 | 555 |
| 578 void DocumentThreadableLoader::redirectBlocked() | 556 void DocumentThreadableLoader::redirectBlocked() |
| 579 { | 557 { |
| 580 // Tells the client that a redirect was received but not followed (for an un
known reason). | 558 // Tells the client that a redirect was received but not followed (for an un
known reason). |
| 581 ThreadableLoaderClient* client = m_client; | 559 ThreadableLoaderClient* client = m_client; |
| 582 clear(); | 560 clear(); |
| 583 client->didFailRedirectCheck(); | 561 client->didFailRedirectCheck(); |
| 584 // |this| may be dead here | |
| 585 } | 562 } |
| 586 | 563 |
| 587 void DocumentThreadableLoader::dataSent(Resource* resource, unsigned long long b
ytesSent, unsigned long long totalBytesToBeSent) | 564 void DocumentThreadableLoader::dataSent(Resource* resource, unsigned long long b
ytesSent, unsigned long long totalBytesToBeSent) |
| 588 { | 565 { |
| 589 ASSERT(m_client); | 566 ASSERT(m_client); |
| 590 ASSERT_UNUSED(resource, resource == this->resource()); | 567 ASSERT_UNUSED(resource, resource == this->resource()); |
| 591 ASSERT(m_async); | 568 ASSERT(m_async); |
| 592 | 569 |
| 593 m_client->didSendData(bytesSent, totalBytesToBeSent); | 570 m_client->didSendData(bytesSent, totalBytesToBeSent); |
| 594 // |this| may be dead here. | |
| 595 } | 571 } |
| 596 | 572 |
| 597 void DocumentThreadableLoader::dataDownloaded(Resource* resource, int dataLength
) | 573 void DocumentThreadableLoader::dataDownloaded(Resource* resource, int dataLength
) |
| 598 { | 574 { |
| 599 ASSERT(m_client); | 575 ASSERT(m_client); |
| 600 ASSERT_UNUSED(resource, resource == this->resource()); | 576 ASSERT_UNUSED(resource, resource == this->resource()); |
| 601 ASSERT(m_actualRequest.isNull()); | 577 ASSERT(m_actualRequest.isNull()); |
| 602 ASSERT(m_async); | 578 ASSERT(m_async); |
| 603 | 579 |
| 604 m_client->didDownloadData(dataLength); | 580 m_client->didDownloadData(dataLength); |
| 605 // |this| may be dead here. | |
| 606 } | 581 } |
| 607 | 582 |
| 608 void DocumentThreadableLoader::didReceiveResourceTiming(Resource* resource, cons
t ResourceTimingInfo& info) | 583 void DocumentThreadableLoader::didReceiveResourceTiming(Resource* resource, cons
t ResourceTimingInfo& info) |
| 609 { | 584 { |
| 610 ASSERT(m_client); | 585 ASSERT(m_client); |
| 611 ASSERT_UNUSED(resource, resource == this->resource()); | 586 ASSERT_UNUSED(resource, resource == this->resource()); |
| 612 ASSERT(m_async); | 587 ASSERT(m_async); |
| 613 | 588 |
| 614 m_client->didReceiveResourceTiming(info); | 589 m_client->didReceiveResourceTiming(info); |
| 615 // |this| may be dead here. | |
| 616 } | 590 } |
| 617 | 591 |
| 618 void DocumentThreadableLoader::responseReceived(Resource* resource, const Resour
ceResponse& response, std::unique_ptr<WebDataConsumerHandle> handle) | 592 void DocumentThreadableLoader::responseReceived(Resource* resource, const Resour
ceResponse& response, std::unique_ptr<WebDataConsumerHandle> handle) |
| 619 { | 593 { |
| 620 ASSERT_UNUSED(resource, resource == this->resource()); | 594 ASSERT_UNUSED(resource, resource == this->resource()); |
| 621 ASSERT(m_async); | 595 ASSERT(m_async); |
| 622 | 596 |
| 623 if (handle) | 597 if (handle) |
| 624 m_isUsingDataConsumerHandle = true; | 598 m_isUsingDataConsumerHandle = true; |
| 625 | 599 |
| 626 handleResponse(resource->identifier(), response, std::move(handle)); | 600 handleResponse(resource->identifier(), response, std::move(handle)); |
| 627 // |this| may be dead here. | |
| 628 } | 601 } |
| 629 | 602 |
| 630 void DocumentThreadableLoader::handlePreflightResponse(const ResourceResponse& r
esponse) | 603 void DocumentThreadableLoader::handlePreflightResponse(const ResourceResponse& r
esponse) |
| 631 { | 604 { |
| 632 String accessControlErrorDescription; | 605 String accessControlErrorDescription; |
| 633 | 606 |
| 634 if (!passesAccessControlCheck(response, effectiveAllowCredentials(), getSecu
rityOrigin(), accessControlErrorDescription, m_requestContext)) { | 607 if (!passesAccessControlCheck(response, effectiveAllowCredentials(), getSecu
rityOrigin(), accessControlErrorDescription, m_requestContext)) { |
| 635 handlePreflightFailure(response.url().getString(), "Response to prefligh
t request doesn't pass access control check: " + accessControlErrorDescription); | 608 handlePreflightFailure(response.url().getString(), "Response to prefligh
t request doesn't pass access control check: " + accessControlErrorDescription); |
| 636 // |this| may be dead here in async mode. | |
| 637 return; | 609 return; |
| 638 } | 610 } |
| 639 | 611 |
| 640 if (!passesPreflightStatusCheck(response, accessControlErrorDescription)) { | 612 if (!passesPreflightStatusCheck(response, accessControlErrorDescription)) { |
| 641 handlePreflightFailure(response.url().getString(), accessControlErrorDes
cription); | 613 handlePreflightFailure(response.url().getString(), accessControlErrorDes
cription); |
| 642 // |this| may be dead here in async mode. | |
| 643 return; | 614 return; |
| 644 } | 615 } |
| 645 | 616 |
| 646 if (m_actualRequest.isExternalRequest() && !passesExternalPreflightCheck(res
ponse, accessControlErrorDescription)) { | 617 if (m_actualRequest.isExternalRequest() && !passesExternalPreflightCheck(res
ponse, accessControlErrorDescription)) { |
| 647 handlePreflightFailure(response.url().getString(), accessControlErrorDes
cription); | 618 handlePreflightFailure(response.url().getString(), accessControlErrorDes
cription); |
| 648 // |this| may be dead here in async mode. | |
| 649 return; | 619 return; |
| 650 } | 620 } |
| 651 | 621 |
| 652 std::unique_ptr<CrossOriginPreflightResultCacheItem> preflightResult = wrapU
nique(new CrossOriginPreflightResultCacheItem(effectiveAllowCredentials())); | 622 std::unique_ptr<CrossOriginPreflightResultCacheItem> preflightResult = wrapU
nique(new CrossOriginPreflightResultCacheItem(effectiveAllowCredentials())); |
| 653 if (!preflightResult->parse(response, accessControlErrorDescription) | 623 if (!preflightResult->parse(response, accessControlErrorDescription) |
| 654 || !preflightResult->allowsCrossOriginMethod(m_actualRequest.httpMethod(
), accessControlErrorDescription) | 624 || !preflightResult->allowsCrossOriginMethod(m_actualRequest.httpMethod(
), accessControlErrorDescription) |
| 655 || !preflightResult->allowsCrossOriginHeaders(m_actualRequest.httpHeader
Fields(), accessControlErrorDescription)) { | 625 || !preflightResult->allowsCrossOriginHeaders(m_actualRequest.httpHeader
Fields(), accessControlErrorDescription)) { |
| 656 handlePreflightFailure(response.url().getString(), accessControlErrorDes
cription); | 626 handlePreflightFailure(response.url().getString(), accessControlErrorDes
cription); |
| 657 // |this| may be dead here in async mode. | |
| 658 return; | 627 return; |
| 659 } | 628 } |
| 660 | 629 |
| 661 CrossOriginPreflightResultCache::shared().appendEntry(getSecurityOrigin()->t
oString(), m_actualRequest.url(), std::move(preflightResult)); | 630 CrossOriginPreflightResultCache::shared().appendEntry(getSecurityOrigin()->t
oString(), m_actualRequest.url(), std::move(preflightResult)); |
| 662 } | 631 } |
| 663 | 632 |
| 664 void DocumentThreadableLoader::reportResponseReceived(unsigned long identifier,
const ResourceResponse& response) | 633 void DocumentThreadableLoader::reportResponseReceived(unsigned long identifier,
const ResourceResponse& response) |
| 665 { | 634 { |
| 666 LocalFrame* frame = document().frame(); | 635 LocalFrame* frame = document().frame(); |
| 667 // We are seeing crashes caused by nullptr (crbug.com/578849). But the frame | 636 // We are seeing crashes caused by nullptr (crbug.com/578849). But the frame |
| 668 // must be set here. TODO(horo): Find the root cause of the unset frame. | 637 // must be set here. TODO(horo): Find the root cause of the unset frame. |
| 669 ASSERT(frame); | 638 ASSERT(frame); |
| 670 if (!frame) | 639 if (!frame) |
| 671 return; | 640 return; |
| 672 DocumentLoader* loader = frame->loader().documentLoader(); | 641 DocumentLoader* loader = frame->loader().documentLoader(); |
| 673 TRACE_EVENT_INSTANT1("devtools.timeline", "ResourceReceiveResponse", TRACE_E
VENT_SCOPE_THREAD, "data", InspectorReceiveResponseEvent::data(identifier, frame
, response)); | 642 TRACE_EVENT_INSTANT1("devtools.timeline", "ResourceReceiveResponse", TRACE_E
VENT_SCOPE_THREAD, "data", InspectorReceiveResponseEvent::data(identifier, frame
, response)); |
| 674 InspectorInstrumentation::didReceiveResourceResponse(frame, identifier, load
er, response, resource()); | 643 InspectorInstrumentation::didReceiveResourceResponse(frame, identifier, load
er, response, resource()); |
| 675 frame->console().reportResourceResponseReceived(loader, identifier, response
); | 644 frame->console().reportResourceResponseReceived(loader, identifier, response
); |
| 676 } | 645 } |
| 677 | 646 |
| 678 void DocumentThreadableLoader::handleResponse(unsigned long identifier, const Re
sourceResponse& response, std::unique_ptr<WebDataConsumerHandle> handle) | 647 void DocumentThreadableLoader::handleResponse(unsigned long identifier, const Re
sourceResponse& response, std::unique_ptr<WebDataConsumerHandle> handle) |
| 679 { | 648 { |
| 680 ASSERT(m_client); | 649 ASSERT(m_client); |
| 681 | 650 |
| 682 if (!m_actualRequest.isNull()) { | 651 if (!m_actualRequest.isNull()) { |
| 683 reportResponseReceived(identifier, response); | 652 reportResponseReceived(identifier, response); |
| 684 handlePreflightResponse(response); | 653 handlePreflightResponse(response); |
| 685 // |this| may be dead here in async mode. | |
| 686 return; | 654 return; |
| 687 } | 655 } |
| 688 | 656 |
| 689 if (response.wasFetchedViaServiceWorker()) { | 657 if (response.wasFetchedViaServiceWorker()) { |
| 690 if (response.wasFallbackRequiredByServiceWorker()) { | 658 if (response.wasFallbackRequiredByServiceWorker()) { |
| 691 // At this point we must have m_fallbackRequestForServiceWorker. | 659 // At this point we must have m_fallbackRequestForServiceWorker. |
| 692 // (For SharedWorker the request won't be CORS or CORS-with-prefligh
t, | 660 // (For SharedWorker the request won't be CORS or CORS-with-prefligh
t, |
| 693 // therefore fallback-to-network is handled in the browser process | 661 // therefore fallback-to-network is handled in the browser process |
| 694 // when the ServiceWorker does not call respondWith().) | 662 // when the ServiceWorker does not call respondWith().) |
| 695 ASSERT(!m_fallbackRequestForServiceWorker.isNull()); | 663 ASSERT(!m_fallbackRequestForServiceWorker.isNull()); |
| 696 reportResponseReceived(identifier, response); | 664 reportResponseReceived(identifier, response); |
| 697 loadFallbackRequestForServiceWorker(); | 665 loadFallbackRequestForServiceWorker(); |
| 698 // |this| may be dead here in async mode. | |
| 699 return; | 666 return; |
| 700 } | 667 } |
| 701 m_fallbackRequestForServiceWorker = ResourceRequest(); | 668 m_fallbackRequestForServiceWorker = ResourceRequest(); |
| 702 m_client->didReceiveResponse(identifier, response, std::move(handle)); | 669 m_client->didReceiveResponse(identifier, response, std::move(handle)); |
| 703 return; | 670 return; |
| 704 } | 671 } |
| 705 | 672 |
| 706 // Even if the request met the conditions to get handled by a Service Worker | 673 // Even if the request met the conditions to get handled by a Service Worker |
| 707 // in the constructor of this class (and therefore | 674 // in the constructor of this class (and therefore |
| 708 // |m_fallbackRequestForServiceWorker| is set), the Service Worker may skip | 675 // |m_fallbackRequestForServiceWorker| is set), the Service Worker may skip |
| 709 // processing the request. Only if the request is same origin, the skipped | 676 // processing the request. Only if the request is same origin, the skipped |
| 710 // response may come here (wasFetchedViaServiceWorker() returns false) since | 677 // response may come here (wasFetchedViaServiceWorker() returns false) since |
| 711 // such a request doesn't have to go through the CORS algorithm by calling | 678 // such a request doesn't have to go through the CORS algorithm by calling |
| 712 // loadFallbackRequestForServiceWorker(). | 679 // loadFallbackRequestForServiceWorker(). |
| 713 // FIXME: We should use |m_sameOriginRequest| when we will support | 680 // FIXME: We should use |m_sameOriginRequest| when we will support |
| 714 // Suborigins (crbug.com/336894) for Service Worker. | 681 // Suborigins (crbug.com/336894) for Service Worker. |
| 715 ASSERT(m_fallbackRequestForServiceWorker.isNull() || getSecurityOrigin()->ca
nRequest(m_fallbackRequestForServiceWorker.url())); | 682 ASSERT(m_fallbackRequestForServiceWorker.isNull() || getSecurityOrigin()->ca
nRequest(m_fallbackRequestForServiceWorker.url())); |
| 716 m_fallbackRequestForServiceWorker = ResourceRequest(); | 683 m_fallbackRequestForServiceWorker = ResourceRequest(); |
| 717 | 684 |
| 718 if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == UseAccessC
ontrol) { | 685 if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == UseAccessC
ontrol) { |
| 719 String accessControlErrorDescription; | 686 String accessControlErrorDescription; |
| 720 if (!passesAccessControlCheck(response, effectiveAllowCredentials(), get
SecurityOrigin(), accessControlErrorDescription, m_requestContext)) { | 687 if (!passesAccessControlCheck(response, effectiveAllowCredentials(), get
SecurityOrigin(), accessControlErrorDescription, m_requestContext)) { |
| 721 reportResponseReceived(identifier, response); | 688 reportResponseReceived(identifier, response); |
| 722 | 689 |
| 723 ThreadableLoaderClient* client = m_client; | 690 ThreadableLoaderClient* client = m_client; |
| 724 clear(); | 691 clear(); |
| 725 client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInte
rnal, 0, response.url().getString(), accessControlErrorDescription)); | 692 client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInte
rnal, 0, response.url().getString(), accessControlErrorDescription)); |
| 726 // |this| may be dead here. | |
| 727 return; | 693 return; |
| 728 } | 694 } |
| 729 } | 695 } |
| 730 | 696 |
| 731 m_client->didReceiveResponse(identifier, response, std::move(handle)); | 697 m_client->didReceiveResponse(identifier, response, std::move(handle)); |
| 732 } | 698 } |
| 733 | 699 |
| 734 void DocumentThreadableLoader::setSerializedCachedMetadata(Resource*, const char
* data, size_t size) | 700 void DocumentThreadableLoader::setSerializedCachedMetadata(Resource*, const char
* data, size_t size) |
| 735 { | 701 { |
| 736 if (!m_actualRequest.isNull()) | 702 if (!m_actualRequest.isNull()) |
| 737 return; | 703 return; |
| 738 m_client->didReceiveCachedMetadata(data, size); | 704 m_client->didReceiveCachedMetadata(data, size); |
| 739 // |this| may be dead here. | |
| 740 } | 705 } |
| 741 | 706 |
| 742 void DocumentThreadableLoader::dataReceived(Resource* resource, const char* data
, size_t dataLength) | 707 void DocumentThreadableLoader::dataReceived(Resource* resource, const char* data
, size_t dataLength) |
| 743 { | 708 { |
| 744 ASSERT_UNUSED(resource, resource == this->resource()); | 709 ASSERT_UNUSED(resource, resource == this->resource()); |
| 745 ASSERT(m_async); | 710 ASSERT(m_async); |
| 746 | 711 |
| 747 if (m_isUsingDataConsumerHandle) | 712 if (m_isUsingDataConsumerHandle) |
| 748 return; | 713 return; |
| 749 | 714 |
| 750 // TODO(junov): Fix the ThreadableLoader ecosystem to use size_t. | 715 // TODO(junov): Fix the ThreadableLoader ecosystem to use size_t. |
| 751 // Until then, we use safeCast to trap potential overflows. | 716 // Until then, we use safeCast to trap potential overflows. |
| 752 handleReceivedData(data, safeCast<unsigned>(dataLength)); | 717 handleReceivedData(data, safeCast<unsigned>(dataLength)); |
| 753 // |this| may be dead here. | |
| 754 } | 718 } |
| 755 | 719 |
| 756 void DocumentThreadableLoader::handleReceivedData(const char* data, size_t dataL
ength) | 720 void DocumentThreadableLoader::handleReceivedData(const char* data, size_t dataL
ength) |
| 757 { | 721 { |
| 758 ASSERT(m_client); | 722 ASSERT(m_client); |
| 759 | 723 |
| 760 // Preflight data should be invisible to clients. | 724 // Preflight data should be invisible to clients. |
| 761 if (!m_actualRequest.isNull()) | 725 if (!m_actualRequest.isNull()) |
| 762 return; | 726 return; |
| 763 | 727 |
| 764 ASSERT(m_fallbackRequestForServiceWorker.isNull()); | 728 ASSERT(m_fallbackRequestForServiceWorker.isNull()); |
| 765 | 729 |
| 766 m_client->didReceiveData(data, dataLength); | 730 m_client->didReceiveData(data, dataLength); |
| 767 // |this| may be dead here in async mode. | |
| 768 } | 731 } |
| 769 | 732 |
| 770 void DocumentThreadableLoader::notifyFinished(Resource* resource) | 733 void DocumentThreadableLoader::notifyFinished(Resource* resource) |
| 771 { | 734 { |
| 772 ASSERT(m_client); | 735 ASSERT(m_client); |
| 773 ASSERT(resource == this->resource()); | 736 ASSERT(resource == this->resource()); |
| 774 ASSERT(m_async); | 737 ASSERT(m_async); |
| 775 | 738 |
| 776 if (resource->errorOccurred()) { | 739 if (resource->errorOccurred()) { |
| 777 handleError(resource->resourceError()); | 740 handleError(resource->resourceError()); |
| 778 // |this| may be dead here. | |
| 779 } else { | 741 } else { |
| 780 handleSuccessfulFinish(resource->identifier(), resource->loadFinishTime(
)); | 742 handleSuccessfulFinish(resource->identifier(), resource->loadFinishTime(
)); |
| 781 // |this| may be dead here. | |
| 782 } | 743 } |
| 783 } | 744 } |
| 784 | 745 |
| 785 void DocumentThreadableLoader::handleSuccessfulFinish(unsigned long identifier,
double finishTime) | 746 void DocumentThreadableLoader::handleSuccessfulFinish(unsigned long identifier,
double finishTime) |
| 786 { | 747 { |
| 787 ASSERT(m_fallbackRequestForServiceWorker.isNull()); | 748 ASSERT(m_fallbackRequestForServiceWorker.isNull()); |
| 788 | 749 |
| 789 if (!m_actualRequest.isNull()) { | 750 if (!m_actualRequest.isNull()) { |
| 790 // FIXME: Timeout should be applied to whole fetch, not for each of | 751 // FIXME: Timeout should be applied to whole fetch, not for each of |
| 791 // preflight and actual request. | 752 // preflight and actual request. |
| 792 m_timeoutTimer.stop(); | 753 m_timeoutTimer.stop(); |
| 793 ASSERT(!m_sameOriginRequest); | 754 ASSERT(!m_sameOriginRequest); |
| 794 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); | 755 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); |
| 795 loadActualRequest(); | 756 loadActualRequest(); |
| 796 // |this| may be dead here in async mode. | |
| 797 return; | 757 return; |
| 798 } | 758 } |
| 799 | 759 |
| 800 ThreadableLoaderClient* client = m_client; | 760 ThreadableLoaderClient* client = m_client; |
| 801 // Protect the resource in |didFinishLoading| in order not to release the | 761 // Protect the resource in |didFinishLoading| in order not to release the |
| 802 // downloaded file. | 762 // downloaded file. |
| 803 Persistent<Resource> resource = m_resource; | 763 Persistent<Resource> protect = resource(); |
| 804 clear(); | 764 clear(); |
| 805 client->didFinishLoading(identifier, finishTime); | 765 client->didFinishLoading(identifier, finishTime); |
| 806 // |this| may be dead here in async mode. | |
| 807 } | 766 } |
| 808 | 767 |
| 809 void DocumentThreadableLoader::didTimeout(TimerBase* timer) | 768 void DocumentThreadableLoader::didTimeout(TimerBase* timer) |
| 810 { | 769 { |
| 811 ASSERT_UNUSED(timer, timer == &m_timeoutTimer); | 770 ASSERT_UNUSED(timer, timer == &m_timeoutTimer); |
| 812 | 771 |
| 813 // Using values from net/base/net_error_list.h ERR_TIMED_OUT, | 772 // Using values from net/base/net_error_list.h ERR_TIMED_OUT, |
| 814 // Same as existing FIXME above - this error should be coming from FrameLoad
erClient to be identifiable. | 773 // Same as existing FIXME above - this error should be coming from FrameLoad
erClient to be identifiable. |
| 815 static const int timeoutError = -7; | 774 static const int timeoutError = -7; |
| 816 ResourceError error("net", timeoutError, resource()->url(), String()); | 775 ResourceError error("net", timeoutError, resource()->url(), String()); |
| 817 error.setIsTimeout(true); | 776 error.setIsTimeout(true); |
| 818 cancelWithError(error); | 777 cancelWithError(error); |
| 819 // |this| may be dead here. | |
| 820 } | 778 } |
| 821 | 779 |
| 822 void DocumentThreadableLoader::loadFallbackRequestForServiceWorker() | 780 void DocumentThreadableLoader::loadFallbackRequestForServiceWorker() |
| 823 { | 781 { |
| 824 clearResource(); | 782 clearResource(); |
| 825 ResourceRequest fallbackRequest(m_fallbackRequestForServiceWorker); | 783 ResourceRequest fallbackRequest(m_fallbackRequestForServiceWorker); |
| 826 m_fallbackRequestForServiceWorker = ResourceRequest(); | 784 m_fallbackRequestForServiceWorker = ResourceRequest(); |
| 827 dispatchInitialRequest(fallbackRequest); | 785 dispatchInitialRequest(fallbackRequest); |
| 828 // |this| may be dead here in async mode. | |
| 829 } | 786 } |
| 830 | 787 |
| 831 void DocumentThreadableLoader::loadActualRequest() | 788 void DocumentThreadableLoader::loadActualRequest() |
| 832 { | 789 { |
| 833 ResourceRequest actualRequest = m_actualRequest; | 790 ResourceRequest actualRequest = m_actualRequest; |
| 834 ResourceLoaderOptions actualOptions = m_actualOptions; | 791 ResourceLoaderOptions actualOptions = m_actualOptions; |
| 835 m_actualRequest = ResourceRequest(); | 792 m_actualRequest = ResourceRequest(); |
| 836 m_actualOptions = ResourceLoaderOptions(); | 793 m_actualOptions = ResourceLoaderOptions(); |
| 837 | 794 |
| 838 actualRequest.setHTTPOrigin(getSecurityOrigin()); | 795 actualRequest.setHTTPOrigin(getSecurityOrigin()); |
| 839 | 796 |
| 840 clearResource(); | 797 clearResource(); |
| 841 | 798 |
| 842 // Explicitly set the SkipServiceWorker flag here. Even if the page was not | 799 // Explicitly set the SkipServiceWorker flag here. Even if the page was not |
| 843 // controlled by a SW when the preflight request was sent, a new SW may be | 800 // controlled by a SW when the preflight request was sent, a new SW may be |
| 844 // controlling the page now by calling clients.claim(). We should not send | 801 // controlling the page now by calling clients.claim(). We should not send |
| 845 // the actual request to the SW. https://crbug.com/604583 | 802 // the actual request to the SW. https://crbug.com/604583 |
| 846 actualRequest.setSkipServiceWorker(WebURLRequest::SkipServiceWorker::All); | 803 actualRequest.setSkipServiceWorker(WebURLRequest::SkipServiceWorker::All); |
| 847 | 804 |
| 848 loadRequest(actualRequest, actualOptions); | 805 loadRequest(actualRequest, actualOptions); |
| 849 // |this| may be dead here in async mode. | |
| 850 } | 806 } |
| 851 | 807 |
| 852 void DocumentThreadableLoader::handlePreflightFailure(const String& url, const S
tring& errorDescription) | 808 void DocumentThreadableLoader::handlePreflightFailure(const String& url, const S
tring& errorDescription) |
| 853 { | 809 { |
| 854 ResourceError error(errorDomainBlinkInternal, 0, url, errorDescription); | 810 ResourceError error(errorDomainBlinkInternal, 0, url, errorDescription); |
| 855 | 811 |
| 856 // Prevent handleSuccessfulFinish() from bypassing access check. | 812 // Prevent handleSuccessfulFinish() from bypassing access check. |
| 857 m_actualRequest = ResourceRequest(); | 813 m_actualRequest = ResourceRequest(); |
| 858 | 814 |
| 859 ThreadableLoaderClient* client = m_client; | 815 ThreadableLoaderClient* client = m_client; |
| 860 clear(); | 816 clear(); |
| 861 client->didFailAccessControlCheck(error); | 817 client->didFailAccessControlCheck(error); |
| 862 // |this| may be dead here in async mode. | |
| 863 } | 818 } |
| 864 | 819 |
| 865 void DocumentThreadableLoader::handleError(const ResourceError& error) | 820 void DocumentThreadableLoader::handleError(const ResourceError& error) |
| 866 { | 821 { |
| 867 // Copy the ResourceError instance to make it sure that the passed | 822 // Copy the ResourceError instance to make it sure that the passed |
| 868 // ResourceError is alive during didFail() even when the Resource is | 823 // ResourceError is alive during didFail() even when the Resource is |
| 869 // destructed during didFail(). | 824 // destructed during didFail(). |
| 870 ResourceError copiedError = error; | 825 ResourceError copiedError = error; |
| 871 | 826 |
| 872 ThreadableLoaderClient* client = m_client; | 827 ThreadableLoaderClient* client = m_client; |
| 873 clear(); | 828 clear(); |
| 874 client->didFail(copiedError); | 829 client->didFail(copiedError); |
| 875 // |this| may be dead here. | |
| 876 } | 830 } |
| 877 | 831 |
| 878 void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, Resou
rceLoaderOptions resourceLoaderOptions) | 832 void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, Resou
rceLoaderOptions resourceLoaderOptions) |
| 879 { | 833 { |
| 880 // Any credential should have been removed from the cross-site requests. | 834 // Any credential should have been removed from the cross-site requests. |
| 881 const KURL& requestURL = request.url(); | 835 const KURL& requestURL = request.url(); |
| 882 ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); | 836 ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); |
| 883 ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); | 837 ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); |
| 884 | 838 |
| 885 // Update resourceLoaderOptions with enforced values. | 839 // Update resourceLoaderOptions with enforced values. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 901 WeakPtr<DocumentThreadableLoader> self(m_weakFactory.createWeakPtr()); | 855 WeakPtr<DocumentThreadableLoader> self(m_weakFactory.createWeakPtr()); |
| 902 | 856 |
| 903 if (request.requestContext() == WebURLRequest::RequestContextVideo || re
quest.requestContext() == WebURLRequest::RequestContextAudio) | 857 if (request.requestContext() == WebURLRequest::RequestContextVideo || re
quest.requestContext() == WebURLRequest::RequestContextAudio) |
| 904 setResource(RawResource::fetchMedia(newRequest, document().fetcher()
)); | 858 setResource(RawResource::fetchMedia(newRequest, document().fetcher()
)); |
| 905 else if (request.requestContext() == WebURLRequest::RequestContextManife
st) | 859 else if (request.requestContext() == WebURLRequest::RequestContextManife
st) |
| 906 setResource(RawResource::fetchManifest(newRequest, document().fetche
r())); | 860 setResource(RawResource::fetchManifest(newRequest, document().fetche
r())); |
| 907 else | 861 else |
| 908 setResource(RawResource::fetch(newRequest, document().fetcher())); | 862 setResource(RawResource::fetch(newRequest, document().fetcher())); |
| 909 | 863 |
| 910 // setResource() might call notifyFinished() synchronously, and thus | 864 // setResource() might call notifyFinished() synchronously, and thus |
| 911 // clear() might be called and |this| may be dead here. | |
| 912 if (!self) | 865 if (!self) |
| 913 return; | 866 return; |
| 914 | 867 |
| 915 if (!resource()) { | 868 if (!resource()) { |
| 916 InspectorInstrumentation::documentThreadableLoaderFailedToStartLoadi
ngForClient(m_document, m_client); | 869 InspectorInstrumentation::documentThreadableLoaderFailedToStartLoadi
ngForClient(m_document, m_client); |
| 917 ThreadableLoaderClient* client = m_client; | 870 ThreadableLoaderClient* client = m_client; |
| 918 clear(); | 871 clear(); |
| 919 // setResource() might call notifyFinished() and thus clear() | 872 // setResource() might call notifyFinished() and thus clear() |
| 920 // synchronously, and in such cases ThreadableLoaderClient is | 873 // synchronously, and in such cases ThreadableLoaderClient is |
| 921 // already notified and |client| is null. | 874 // already notified and |client| is null. |
| 922 if (!client) | 875 if (!client) |
| 923 return; | 876 return; |
| 924 client->didFail(ResourceError(errorDomainBlinkInternal, 0, requestUR
L.getString(), "Failed to start loading.")); | 877 client->didFail(ResourceError(errorDomainBlinkInternal, 0, requestUR
L.getString(), "Failed to start loading.")); |
| 925 // |this| may be dead here. | |
| 926 return; | 878 return; |
| 927 } | 879 } |
| 928 | 880 |
| 929 if (resource()->loader()) { | 881 if (resource()->loader()) { |
| 930 unsigned long identifier = resource()->identifier(); | 882 unsigned long identifier = resource()->identifier(); |
| 931 InspectorInstrumentation::documentThreadableLoaderStartedLoadingForC
lient(m_document, identifier, m_client); | 883 InspectorInstrumentation::documentThreadableLoaderStartedLoadingForC
lient(m_document, identifier, m_client); |
| 932 } else { | 884 } else { |
| 933 InspectorInstrumentation::documentThreadableLoaderFailedToStartLoadi
ngForClient(m_document, m_client); | 885 InspectorInstrumentation::documentThreadableLoaderFailedToStartLoadi
ngForClient(m_document, m_client); |
| 934 } | 886 } |
| 935 return; | 887 return; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1010 { | 962 { |
| 1011 return m_securityOrigin ? m_securityOrigin.get() : document().getSecurityOri
gin(); | 963 return m_securityOrigin ? m_securityOrigin.get() : document().getSecurityOri
gin(); |
| 1012 } | 964 } |
| 1013 | 965 |
| 1014 Document& DocumentThreadableLoader::document() const | 966 Document& DocumentThreadableLoader::document() const |
| 1015 { | 967 { |
| 1016 ASSERT(m_document); | 968 ASSERT(m_document); |
| 1017 return *m_document; | 969 return *m_document; |
| 1018 } | 970 } |
| 1019 | 971 |
| 972 DEFINE_TRACE(DocumentThreadableLoader) |
| 973 { |
| 974 visitor->trace(m_resource); |
| 975 visitor->trace(m_document); |
| 976 ThreadableLoader::trace(visitor); |
| 977 } |
| 978 |
| 1020 } // namespace blink | 979 } // namespace blink |
| OLD | NEW |