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 |