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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 73 : m_client(client) | 73 : m_client(client) |
| 74 , m_document(document) | 74 , m_document(document) |
| 75 , m_options(options) | 75 , m_options(options) |
| 76 , m_resourceLoaderOptions(resourceLoaderOptions) | 76 , m_resourceLoaderOptions(resourceLoaderOptions) |
| 77 , m_forceDoNotAllowStoredCredentials(false) | 77 , m_forceDoNotAllowStoredCredentials(false) |
| 78 , m_securityOrigin(m_resourceLoaderOptions.securityOrigin) | 78 , m_securityOrigin(m_resourceLoaderOptions.securityOrigin) |
| 79 , m_sameOriginRequest(securityOrigin()->canRequest(request.url())) | 79 , m_sameOriginRequest(securityOrigin()->canRequest(request.url())) |
| 80 , m_simpleRequest(true) | 80 , m_simpleRequest(true) |
| 81 , m_async(blockingBehavior == LoadAsynchronously) | 81 , m_async(blockingBehavior == LoadAsynchronously) |
| 82 , m_timeoutTimer(this, &DocumentThreadableLoader::didTimeout) | 82 , m_timeoutTimer(this, &DocumentThreadableLoader::didTimeout) |
| 83 , m_requestStartedSeconds(0.0) | |
| 83 { | 84 { |
| 84 ASSERT(client); | 85 ASSERT(client); |
| 85 // Setting an outgoing referer is only supported in the async code path. | 86 // Setting an outgoing referer is only supported in the async code path. |
| 86 ASSERT(m_async || request.httpReferrer().isEmpty()); | 87 ASSERT(m_async || request.httpReferrer().isEmpty()); |
| 87 | 88 |
| 89 m_requestStartedSeconds = monotonicallyIncreasingTime(); | |
| 90 | |
| 88 // Save any CORS simple headers on the request here. If this request redirec ts cross-origin, we cancel the old request | 91 // Save any CORS simple headers on the request here. If this request redirec ts cross-origin, we cancel the old request |
| 89 // create a new one, and copy these headers. | 92 // create a new one, and copy these headers. |
| 90 const HTTPHeaderMap& headerMap = request.httpHeaderFields(); | 93 const HTTPHeaderMap& headerMap = request.httpHeaderFields(); |
| 91 HTTPHeaderMap::const_iterator end = headerMap.end(); | 94 HTTPHeaderMap::const_iterator end = headerMap.end(); |
| 92 for (HTTPHeaderMap::const_iterator it = headerMap.begin(); it != end; ++it) { | 95 for (HTTPHeaderMap::const_iterator it = headerMap.begin(); it != end; ++it) { |
| 93 if (isOnAccessControlSimpleRequestHeaderWhitelist(it->key, it->value)) | 96 if (isOnAccessControlSimpleRequestHeaderWhitelist(it->key, it->value)) |
| 94 m_simpleRequestHeaders.add(it->key, it->value); | 97 m_simpleRequestHeaders.add(it->key, it->value); |
| 95 } | 98 } |
| 96 | 99 |
| 97 if (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossO riginRequests) { | 100 if (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossO riginRequests) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 141 preflightOptions.allowCredentials = DoNotAllowStoredCredentials; | 144 preflightOptions.allowCredentials = DoNotAllowStoredCredentials; |
| 142 loadRequest(preflightRequest, preflightOptions); | 145 loadRequest(preflightRequest, preflightOptions); |
| 143 } | 146 } |
| 144 } | 147 } |
| 145 } | 148 } |
| 146 | 149 |
| 147 DocumentThreadableLoader::~DocumentThreadableLoader() | 150 DocumentThreadableLoader::~DocumentThreadableLoader() |
| 148 { | 151 { |
| 149 } | 152 } |
| 150 | 153 |
| 154 void DocumentThreadableLoader::overrideTimeout(unsigned long timeoutMilliseconds ) | |
| 155 { | |
| 156 if (!m_async) | |
| 157 return; | |
|
abarth-chromium
2014/07/31 16:08:13
How can this be called during a synchronous reques
| |
| 158 m_timeoutTimer.stop(); | |
| 159 // At the time of this method's implementation, it is only ever called by | |
| 160 // XMLHttpRequest, when the timeout attribute is set after sending the | |
| 161 // request. | |
| 162 // | |
| 163 // The XHR request says to resolve the time relative to when the request | |
| 164 // was initially sent, however other uses of this method may need to | |
| 165 // behave differently, in which case this should be re-arranged somehow. | |
| 166 if (timeoutMilliseconds && m_requestStartedSeconds > 0.0) { | |
|
abarth-chromium
2014/07/31 16:08:13
How could m_requestStartedSeconds not be > 0.0? S
| |
| 167 double elapsedTime = monotonicallyIncreasingTime() - m_requestStartedSec onds; | |
| 168 double nextFire = timeoutMilliseconds / 1000.0; | |
| 169 double resolvedTime = std::max(nextFire - elapsedTime, 0.0); | |
| 170 m_timeoutTimer.startOneShot(resolvedTime, FROM_HERE); | |
|
abarth-chromium
2014/07/31 16:08:12
So, if the request has been running already for 2
caitp (gmail)
2014/07/31 16:43:29
I am not exactly certain how startOneShot() will w
tyoshino (SeeGerritForStatus)
2014/08/01 07:24:18
Correct. For the abarth@'s example
o elapsedTime =
| |
| 171 } | |
| 172 } | |
| 173 | |
| 151 void DocumentThreadableLoader::cancel() | 174 void DocumentThreadableLoader::cancel() |
| 152 { | 175 { |
| 153 cancelWithError(ResourceError()); | 176 cancelWithError(ResourceError()); |
| 154 } | 177 } |
| 155 | 178 |
| 156 void DocumentThreadableLoader::cancelWithError(const ResourceError& error) | 179 void DocumentThreadableLoader::cancelWithError(const ResourceError& error) |
| 157 { | 180 { |
| 158 RefPtr<DocumentThreadableLoader> protect(this); | 181 RefPtr<DocumentThreadableLoader> protect(this); |
| 159 | 182 |
| 160 // Cancel can re-enter and m_resource might be null here as a result. | 183 // Cancel can re-enter and m_resource might be null here as a result. |
| 161 if (m_client && resource()) { | 184 if (m_client && resource()) { |
| 162 ResourceError errorForCallback = error; | 185 ResourceError errorForCallback = error; |
| 163 if (errorForCallback.isNull()) { | 186 if (errorForCallback.isNull()) { |
| 164 // FIXME: This error is sent to the client in didFail(), so it shoul d not be an internal one. Use FrameLoaderClient::cancelledError() instead. | 187 // FIXME: This error is sent to the client in didFail(), so it shoul d not be an internal one. Use FrameLoaderClient::cancelledError() instead. |
| 165 errorForCallback = ResourceError(errorDomainBlinkInternal, 0, resour ce()->url().string(), "Load cancelled"); | 188 errorForCallback = ResourceError(errorDomainBlinkInternal, 0, resour ce()->url().string(), "Load cancelled"); |
| 166 errorForCallback.setIsCancellation(true); | 189 errorForCallback.setIsCancellation(true); |
| 167 } | 190 } |
| 168 m_client->didFail(errorForCallback); | 191 m_client->didFail(errorForCallback); |
| 169 } | 192 } |
| 170 clearResource(); | 193 clearResource(); |
| 171 m_client = 0; | 194 m_client = 0; |
| 195 m_requestStartedSeconds = 0.0; | |
| 172 } | 196 } |
| 173 | 197 |
| 174 void DocumentThreadableLoader::setDefersLoading(bool value) | 198 void DocumentThreadableLoader::setDefersLoading(bool value) |
| 175 { | 199 { |
| 176 if (resource()) | 200 if (resource()) |
| 177 resource()->setDefersLoading(value); | 201 resource()->setDefersLoading(value); |
| 178 } | 202 } |
| 179 | 203 |
| 180 void DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequ est& request, const ResourceResponse& redirectResponse) | 204 void DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequ est& request, const ResourceResponse& redirectResponse) |
| 181 { | 205 { |
| 182 ASSERT(m_client); | 206 ASSERT(m_client); |
| 183 ASSERT_UNUSED(resource, resource == this->resource()); | 207 ASSERT_UNUSED(resource, resource == this->resource()); |
| 184 | 208 |
| 185 RefPtr<DocumentThreadableLoader> protect(this); | 209 RefPtr<DocumentThreadableLoader> protect(this); |
| 186 if (!isAllowedByPolicy(request.url())) { | 210 if (!isAllowedByPolicy(request.url())) { |
| 187 m_client->didFailRedirectCheck(); | 211 m_client->didFailRedirectCheck(); |
| 188 request = ResourceRequest(); | 212 request = ResourceRequest(); |
| 213 m_requestStartedSeconds = 0.0; | |
| 189 return; | 214 return; |
| 190 } | 215 } |
| 191 | 216 |
| 192 // Allow same origin requests to continue after allowing clients to audit th e redirect. | 217 // Allow same origin requests to continue after allowing clients to audit th e redirect. |
| 193 if (isAllowedRedirect(request.url())) { | 218 if (isAllowedRedirect(request.url())) { |
| 194 if (m_client->isDocumentThreadableLoaderClient()) | 219 if (m_client->isDocumentThreadableLoaderClient()) |
| 195 static_cast<DocumentThreadableLoaderClient*>(m_client)->willSendRequ est(request, redirectResponse); | 220 static_cast<DocumentThreadableLoaderClient*>(m_client)->willSendRequ est(request, redirectResponse); |
| 196 return; | 221 return; |
| 197 } | 222 } |
| 198 | 223 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 245 makeCrossOriginAccessRequest(request); | 270 makeCrossOriginAccessRequest(request); |
| 246 return; | 271 return; |
| 247 } | 272 } |
| 248 | 273 |
| 249 ResourceError error(errorDomainBlinkInternal, 0, redirectResponse.url(). string(), accessControlErrorDescription); | 274 ResourceError error(errorDomainBlinkInternal, 0, redirectResponse.url(). string(), accessControlErrorDescription); |
| 250 m_client->didFailAccessControlCheck(error); | 275 m_client->didFailAccessControlCheck(error); |
| 251 } else { | 276 } else { |
| 252 m_client->didFailRedirectCheck(); | 277 m_client->didFailRedirectCheck(); |
| 253 } | 278 } |
| 254 request = ResourceRequest(); | 279 request = ResourceRequest(); |
| 280 m_requestStartedSeconds = 0.0; | |
| 255 } | 281 } |
| 256 | 282 |
| 257 void DocumentThreadableLoader::dataSent(Resource* resource, unsigned long long b ytesSent, unsigned long long totalBytesToBeSent) | 283 void DocumentThreadableLoader::dataSent(Resource* resource, unsigned long long b ytesSent, unsigned long long totalBytesToBeSent) |
| 258 { | 284 { |
| 259 ASSERT(m_client); | 285 ASSERT(m_client); |
| 260 ASSERT_UNUSED(resource, resource == this->resource()); | 286 ASSERT_UNUSED(resource, resource == this->resource()); |
| 261 m_client->didSendData(bytesSent, totalBytesToBeSent); | 287 m_client->didSendData(bytesSent, totalBytesToBeSent); |
| 262 } | 288 } |
| 263 | 289 |
| 264 void DocumentThreadableLoader::dataDownloaded(Resource* resource, int dataLength ) | 290 void DocumentThreadableLoader::dataDownloaded(Resource* resource, int dataLength ) |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 358 else | 384 else |
| 359 handleSuccessfulFinish(resource->identifier(), resource->loadFinishTime( )); | 385 handleSuccessfulFinish(resource->identifier(), resource->loadFinishTime( )); |
| 360 } | 386 } |
| 361 | 387 |
| 362 void DocumentThreadableLoader::handleSuccessfulFinish(unsigned long identifier, double finishTime) | 388 void DocumentThreadableLoader::handleSuccessfulFinish(unsigned long identifier, double finishTime) |
| 363 { | 389 { |
| 364 if (m_actualRequest) { | 390 if (m_actualRequest) { |
| 365 ASSERT(!m_sameOriginRequest); | 391 ASSERT(!m_sameOriginRequest); |
| 366 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); | 392 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); |
| 367 loadActualRequest(); | 393 loadActualRequest(); |
| 368 } else | 394 } else |
|
abarth-chromium
2014/07/31 16:01:35
Please add { }
| |
| 395 // FIXME: Should prevent timeout from being overridden after finished lo ading, without | |
| 396 // resetting m_requestStartedSeconds to 0.0 | |
| 369 m_client->didFinishLoading(identifier, finishTime); | 397 m_client->didFinishLoading(identifier, finishTime); |
| 370 } | 398 } |
| 371 | 399 |
| 372 void DocumentThreadableLoader::didTimeout(Timer<DocumentThreadableLoader>* timer ) | 400 void DocumentThreadableLoader::didTimeout(Timer<DocumentThreadableLoader>* timer ) |
| 373 { | 401 { |
| 374 ASSERT_UNUSED(timer, timer == &m_timeoutTimer); | 402 ASSERT_UNUSED(timer, timer == &m_timeoutTimer); |
| 375 | 403 |
| 376 // Using values from net/base/net_error_list.h ERR_TIMED_OUT, | 404 // Using values from net/base/net_error_list.h ERR_TIMED_OUT, |
| 377 // Same as existing FIXME above - this error should be coming from FrameLoad erClient to be identifiable. | 405 // Same as existing FIXME above - this error should be coming from FrameLoad erClient to be identifiable. |
| 378 static const int timeoutError = -7; | 406 static const int timeoutError = -7; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 395 loadRequest(*actualRequest, *actualOptions); | 423 loadRequest(*actualRequest, *actualOptions); |
| 396 } | 424 } |
| 397 | 425 |
| 398 void DocumentThreadableLoader::handlePreflightFailure(const String& url, const S tring& errorDescription) | 426 void DocumentThreadableLoader::handlePreflightFailure(const String& url, const S tring& errorDescription) |
| 399 { | 427 { |
| 400 ResourceError error(errorDomainBlinkInternal, 0, url, errorDescription); | 428 ResourceError error(errorDomainBlinkInternal, 0, url, errorDescription); |
| 401 | 429 |
| 402 // Prevent handleSuccessfulFinish() from bypassing access check. | 430 // Prevent handleSuccessfulFinish() from bypassing access check. |
| 403 m_actualRequest = nullptr; | 431 m_actualRequest = nullptr; |
| 404 | 432 |
| 433 // FIXME: Should prevent timeout from being overridden after preflight failu re, without | |
| 434 // resetting m_requestStartedSeconds to 0.0 | |
| 405 m_client->didFailAccessControlCheck(error); | 435 m_client->didFailAccessControlCheck(error); |
| 406 } | 436 } |
| 407 | 437 |
| 408 void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, Resou rceLoaderOptions resourceLoaderOptions) | 438 void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, Resou rceLoaderOptions resourceLoaderOptions) |
| 409 { | 439 { |
| 410 // Any credential should have been removed from the cross-site requests. | 440 // Any credential should have been removed from the cross-site requests. |
| 411 const KURL& requestURL = request.url(); | 441 const KURL& requestURL = request.url(); |
| 412 ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); | 442 ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); |
| 413 ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); | 443 ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); |
| 414 | 444 |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 441 FetchRequest fetchRequest(request, m_options.initiator, resourceLoaderOption s); | 471 FetchRequest fetchRequest(request, m_options.initiator, resourceLoaderOption s); |
| 442 ResourcePtr<Resource> resource = m_document.fetcher()->fetchSynchronously(fe tchRequest); | 472 ResourcePtr<Resource> resource = m_document.fetcher()->fetchSynchronously(fe tchRequest); |
| 443 ResourceResponse response = resource ? resource->response() : ResourceRespon se(); | 473 ResourceResponse response = resource ? resource->response() : ResourceRespon se(); |
| 444 unsigned long identifier = resource ? resource->identifier() : std::numeric_ limits<unsigned long>::max(); | 474 unsigned long identifier = resource ? resource->identifier() : std::numeric_ limits<unsigned long>::max(); |
| 445 ResourceError error = resource ? resource->resourceError() : ResourceError() ; | 475 ResourceError error = resource ? resource->resourceError() : ResourceError() ; |
| 446 | 476 |
| 447 InspectorInstrumentation::documentThreadableLoaderStartedLoadingForClient(&m _document, identifier, m_client); | 477 InspectorInstrumentation::documentThreadableLoaderStartedLoadingForClient(&m _document, identifier, m_client); |
| 448 | 478 |
| 449 if (!resource) { | 479 if (!resource) { |
| 450 m_client->didFail(error); | 480 m_client->didFail(error); |
| 481 m_requestStartedSeconds = 0.0; // Unnecessary for synchronous request, b ut for API consistency. | |
|
abarth-chromium
2014/07/31 16:01:35
Why doesn't this cause the same problem? Can the
tyoshino (SeeGerritForStatus)
2014/08/01 07:24:18
We enter this path only when m_asyc is false. So,
| |
| 451 return; | 482 return; |
| 452 } | 483 } |
| 453 | 484 |
| 454 // No exception for file:/// resources, see <rdar://problem/4962298>. | 485 // No exception for file:/// resources, see <rdar://problem/4962298>. |
| 455 // Also, if we have an HTTP response, then it wasn't a network error in fact . | 486 // Also, if we have an HTTP response, then it wasn't a network error in fact . |
| 456 if (!error.isNull() && !requestURL.isLocalFile() && response.httpStatusCode( ) <= 0) { | 487 if (!error.isNull() && !requestURL.isLocalFile() && response.httpStatusCode( ) <= 0) { |
| 457 m_client->didFail(error); | 488 m_client->didFail(error); |
| 458 return; | 489 return; |
| 459 } | 490 } |
| 460 | 491 |
| 461 // FIXME: A synchronous request does not tell us whether a redirect happened or not, so we guess by comparing the | 492 // FIXME: A synchronous request does not tell us whether a redirect happened or not, so we guess by comparing the |
| 462 // 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 | 493 // 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 |
| 463 // requested. Also comparing the request and response URLs as strings will f ail if the requestURL still has its credentials. | 494 // requested. Also comparing the request and response URLs as strings will f ail if the requestURL still has its credentials. |
| 464 if (requestURL != response.url() && (!isAllowedByPolicy(response.url()) || ! isAllowedRedirect(response.url()))) { | 495 if (requestURL != response.url() && (!isAllowedByPolicy(response.url()) || ! isAllowedRedirect(response.url()))) { |
| 465 m_client->didFailRedirectCheck(); | 496 m_client->didFailRedirectCheck(); |
| 497 m_requestStartedSeconds = 0.0; // Unnecessary for synchronous request, b ut for API consistency. | |
|
abarth-chromium
2014/07/31 16:01:35
ditto
| |
| 466 return; | 498 return; |
| 467 } | 499 } |
| 468 | 500 |
| 469 handleResponse(identifier, response); | 501 handleResponse(identifier, response); |
| 470 | 502 |
| 471 SharedBuffer* data = resource->resourceBuffer(); | 503 SharedBuffer* data = resource->resourceBuffer(); |
| 472 if (data) | 504 if (data) |
| 473 handleReceivedData(data->data(), data->size()); | 505 handleReceivedData(data->data(), data->size()); |
| 474 | 506 |
| 475 handleSuccessfulFinish(identifier, 0.0); | 507 handleSuccessfulFinish(identifier, 0.0); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 496 return DoNotAllowStoredCredentials; | 528 return DoNotAllowStoredCredentials; |
| 497 return m_resourceLoaderOptions.allowCredentials; | 529 return m_resourceLoaderOptions.allowCredentials; |
| 498 } | 530 } |
| 499 | 531 |
| 500 SecurityOrigin* DocumentThreadableLoader::securityOrigin() const | 532 SecurityOrigin* DocumentThreadableLoader::securityOrigin() const |
| 501 { | 533 { |
| 502 return m_securityOrigin ? m_securityOrigin.get() : m_document.securityOrigin (); | 534 return m_securityOrigin ? m_securityOrigin.get() : m_document.securityOrigin (); |
| 503 } | 535 } |
| 504 | 536 |
| 505 } // namespace WebCore | 537 } // namespace WebCore |
| OLD | NEW |