Chromium Code Reviews| 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 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 138 , m_timeoutTimer(this, &DocumentThreadableLoader::didTimeout) | 138 , m_timeoutTimer(this, &DocumentThreadableLoader::didTimeout) |
| 139 , m_requestStartedSeconds(0.0) | 139 , m_requestStartedSeconds(0.0) |
| 140 , m_corsRedirectLimit(kMaxCORSRedirects) | 140 , m_corsRedirectLimit(kMaxCORSRedirects) |
| 141 , m_redirectMode(request.fetchRedirectMode()) | 141 , m_redirectMode(request.fetchRedirectMode()) |
| 142 { | 142 { |
| 143 ASSERT(client); | 143 ASSERT(client); |
| 144 // Setting an outgoing referer is only supported in the async code path. | 144 // Setting an outgoing referer is only supported in the async code path. |
| 145 ASSERT(m_async || request.httpReferrer().isEmpty()); | 145 ASSERT(m_async || request.httpReferrer().isEmpty()); |
| 146 | 146 |
| 147 if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == DenyCrossO riginRequests) { | 147 if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == DenyCrossO riginRequests) { |
| 148 m_client->didFail(ResourceError(errorDomainBlinkInternal, 0, request.url ().string(), "Cross origin requests are not supported.")); | 148 ThreadableLoaderClient* client = m_client; |
| 149 clear(); | |
| 150 client->didFail(ResourceError(errorDomainBlinkInternal, 0, request.url() .string(), "Cross origin requests are not supported.")); | |
| 151 // |this| may be dead here. | |
| 149 return; | 152 return; |
| 150 } | 153 } |
| 151 | 154 |
| 152 m_requestStartedSeconds = monotonicallyIncreasingTime(); | 155 m_requestStartedSeconds = monotonicallyIncreasingTime(); |
| 153 | 156 |
| 154 // Save any CORS simple headers on the request here. If this request redirec ts cross-origin, we cancel the old request | 157 // Save any CORS simple headers on the request here. If this request redirec ts cross-origin, we cancel the old request |
| 155 // create a new one, and copy these headers. | 158 // create a new one, and copy these headers. |
| 156 const HTTPHeaderMap& headerMap = request.httpHeaderFields(); | 159 const HTTPHeaderMap& headerMap = request.httpHeaderFields(); |
| 157 for (const auto& header : headerMap) { | 160 for (const auto& header : headerMap) { |
| 158 if (FetchUtils::isSimpleHeader(header.key, header.value)) | 161 if (FetchUtils::isSimpleHeader(header.key, header.value)) |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 179 newRequest.setFetchRequestMode(WebURLRequest::FetchRequestModeCORS); | 182 newRequest.setFetchRequestMode(WebURLRequest::FetchRequestModeCORS); |
| 180 | 183 |
| 181 m_fallbackRequestForServiceWorker = adoptPtr(new ResourceRequest(request )); | 184 m_fallbackRequestForServiceWorker = adoptPtr(new ResourceRequest(request )); |
| 182 m_fallbackRequestForServiceWorker->setSkipServiceWorker(true); | 185 m_fallbackRequestForServiceWorker->setSkipServiceWorker(true); |
| 183 | 186 |
| 184 loadRequest(newRequest, m_resourceLoaderOptions); | 187 loadRequest(newRequest, m_resourceLoaderOptions); |
| 185 return; | 188 return; |
| 186 } | 189 } |
| 187 | 190 |
| 188 dispatchInitialRequest(request); | 191 dispatchInitialRequest(request); |
| 192 // |this| may be dead here in async mode. | |
| 189 } | 193 } |
| 190 | 194 |
| 191 void DocumentThreadableLoader::dispatchInitialRequest(const ResourceRequest& req uest) | 195 void DocumentThreadableLoader::dispatchInitialRequest(const ResourceRequest& req uest) |
| 192 { | 196 { |
| 193 if (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossO riginRequests) { | 197 if (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossO riginRequests) { |
| 194 loadRequest(request, m_resourceLoaderOptions); | 198 loadRequest(request, m_resourceLoaderOptions); |
| 195 return; | 199 return; |
| 196 } | 200 } |
| 197 | 201 |
| 198 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); | 202 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); |
| 199 | 203 |
| 200 makeCrossOriginAccessRequest(request); | 204 makeCrossOriginAccessRequest(request); |
| 205 // |this| may be dead here in async mode. | |
| 201 } | 206 } |
| 202 | 207 |
| 203 void DocumentThreadableLoader::makeCrossOriginAccessRequest(const ResourceReques t& request) | 208 void DocumentThreadableLoader::makeCrossOriginAccessRequest(const ResourceReques t& request) |
| 204 { | 209 { |
| 205 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); | 210 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); |
| 211 ASSERT(m_client); | |
| 212 ASSERT(!resource()); | |
| 206 | 213 |
| 207 // Cross-origin requests are only allowed certain registered schemes. | 214 // Cross-origin requests are only allowed certain registered schemes. |
| 208 // We would catch this when checking response headers later, but there | 215 // We would catch this when checking response headers later, but there |
| 209 // is no reason to send a request, preflighted or not, that's guaranteed | 216 // is no reason to send a request, preflighted or not, that's guaranteed |
| 210 // to be denied. | 217 // to be denied. |
| 211 if (!SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(request.url().protoco l())) { | 218 if (!SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(request.url().protoco l())) { |
| 212 m_client->didFailAccessControlCheck(ResourceError(errorDomainBlinkIntern al, 0, request.url().string(), "Cross origin requests are only supported for pro tocol schemes: " + SchemeRegistry::listOfCORSEnabledURLSchemes() + ".")); | 219 ThreadableLoaderClient* client = m_client; |
| 220 clear(); | |
| 221 client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal , 0, request.url().string(), "Cross origin requests are only supported for proto col schemes: " + SchemeRegistry::listOfCORSEnabledURLSchemes() + ".")); | |
| 222 // |this| may be dead here in async mode. | |
| 213 return; | 223 return; |
| 214 } | 224 } |
| 215 | 225 |
| 216 // We use isSimpleOrForbiddenRequest() here since |request| may have been | 226 // We use isSimpleOrForbiddenRequest() here since |request| may have been |
| 217 // modified in the process of loading (not from the user's input). For | 227 // modified in the process of loading (not from the user's input). For |
| 218 // example, referrer. We need to accept them. For security, we must reject | 228 // example, referrer. We need to accept them. For security, we must reject |
| 219 // forbidden headers/methods at the point we accept user's input. Not here. | 229 // forbidden headers/methods at the point we accept user's input. Not here. |
| 220 if ((m_options.preflightPolicy == ConsiderPreflight && FetchUtils::isSimpleO rForbiddenRequest(request.httpMethod(), request.httpHeaderFields())) || m_option s.preflightPolicy == PreventPreflight) { | 230 if ((m_options.preflightPolicy == ConsiderPreflight && FetchUtils::isSimpleO rForbiddenRequest(request.httpMethod(), request.httpHeaderFields())) || m_option s.preflightPolicy == PreventPreflight) { |
| 221 ResourceRequest crossOriginRequest(request); | 231 ResourceRequest crossOriginRequest(request); |
| 222 ResourceLoaderOptions crossOriginOptions(m_resourceLoaderOptions); | 232 ResourceLoaderOptions crossOriginOptions(m_resourceLoaderOptions); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 double elapsedTime = monotonicallyIncreasingTime() - m_requestStartedSec onds; | 276 double elapsedTime = monotonicallyIncreasingTime() - m_requestStartedSec onds; |
| 267 double nextFire = timeoutMilliseconds / 1000.0; | 277 double nextFire = timeoutMilliseconds / 1000.0; |
| 268 double resolvedTime = std::max(nextFire - elapsedTime, 0.0); | 278 double resolvedTime = std::max(nextFire - elapsedTime, 0.0); |
| 269 m_timeoutTimer.startOneShot(resolvedTime, FROM_HERE); | 279 m_timeoutTimer.startOneShot(resolvedTime, FROM_HERE); |
| 270 } | 280 } |
| 271 } | 281 } |
| 272 | 282 |
| 273 void DocumentThreadableLoader::cancel() | 283 void DocumentThreadableLoader::cancel() |
| 274 { | 284 { |
| 275 cancelWithError(ResourceError()); | 285 cancelWithError(ResourceError()); |
| 286 // |this| may be dead here. | |
| 276 } | 287 } |
| 277 | 288 |
| 278 void DocumentThreadableLoader::cancelWithError(const ResourceError& error) | 289 void DocumentThreadableLoader::cancelWithError(const ResourceError& error) |
| 279 { | 290 { |
| 280 RefPtr<DocumentThreadableLoader> protect(this); | 291 // Cancel can re-enter and m_resource might be null here as a result. |
| 292 if (!m_client || !resource()) { | |
| 293 clear(); | |
| 294 return; | |
| 295 } | |
| 281 | 296 |
| 282 // Cancel can re-enter and m_resource might be null here as a result. | 297 ResourceError errorForCallback = error; |
| 283 if (m_client && resource()) { | 298 if (errorForCallback.isNull()) { |
| 284 ResourceError errorForCallback = error; | 299 // FIXME: This error is sent to the client in didFail(), so it should no t be an internal one. Use FrameLoaderClient::cancelledError() instead. |
| 285 if (errorForCallback.isNull()) { | 300 errorForCallback = ResourceError(errorDomainBlinkInternal, 0, resource() ->url().string(), "Load cancelled"); |
| 286 // FIXME: This error is sent to the client in didFail(), so it shoul d not be an internal one. Use FrameLoaderClient::cancelledError() instead. | 301 errorForCallback.setIsCancellation(true); |
| 287 errorForCallback = ResourceError(errorDomainBlinkInternal, 0, resour ce()->url().string(), "Load cancelled"); | |
| 288 errorForCallback.setIsCancellation(true); | |
| 289 } | |
| 290 m_client->didFail(errorForCallback); | |
| 291 } | 302 } |
| 292 clearResource(); | 303 |
| 293 m_client = 0; | 304 ThreadableLoaderClient* client = m_client; |
| 294 m_requestStartedSeconds = 0.0; | 305 clear(); |
| 306 client->didFail(errorForCallback); | |
| 307 // |this| may be dead here in async mode. | |
| 295 } | 308 } |
| 296 | 309 |
| 297 void DocumentThreadableLoader::setDefersLoading(bool value) | 310 void DocumentThreadableLoader::setDefersLoading(bool value) |
| 298 { | 311 { |
| 299 if (resource()) | 312 if (resource()) |
| 300 resource()->setDefersLoading(value); | 313 resource()->setDefersLoading(value); |
| 301 } | 314 } |
| 302 | 315 |
| 316 void DocumentThreadableLoader::clear() | |
| 317 { | |
| 318 m_client = 0; | |
| 319 | |
| 320 if (!m_async) | |
| 321 return; | |
| 322 | |
| 323 clearResource(); | |
| 324 m_timeoutTimer.stop(); | |
| 325 m_requestStartedSeconds = 0.0; | |
| 326 } | |
| 327 | |
| 303 // In this method, we can clear |request| to tell content::WebURLLoaderImpl of | 328 // In this method, we can clear |request| to tell content::WebURLLoaderImpl of |
| 304 // Chromium not to follow the redirect. This works only when this method is | 329 // Chromium not to follow the redirect. This works only when this method is |
| 305 // called by RawResource::willSendRequest(). If called by | 330 // called by RawResource::willSendRequest(). If called by |
| 306 // RawResource::didAddClient(), clearing |request| won't be propagated | 331 // RawResource::didAddClient(), clearing |request| won't be propagated |
| 307 // to content::WebURLLoaderImpl. So, this loader must also get detached from | 332 // to content::WebURLLoaderImpl. So, this loader must also get detached from |
| 308 // the resource by calling clearResource(). | 333 // the resource by calling clearResource(). |
| 309 void DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequ est& request, const ResourceResponse& redirectResponse) | 334 void DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequ est& request, const ResourceResponse& redirectResponse) |
| 310 { | 335 { |
| 311 ASSERT(m_client); | 336 ASSERT(m_client); |
| 312 ASSERT_UNUSED(resource, resource == this->resource()); | 337 ASSERT_UNUSED(resource, resource == this->resource()); |
| 313 ASSERT(m_async); | 338 ASSERT(m_async); |
| 314 | 339 |
| 315 RefPtr<DocumentThreadableLoader> protect(this); | |
| 316 | |
| 317 if (m_actualRequest) { | 340 if (m_actualRequest) { |
| 318 reportResponseReceived(resource->identifier(), redirectResponse); | 341 reportResponseReceived(resource->identifier(), redirectResponse); |
| 319 | 342 |
| 320 clearResource(); | 343 handlePreflightFailure(redirectResponse.url().string(), "Response for pr eflight is invalid (redirect)"); |
| 344 // |this| may be dead here. | |
| 345 | |
| 321 request = ResourceRequest(); | 346 request = ResourceRequest(); |
| 322 | 347 |
| 323 m_requestStartedSeconds = 0.0; | |
| 324 | |
| 325 handlePreflightFailure(redirectResponse.url().string(), "Response for pr eflight is invalid (redirect)"); | |
| 326 | |
| 327 return; | 348 return; |
| 328 } | 349 } |
| 329 | 350 |
| 330 if (m_redirectMode == WebURLRequest::FetchRedirectModeManual) { | 351 if (m_redirectMode == WebURLRequest::FetchRedirectModeManual) { |
| 352 // Keep |this| alive even if the client release a reference in | |
| 353 // responseReceived(). | |
| 354 RefPtr<DocumentThreadableLoader> protect(this); | |
| 355 | |
| 331 // We use |m_redirectMode| to check the original redirect mode. | 356 // We use |m_redirectMode| to check the original redirect mode. |
| 332 // |request| is a new request for redirect. So we don't set the redirect | 357 // |request| is a new request for redirect. So we don't set the redirect |
| 333 // mode of it in WebURLLoaderImpl::Context::OnReceivedRedirect(). | 358 // mode of it in WebURLLoaderImpl::Context::OnReceivedRedirect(). |
| 334 ASSERT(request.useStreamOnResponse()); | 359 ASSERT(request.useStreamOnResponse()); |
| 335 // There is no need to read the body of redirect response because there | 360 // There is no need to read the body of redirect response because there |
| 336 // is no way to read the body of opaque-redirect filtered response's | 361 // is no way to read the body of opaque-redirect filtered response's |
| 337 // internal response. | 362 // internal response. |
| 338 // TODO(horo): If we support any API which expose the internal body, we | 363 // TODO(horo): If we support any API which expose the internal body, we |
| 339 // will have to read the body. And also HTTPCache changes will be needed | 364 // will have to read the body. And also HTTPCache changes will be needed |
| 340 // because it doesn't store the body of redirect responses. | 365 // because it doesn't store the body of redirect responses. |
| 341 responseReceived(resource, redirectResponse, adoptPtr(new EmptyDataHandl e())); | 366 responseReceived(resource, redirectResponse, adoptPtr(new EmptyDataHandl e())); |
| 367 | |
| 368 ASSERT(!m_actualRequest); | |
|
hiroshige
2015/09/16 04:09:47
Here |m_client| might be null (i.e. clear() might
tyoshino (SeeGerritForStatus)
2015/09/16 05:41:16
I thought I fixed this too in addition to L821, bu
| |
| 342 notifyFinished(resource); | 369 notifyFinished(resource); |
| 343 clearResource(); | 370 |
| 344 request = ResourceRequest(); | 371 request = ResourceRequest(); |
| 372 | |
| 345 return; | 373 return; |
| 346 } | 374 } |
| 347 | 375 |
| 348 if (m_redirectMode == WebURLRequest::FetchRedirectModeError || !isAllowedByC ontentSecurityPolicy(request.url(), ContentSecurityPolicy::DidRedirect)) { | 376 if (m_redirectMode == WebURLRequest::FetchRedirectModeError || !isAllowedByC ontentSecurityPolicy(request.url(), ContentSecurityPolicy::DidRedirect)) { |
| 349 m_client->didFailRedirectCheck(); | 377 ThreadableLoaderClient* client = m_client; |
| 378 clear(); | |
| 379 client->didFailRedirectCheck(); | |
| 380 // |this| may be dead here. | |
| 350 | 381 |
| 351 clearResource(); | |
| 352 request = ResourceRequest(); | 382 request = ResourceRequest(); |
| 353 | 383 |
| 354 m_requestStartedSeconds = 0.0; | |
| 355 return; | 384 return; |
| 356 } | 385 } |
| 357 | 386 |
| 358 // Allow same origin requests to continue after allowing clients to audit th e redirect. | 387 // Allow same origin requests to continue after allowing clients to audit th e redirect. |
| 359 if (isAllowedRedirect(request.url())) { | 388 if (isAllowedRedirect(request.url())) { |
| 360 if (m_client->isDocumentThreadableLoaderClient()) | 389 if (m_client->isDocumentThreadableLoaderClient()) |
| 361 static_cast<DocumentThreadableLoaderClient*>(m_client)->willFollowRe direct(request, redirectResponse); | 390 static_cast<DocumentThreadableLoaderClient*>(m_client)->willFollowRe direct(request, redirectResponse); |
| 362 return; | 391 return; |
| 363 } | 392 } |
| 364 | 393 |
| 365 if (m_corsRedirectLimit <= 0) { | 394 if (m_corsRedirectLimit <= 0) { |
| 366 m_client->didFailRedirectCheck(); | 395 ThreadableLoaderClient* client = m_client; |
| 396 clear(); | |
| 397 client->didFailRedirectCheck(); | |
| 398 // |this| may be dead here. | |
| 367 } else if (m_options.crossOriginRequestPolicy == UseAccessControl) { | 399 } else if (m_options.crossOriginRequestPolicy == UseAccessControl) { |
| 368 --m_corsRedirectLimit; | 400 --m_corsRedirectLimit; |
| 369 | 401 |
| 370 InspectorInstrumentation::didReceiveCORSRedirectResponse(m_document.fram e(), resource->identifier(), m_document.frame()->loader().documentLoader(), redi rectResponse, 0); | 402 InspectorInstrumentation::didReceiveCORSRedirectResponse(m_document.fram e(), resource->identifier(), m_document.frame()->loader().documentLoader(), redi rectResponse, 0); |
| 371 | 403 |
| 372 bool allowRedirect = false; | 404 bool allowRedirect = false; |
| 373 String accessControlErrorDescription; | 405 String accessControlErrorDescription; |
| 374 | 406 |
| 375 // Non-simple cross origin requests (both preflight and actual one) are | 407 // Non-simple cross origin requests (both preflight and actual one) are |
| 376 // not allowed to follow redirect. | 408 // not allowed to follow redirect. |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 404 m_forceDoNotAllowStoredCredentials = true; | 436 m_forceDoNotAllowStoredCredentials = true; |
| 405 | 437 |
| 406 // Remove any headers that may have been added by the network layer that cause access control to fail. | 438 // Remove any headers that may have been added by the network layer that cause access control to fail. |
| 407 request.clearHTTPReferrer(); | 439 request.clearHTTPReferrer(); |
| 408 request.clearHTTPOrigin(); | 440 request.clearHTTPOrigin(); |
| 409 request.clearHTTPUserAgent(); | 441 request.clearHTTPUserAgent(); |
| 410 // Add any CORS simple request headers which we previously saved fro m the original request. | 442 // Add any CORS simple request headers which we previously saved fro m the original request. |
| 411 for (const auto& header : m_simpleRequestHeaders) | 443 for (const auto& header : m_simpleRequestHeaders) |
| 412 request.setHTTPHeaderField(header.key, header.value); | 444 request.setHTTPHeaderField(header.key, header.value); |
| 413 makeCrossOriginAccessRequest(request); | 445 makeCrossOriginAccessRequest(request); |
| 446 // |this| may be dead here. | |
| 414 return; | 447 return; |
| 415 } | 448 } |
| 416 | 449 |
| 417 ResourceError error(errorDomainBlinkInternal, 0, redirectResponse.url(). string(), accessControlErrorDescription); | 450 ThreadableLoaderClient* client = m_client; |
| 418 m_client->didFailAccessControlCheck(error); | 451 clear(); |
| 452 client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal , 0, redirectResponse.url().string(), accessControlErrorDescription)); | |
| 453 // |this| may be dead here. | |
| 419 } else { | 454 } else { |
| 420 m_client->didFailRedirectCheck(); | 455 ThreadableLoaderClient* client = m_client; |
| 456 clear(); | |
| 457 client->didFailRedirectCheck(); | |
| 458 // |this| may be dead here. | |
| 421 } | 459 } |
| 422 | 460 |
| 423 clearResource(); | |
| 424 request = ResourceRequest(); | 461 request = ResourceRequest(); |
| 425 | |
| 426 m_requestStartedSeconds = 0.0; | |
| 427 } | 462 } |
| 428 | 463 |
| 429 void DocumentThreadableLoader::dataSent(Resource* resource, unsigned long long b ytesSent, unsigned long long totalBytesToBeSent) | 464 void DocumentThreadableLoader::dataSent(Resource* resource, unsigned long long b ytesSent, unsigned long long totalBytesToBeSent) |
| 430 { | 465 { |
| 431 ASSERT(m_client); | 466 ASSERT(m_client); |
| 432 ASSERT_UNUSED(resource, resource == this->resource()); | 467 ASSERT_UNUSED(resource, resource == this->resource()); |
| 433 ASSERT(m_async); | 468 ASSERT(m_async); |
| 434 | 469 |
| 435 m_client->didSendData(bytesSent, totalBytesToBeSent); | 470 m_client->didSendData(bytesSent, totalBytesToBeSent); |
| 471 // |this| may be dead here. | |
| 436 } | 472 } |
| 437 | 473 |
| 438 void DocumentThreadableLoader::dataDownloaded(Resource* resource, int dataLength ) | 474 void DocumentThreadableLoader::dataDownloaded(Resource* resource, int dataLength ) |
| 439 { | 475 { |
| 440 ASSERT(m_client); | 476 ASSERT(m_client); |
| 441 ASSERT_UNUSED(resource, resource == this->resource()); | 477 ASSERT_UNUSED(resource, resource == this->resource()); |
| 442 ASSERT(!m_actualRequest); | 478 ASSERT(!m_actualRequest); |
| 443 ASSERT(m_async); | 479 ASSERT(m_async); |
| 444 | 480 |
| 445 m_client->didDownloadData(dataLength); | 481 m_client->didDownloadData(dataLength); |
| 482 // |this| may be dead here. | |
| 446 } | 483 } |
| 447 | 484 |
| 448 void DocumentThreadableLoader::didReceiveResourceTiming(Resource* resource, cons t ResourceTimingInfo& info) | 485 void DocumentThreadableLoader::didReceiveResourceTiming(Resource* resource, cons t ResourceTimingInfo& info) |
| 449 { | 486 { |
| 450 ASSERT(m_client); | 487 ASSERT(m_client); |
| 451 ASSERT_UNUSED(resource, resource == this->resource()); | 488 ASSERT_UNUSED(resource, resource == this->resource()); |
| 452 ASSERT(m_async); | 489 ASSERT(m_async); |
| 453 | 490 |
| 454 m_client->didReceiveResourceTiming(info); | 491 m_client->didReceiveResourceTiming(info); |
| 492 // |this| may be dead here. | |
| 455 } | 493 } |
| 456 | 494 |
| 457 void DocumentThreadableLoader::responseReceived(Resource* resource, const Resour ceResponse& response, PassOwnPtr<WebDataConsumerHandle> handle) | 495 void DocumentThreadableLoader::responseReceived(Resource* resource, const Resour ceResponse& response, PassOwnPtr<WebDataConsumerHandle> handle) |
| 458 { | 496 { |
| 459 ASSERT_UNUSED(resource, resource == this->resource()); | 497 ASSERT_UNUSED(resource, resource == this->resource()); |
| 460 ASSERT(m_async); | 498 ASSERT(m_async); |
| 461 | 499 |
| 462 if (handle) | 500 if (handle) |
| 463 m_isUsingDataConsumerHandle = true; | 501 m_isUsingDataConsumerHandle = true; |
| 464 | 502 |
| 465 handleResponse(resource->identifier(), response, handle); | 503 handleResponse(resource->identifier(), response, handle); |
| 504 // |this| may be dead here. | |
| 466 } | 505 } |
| 467 | 506 |
| 468 void DocumentThreadableLoader::handlePreflightResponse(const ResourceResponse& r esponse) | 507 void DocumentThreadableLoader::handlePreflightResponse(const ResourceResponse& r esponse) |
| 469 { | 508 { |
| 470 String accessControlErrorDescription; | 509 String accessControlErrorDescription; |
| 471 | 510 |
| 472 if (!passesAccessControlCheck(response, effectiveAllowCredentials(), securit yOrigin(), accessControlErrorDescription, m_requestContext)) { | 511 if (!passesAccessControlCheck(response, effectiveAllowCredentials(), securit yOrigin(), accessControlErrorDescription, m_requestContext)) { |
| 473 handlePreflightFailure(response.url().string(), "Response to preflight r equest doesn't pass access control check: " + accessControlErrorDescription); | 512 handlePreflightFailure(response.url().string(), "Response to preflight r equest doesn't pass access control check: " + accessControlErrorDescription); |
| 513 // |this| may be dead here in async mode. | |
| 474 return; | 514 return; |
| 475 } | 515 } |
| 476 | 516 |
| 477 if (!passesPreflightStatusCheck(response, accessControlErrorDescription)) { | 517 if (!passesPreflightStatusCheck(response, accessControlErrorDescription)) { |
| 478 handlePreflightFailure(response.url().string(), accessControlErrorDescri ption); | 518 handlePreflightFailure(response.url().string(), accessControlErrorDescri ption); |
| 519 // |this| may be dead here in async mode. | |
| 479 return; | 520 return; |
| 480 } | 521 } |
| 481 | 522 |
| 482 OwnPtr<CrossOriginPreflightResultCacheItem> preflightResult = adoptPtr(new C rossOriginPreflightResultCacheItem(effectiveAllowCredentials())); | 523 OwnPtr<CrossOriginPreflightResultCacheItem> preflightResult = adoptPtr(new C rossOriginPreflightResultCacheItem(effectiveAllowCredentials())); |
| 483 if (!preflightResult->parse(response, accessControlErrorDescription) | 524 if (!preflightResult->parse(response, accessControlErrorDescription) |
| 484 || !preflightResult->allowsCrossOriginMethod(m_actualRequest->httpMethod (), accessControlErrorDescription) | 525 || !preflightResult->allowsCrossOriginMethod(m_actualRequest->httpMethod (), accessControlErrorDescription) |
| 485 || !preflightResult->allowsCrossOriginHeaders(m_actualRequest->httpHeade rFields(), accessControlErrorDescription)) { | 526 || !preflightResult->allowsCrossOriginHeaders(m_actualRequest->httpHeade rFields(), accessControlErrorDescription)) { |
| 486 handlePreflightFailure(response.url().string(), accessControlErrorDescri ption); | 527 handlePreflightFailure(response.url().string(), accessControlErrorDescri ption); |
| 528 // |this| may be dead here in async mode. | |
| 487 return; | 529 return; |
| 488 } | 530 } |
| 489 | 531 |
| 490 CrossOriginPreflightResultCache::shared().appendEntry(securityOrigin()->toSt ring(), m_actualRequest->url(), preflightResult.release()); | 532 CrossOriginPreflightResultCache::shared().appendEntry(securityOrigin()->toSt ring(), m_actualRequest->url(), preflightResult.release()); |
| 491 } | 533 } |
| 492 | 534 |
| 493 void DocumentThreadableLoader::reportResponseReceived(unsigned long identifier, const ResourceResponse& response) | 535 void DocumentThreadableLoader::reportResponseReceived(unsigned long identifier, const ResourceResponse& response) |
| 494 { | 536 { |
| 495 DocumentLoader* loader = m_document.frame()->loader().documentLoader(); | 537 DocumentLoader* loader = m_document.frame()->loader().documentLoader(); |
| 496 TRACE_EVENT_INSTANT1("devtools.timeline", "ResourceReceiveResponse", TRACE_E VENT_SCOPE_THREAD, "data", InspectorReceiveResponseEvent::data(identifier, m_doc ument.frame(), response)); | 538 TRACE_EVENT_INSTANT1("devtools.timeline", "ResourceReceiveResponse", TRACE_E VENT_SCOPE_THREAD, "data", InspectorReceiveResponseEvent::data(identifier, m_doc ument.frame(), response)); |
| 497 LocalFrame* frame = m_document.frame(); | 539 LocalFrame* frame = m_document.frame(); |
| 498 InspectorInstrumentation::didReceiveResourceResponse(frame, identifier, load er, response, resource() ? resource()->loader() : 0); | 540 InspectorInstrumentation::didReceiveResourceResponse(frame, identifier, load er, response, resource() ? resource()->loader() : 0); |
| 499 frame->console().reportResourceResponseReceived(loader, identifier, response ); | 541 frame->console().reportResourceResponseReceived(loader, identifier, response ); |
| 500 } | 542 } |
| 501 | 543 |
| 502 void DocumentThreadableLoader::handleResponse(unsigned long identifier, const Re sourceResponse& response, PassOwnPtr<WebDataConsumerHandle> handle) | 544 void DocumentThreadableLoader::handleResponse(unsigned long identifier, const Re sourceResponse& response, PassOwnPtr<WebDataConsumerHandle> handle) |
| 503 { | 545 { |
| 504 ASSERT(m_client); | 546 ASSERT(m_client); |
| 505 | 547 |
| 506 if (m_actualRequest) { | 548 if (m_actualRequest) { |
| 507 reportResponseReceived(identifier, response); | 549 reportResponseReceived(identifier, response); |
| 508 handlePreflightResponse(response); | 550 handlePreflightResponse(response); |
| 551 // |this| may be dead here in async mode. | |
| 509 return; | 552 return; |
| 510 } | 553 } |
| 511 | 554 |
| 512 if (response.wasFetchedViaServiceWorker()) { | 555 if (response.wasFetchedViaServiceWorker()) { |
| 513 // It's still possible to reach here with null m_fallbackRequestForServi ceWorker | 556 // It's still possible to reach here with null m_fallbackRequestForServi ceWorker |
| 514 // if the request was for main resource loading (i.e. for SharedWorker), for which | 557 // if the request was for main resource loading (i.e. for SharedWorker), for which |
| 515 // we create DocumentLoader before the controller ServiceWorker is set. | 558 // we create DocumentLoader before the controller ServiceWorker is set. |
| 516 ASSERT(m_fallbackRequestForServiceWorker || m_requestContext == WebURLRe quest::RequestContextSharedWorker); | 559 ASSERT(m_fallbackRequestForServiceWorker || m_requestContext == WebURLRe quest::RequestContextSharedWorker); |
| 517 if (response.wasFallbackRequiredByServiceWorker()) { | 560 if (response.wasFallbackRequiredByServiceWorker()) { |
| 518 // At this point we must have m_fallbackRequestForServiceWorker. | 561 // At this point we must have m_fallbackRequestForServiceWorker. |
| 519 // (For SharedWorker the request won't be CORS or CORS-with-prefligh t, | 562 // (For SharedWorker the request won't be CORS or CORS-with-prefligh t, |
| 520 // therefore fallback-to-network is handled in the browser process | 563 // therefore fallback-to-network is handled in the browser process |
| 521 // when the ServiceWorker does not call respondWith().) | 564 // when the ServiceWorker does not call respondWith().) |
| 522 ASSERT(m_fallbackRequestForServiceWorker); | 565 ASSERT(m_fallbackRequestForServiceWorker); |
| 523 reportResponseReceived(identifier, response); | 566 reportResponseReceived(identifier, response); |
| 524 loadFallbackRequestForServiceWorker(); | 567 loadFallbackRequestForServiceWorker(); |
| 568 // |this| may be dead here in async mode. | |
| 525 return; | 569 return; |
| 526 } | 570 } |
| 527 m_fallbackRequestForServiceWorker = nullptr; | 571 m_fallbackRequestForServiceWorker = nullptr; |
| 528 m_client->didReceiveResponse(identifier, response, handle); | 572 m_client->didReceiveResponse(identifier, response, handle); |
| 529 return; | 573 return; |
| 530 } | 574 } |
| 531 | 575 |
| 532 // Even if the request met the conditions to get handled by a Service Worker | 576 // Even if the request met the conditions to get handled by a Service Worker |
| 533 // in the constructor of this class (and therefore | 577 // in the constructor of this class (and therefore |
| 534 // |m_fallbackRequestForServiceWorker| is set), the Service Worker may skip | 578 // |m_fallbackRequestForServiceWorker| is set), the Service Worker may skip |
| 535 // processing the request. Only if the request is same origin, the skipped | 579 // processing the request. Only if the request is same origin, the skipped |
| 536 // response may come here (wasFetchedViaServiceWorker() returns false) since | 580 // response may come here (wasFetchedViaServiceWorker() returns false) since |
| 537 // such a request doesn't have to go through the CORS algorithm by calling | 581 // such a request doesn't have to go through the CORS algorithm by calling |
| 538 // loadFallbackRequestForServiceWorker(). | 582 // loadFallbackRequestForServiceWorker(). |
| 539 // FIXME: We should use |m_sameOriginRequest| when we will support | 583 // FIXME: We should use |m_sameOriginRequest| when we will support |
| 540 // Suborigins (crbug.com/336894) for Service Worker. | 584 // Suborigins (crbug.com/336894) for Service Worker. |
| 541 ASSERT(!m_fallbackRequestForServiceWorker || securityOrigin()->canRequest(m_ fallbackRequestForServiceWorker->url())); | 585 ASSERT(!m_fallbackRequestForServiceWorker || securityOrigin()->canRequest(m_ fallbackRequestForServiceWorker->url())); |
| 542 m_fallbackRequestForServiceWorker = nullptr; | 586 m_fallbackRequestForServiceWorker = nullptr; |
| 543 | 587 |
| 544 if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == UseAccessC ontrol) { | 588 if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == UseAccessC ontrol) { |
| 545 String accessControlErrorDescription; | 589 String accessControlErrorDescription; |
| 546 if (!passesAccessControlCheck(response, effectiveAllowCredentials(), sec urityOrigin(), accessControlErrorDescription, m_requestContext)) { | 590 if (!passesAccessControlCheck(response, effectiveAllowCredentials(), sec urityOrigin(), accessControlErrorDescription, m_requestContext)) { |
| 547 reportResponseReceived(identifier, response); | 591 reportResponseReceived(identifier, response); |
| 548 m_client->didFailAccessControlCheck(ResourceError(errorDomainBlinkIn ternal, 0, response.url().string(), accessControlErrorDescription)); | 592 |
| 593 ThreadableLoaderClient* client = m_client; | |
| 594 clear(); | |
| 595 client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInte rnal, 0, response.url().string(), accessControlErrorDescription)); | |
| 596 // |this| may be dead here. | |
| 549 return; | 597 return; |
| 550 } | 598 } |
| 551 } | 599 } |
| 552 | 600 |
| 553 m_client->didReceiveResponse(identifier, response, handle); | 601 m_client->didReceiveResponse(identifier, response, handle); |
| 554 } | 602 } |
| 555 | 603 |
| 556 void DocumentThreadableLoader::setSerializedCachedMetadata(Resource*, const char * data, size_t size) | 604 void DocumentThreadableLoader::setSerializedCachedMetadata(Resource*, const char * data, size_t size) |
| 557 { | 605 { |
| 558 if (m_actualRequest) | 606 if (m_actualRequest) |
| 559 return; | 607 return; |
| 560 m_client->didReceiveCachedMetadata(data, size); | 608 m_client->didReceiveCachedMetadata(data, size); |
| 609 // |this| may be dead here. | |
| 561 } | 610 } |
| 562 | 611 |
| 563 void DocumentThreadableLoader::dataReceived(Resource* resource, const char* data , unsigned dataLength) | 612 void DocumentThreadableLoader::dataReceived(Resource* resource, const char* data , unsigned dataLength) |
| 564 { | 613 { |
| 565 ASSERT_UNUSED(resource, resource == this->resource()); | 614 ASSERT_UNUSED(resource, resource == this->resource()); |
| 566 ASSERT(m_async); | 615 ASSERT(m_async); |
| 567 | 616 |
| 568 if (m_isUsingDataConsumerHandle) | 617 if (m_isUsingDataConsumerHandle) |
| 569 return; | 618 return; |
| 570 | 619 |
| 571 handleReceivedData(data, dataLength); | 620 handleReceivedData(data, dataLength); |
| 621 // |this| may be dead here. | |
| 572 } | 622 } |
| 573 | 623 |
| 574 void DocumentThreadableLoader::handleReceivedData(const char* data, unsigned dat aLength) | 624 void DocumentThreadableLoader::handleReceivedData(const char* data, unsigned dat aLength) |
| 575 { | 625 { |
| 576 ASSERT(m_client); | 626 ASSERT(m_client); |
| 577 | 627 |
| 578 // Preflight data should be invisible to clients. | 628 // Preflight data should be invisible to clients. |
| 579 if (m_actualRequest) | 629 if (m_actualRequest) |
| 580 return; | 630 return; |
| 581 | 631 |
| 582 ASSERT(!m_fallbackRequestForServiceWorker); | 632 ASSERT(!m_fallbackRequestForServiceWorker); |
| 583 | 633 |
| 584 m_client->didReceiveData(data, dataLength); | 634 m_client->didReceiveData(data, dataLength); |
| 635 // |this| may be dead here in async mode. | |
| 585 } | 636 } |
| 586 | 637 |
| 587 void DocumentThreadableLoader::notifyFinished(Resource* resource) | 638 void DocumentThreadableLoader::notifyFinished(Resource* resource) |
| 588 { | 639 { |
| 589 ASSERT(m_client); | 640 ASSERT(m_client); |
| 590 ASSERT(resource == this->resource()); | 641 ASSERT(resource == this->resource()); |
| 591 ASSERT(m_async); | 642 ASSERT(m_async); |
| 592 | 643 |
| 593 m_timeoutTimer.stop(); | 644 if (resource->errorOccurred()) { |
| 645 handleError(resource->resourceError()); | |
| 646 // |this| may be dead here. | |
| 647 } else { | |
| 648 handleSuccessfulFinish(resource->identifier(), resource->loadFinishTime( )); | |
| 649 // |this| may be dead here. | |
| 650 } | |
| 651 } | |
| 594 | 652 |
| 595 if (resource->errorOccurred()) | 653 void DocumentThreadableLoader::handleSuccessfulActualRequestFinish(unsigned long identifier, double finishTime) |
| 596 m_client->didFail(resource->resourceError()); | 654 { |
| 597 else | |
| 598 handleSuccessfulFinish(resource->identifier(), resource->loadFinishTime( )); | |
| 599 } | 655 } |
| 600 | 656 |
| 601 void DocumentThreadableLoader::handleSuccessfulFinish(unsigned long identifier, double finishTime) | 657 void DocumentThreadableLoader::handleSuccessfulFinish(unsigned long identifier, double finishTime) |
| 602 { | 658 { |
| 603 ASSERT(!m_fallbackRequestForServiceWorker); | 659 ASSERT(!m_fallbackRequestForServiceWorker); |
| 604 | 660 |
| 605 if (m_actualRequest) { | 661 if (!m_actualRequest) { |
| 662 // FIXME: Timeout should be applied to whole fetch, not for each of | |
| 663 // preflight and actual request. | |
| 664 m_timeoutTimer.stop(); | |
| 606 ASSERT(!m_sameOriginRequest); | 665 ASSERT(!m_sameOriginRequest); |
| 607 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); | 666 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); |
| 608 loadActualRequest(); | 667 loadActualRequest(); |
| 609 } else { | 668 return; |
| 610 // FIXME: Should prevent timeout from being overridden after finished lo ading, without | |
| 611 // resetting m_requestStartedSeconds to 0.0 | |
| 612 m_client->didFinishLoading(identifier, finishTime); | |
| 613 } | 669 } |
| 670 | |
| 671 ThreadableLoaderClient* client = m_client; | |
| 672 m_client = 0; | |
| 673 // Don't clear the resource as the client may need to access the downloaded | |
| 674 // file which will be released when the resource is destoryed. | |
| 675 if (m_async) { | |
| 676 m_timeoutTimer.stop(); | |
| 677 m_requestStartedSeconds = 0.0; | |
| 678 } | |
| 679 client->didFinishLoading(identifier, finishTime); | |
| 680 // |this| may be dead here in async mode. | |
| 614 } | 681 } |
| 615 | 682 |
| 616 void DocumentThreadableLoader::didTimeout(Timer<DocumentThreadableLoader>* timer ) | 683 void DocumentThreadableLoader::didTimeout(Timer<DocumentThreadableLoader>* timer ) |
| 617 { | 684 { |
| 618 ASSERT_UNUSED(timer, timer == &m_timeoutTimer); | 685 ASSERT_UNUSED(timer, timer == &m_timeoutTimer); |
| 619 | 686 |
| 620 // Using values from net/base/net_error_list.h ERR_TIMED_OUT, | 687 // Using values from net/base/net_error_list.h ERR_TIMED_OUT, |
| 621 // Same as existing FIXME above - this error should be coming from FrameLoad erClient to be identifiable. | 688 // Same as existing FIXME above - this error should be coming from FrameLoad erClient to be identifiable. |
| 622 static const int timeoutError = -7; | 689 static const int timeoutError = -7; |
| 623 ResourceError error("net", timeoutError, resource()->url(), String()); | 690 ResourceError error("net", timeoutError, resource()->url(), String()); |
| 624 error.setIsTimeout(true); | 691 error.setIsTimeout(true); |
| 625 cancelWithError(error); | 692 cancelWithError(error); |
| 693 // |this| may be dead here. | |
| 626 } | 694 } |
| 627 | 695 |
| 628 void DocumentThreadableLoader::loadFallbackRequestForServiceWorker() | 696 void DocumentThreadableLoader::loadFallbackRequestForServiceWorker() |
| 629 { | 697 { |
| 630 clearResource(); | 698 clearResource(); |
| 631 OwnPtr<ResourceRequest> fallbackRequest(m_fallbackRequestForServiceWorker.re lease()); | 699 OwnPtr<ResourceRequest> fallbackRequest(m_fallbackRequestForServiceWorker.re lease()); |
| 632 dispatchInitialRequest(*fallbackRequest); | 700 dispatchInitialRequest(*fallbackRequest); |
| 701 // |this| may be dead here in async mode. | |
| 633 } | 702 } |
| 634 | 703 |
| 635 void DocumentThreadableLoader::loadActualRequest() | 704 void DocumentThreadableLoader::loadActualRequest() |
| 636 { | 705 { |
| 637 OwnPtr<ResourceRequest> actualRequest; | 706 OwnPtr<ResourceRequest> actualRequest; |
| 638 actualRequest.swap(m_actualRequest); | 707 actualRequest.swap(m_actualRequest); |
| 639 OwnPtr<ResourceLoaderOptions> actualOptions; | 708 OwnPtr<ResourceLoaderOptions> actualOptions; |
| 640 actualOptions.swap(m_actualOptions); | 709 actualOptions.swap(m_actualOptions); |
| 641 | 710 |
| 642 actualRequest->setHTTPOrigin(securityOrigin()->toAtomicString()); | 711 actualRequest->setHTTPOrigin(securityOrigin()->toAtomicString()); |
| 643 | 712 |
| 644 clearResource(); | 713 clearResource(); |
| 645 | 714 |
| 646 loadRequest(*actualRequest, *actualOptions); | 715 loadRequest(*actualRequest, *actualOptions); |
| 647 } | 716 } |
| 648 | 717 |
| 649 void DocumentThreadableLoader::handlePreflightFailure(const String& url, const S tring& errorDescription) | 718 void DocumentThreadableLoader::handlePreflightFailure(const String& url, const S tring& errorDescription) |
| 650 { | 719 { |
| 651 ResourceError error(errorDomainBlinkInternal, 0, url, errorDescription); | 720 ResourceError error(errorDomainBlinkInternal, 0, url, errorDescription); |
| 652 | 721 |
| 653 // Prevent handleSuccessfulFinish() from bypassing access check. | 722 // Prevent handleSuccessfulFinish() from bypassing access check. |
| 654 m_actualRequest = nullptr; | 723 m_actualRequest = nullptr; |
| 655 | 724 |
| 656 // FIXME: Should prevent timeout from being overridden after preflight failu re, without | 725 ThreadableLoaderClient* client = m_client; |
| 657 // resetting m_requestStartedSeconds to 0.0 | 726 clear(); |
| 658 m_client->didFailAccessControlCheck(error); | 727 client->didFailAccessControlCheck(error); |
| 728 // |this| may be dead here in async mode. | |
| 729 } | |
| 730 | |
| 731 void DocumentThreadableLoader::handleError(const ResourceError& error) | |
| 732 { | |
| 733 // Copy the ResourceError instance to make it sure that the passed | |
| 734 // ResourceError is alive during didFail() even when the Resource is | |
| 735 // destructed during didFail(). | |
| 736 ResourceError copiedError = error; | |
| 737 | |
| 738 ThreadableLoaderClient* client = m_client; | |
| 739 clear(); | |
| 740 client->didFail(copiedError); | |
| 741 // |this| may be dead here. | |
| 659 } | 742 } |
| 660 | 743 |
| 661 void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, Resou rceLoaderOptions resourceLoaderOptions) | 744 void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, Resou rceLoaderOptions resourceLoaderOptions) |
| 662 { | 745 { |
| 663 // Any credential should have been removed from the cross-site requests. | 746 // Any credential should have been removed from the cross-site requests. |
| 664 const KURL& requestURL = request.url(); | 747 const KURL& requestURL = request.url(); |
| 665 ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); | 748 ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); |
| 666 ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); | 749 ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); |
| 667 | 750 |
| 668 // Update resourceLoaderOptions with enforced values. | 751 // Update resourceLoaderOptions with enforced values. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 716 // FIXME: A synchronous request does not tell us whether a redirect happened or not, so we guess by comparing the | 799 // FIXME: A synchronous request does not tell us whether a redirect happened or not, so we guess by comparing the |
| 717 // request and response URLs. This isn't a perfect test though, since a serv er can serve a redirect to the same URL that was | 800 // request and response URLs. This isn't a perfect test though, since a serv er can serve a redirect to the same URL that was |
| 718 // requested. Also comparing the request and response URLs as strings will f ail if the requestURL still has its credentials. | 801 // requested. Also comparing the request and response URLs as strings will f ail if the requestURL still has its credentials. |
| 719 if (requestURL != response.url() && (!isAllowedByContentSecurityPolicy(respo nse.url(), ContentSecurityPolicy::DidRedirect) || !isAllowedRedirect(response.ur l()))) { | 802 if (requestURL != response.url() && (!isAllowedByContentSecurityPolicy(respo nse.url(), ContentSecurityPolicy::DidRedirect) || !isAllowedRedirect(response.ur l()))) { |
| 720 m_client->didFailRedirectCheck(); | 803 m_client->didFailRedirectCheck(); |
| 721 return; | 804 return; |
| 722 } | 805 } |
| 723 | 806 |
| 724 handleResponse(identifier, response, nullptr); | 807 handleResponse(identifier, response, nullptr); |
| 725 | 808 |
| 809 // handleResponse() may detect an error. In such a case (check |m_client| | |
| 810 // as it gets reset by clear() call), skip the rest. | |
| 811 // | |
| 812 // |this| is alive here since loadResourceSynchronously() keeps it alive | |
| 813 // until the end of the function. | |
| 814 if (!m_client) | |
| 815 return; | |
| 816 | |
| 726 SharedBuffer* data = resource->resourceBuffer(); | 817 SharedBuffer* data = resource->resourceBuffer(); |
| 727 if (data) | 818 if (data) |
| 728 handleReceivedData(data->data(), data->size()); | 819 handleReceivedData(data->data(), data->size()); |
| 729 | 820 |
| 821 // The client may cancel this loader in handleReceivedData(). In such a | |
| 822 // case, skip the rest. | |
| 823 if (!m_client) | |
| 824 return; | |
| 825 | |
| 730 handleSuccessfulFinish(identifier, 0.0); | 826 handleSuccessfulFinish(identifier, 0.0); |
| 731 } | 827 } |
| 732 | 828 |
| 733 bool DocumentThreadableLoader::isAllowedRedirect(const KURL& url) const | 829 bool DocumentThreadableLoader::isAllowedRedirect(const KURL& url) const |
| 734 { | 830 { |
| 735 if (m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) | 831 if (m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) |
| 736 return true; | 832 return true; |
| 737 | 833 |
| 738 return m_sameOriginRequest && securityOrigin()->canRequest(url); | 834 return m_sameOriginRequest && securityOrigin()->canRequest(url); |
| 739 } | 835 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 751 return DoNotAllowStoredCredentials; | 847 return DoNotAllowStoredCredentials; |
| 752 return m_resourceLoaderOptions.allowCredentials; | 848 return m_resourceLoaderOptions.allowCredentials; |
| 753 } | 849 } |
| 754 | 850 |
| 755 SecurityOrigin* DocumentThreadableLoader::securityOrigin() const | 851 SecurityOrigin* DocumentThreadableLoader::securityOrigin() const |
| 756 { | 852 { |
| 757 return m_securityOrigin ? m_securityOrigin.get() : m_document.securityOrigin (); | 853 return m_securityOrigin ? m_securityOrigin.get() : m_document.securityOrigin (); |
| 758 } | 854 } |
| 759 | 855 |
| 760 } // namespace blink | 856 } // namespace blink |
| OLD | NEW |