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