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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 69 } | 69 } |
| 70 | 70 |
| 71 DocumentThreadableLoader::DocumentThreadableLoader(Document& document, Threadabl eLoaderClient* client, BlockingBehavior blockingBehavior, const ResourceRequest& request, const ThreadableLoaderOptions& options) | 71 DocumentThreadableLoader::DocumentThreadableLoader(Document& document, Threadabl eLoaderClient* client, BlockingBehavior blockingBehavior, const ResourceRequest& request, const ThreadableLoaderOptions& options) |
| 72 : m_client(client) | 72 : m_client(client) |
| 73 , m_document(document) | 73 , m_document(document) |
| 74 , m_options(options) | 74 , m_options(options) |
| 75 , m_sameOriginRequest(securityOrigin()->canRequest(request.url())) | 75 , m_sameOriginRequest(securityOrigin()->canRequest(request.url())) |
| 76 , m_simpleRequest(true) | 76 , m_simpleRequest(true) |
| 77 , m_async(blockingBehavior == LoadAsynchronously) | 77 , m_async(blockingBehavior == LoadAsynchronously) |
| 78 , m_timeoutTimer(this, &DocumentThreadableLoader::didTimeout) | 78 , m_timeoutTimer(this, &DocumentThreadableLoader::didTimeout) |
| 79 , m_requestStarted(0.0) | |
| 79 { | 80 { |
| 80 ASSERT(client); | 81 ASSERT(client); |
| 81 // Setting an outgoing referer is only supported in the async code path. | 82 // Setting an outgoing referer is only supported in the async code path. |
| 82 ASSERT(m_async || request.httpReferrer().isEmpty()); | 83 ASSERT(m_async || request.httpReferrer().isEmpty()); |
| 83 | 84 |
| 85 m_requestStarted = monotonicallyIncreasingTime(); | |
| 86 | |
| 84 // Save any CORS simple headers on the request here. If this request redirec ts cross-origin, we cancel the old request | 87 // Save any CORS simple headers on the request here. If this request redirec ts cross-origin, we cancel the old request |
| 85 // create a new one, and copy these headers. | 88 // create a new one, and copy these headers. |
| 86 const HTTPHeaderMap& headerMap = request.httpHeaderFields(); | 89 const HTTPHeaderMap& headerMap = request.httpHeaderFields(); |
| 87 HTTPHeaderMap::const_iterator end = headerMap.end(); | 90 HTTPHeaderMap::const_iterator end = headerMap.end(); |
| 88 for (HTTPHeaderMap::const_iterator it = headerMap.begin(); it != end; ++it) { | 91 for (HTTPHeaderMap::const_iterator it = headerMap.begin(); it != end; ++it) { |
| 89 if (isOnAccessControlSimpleRequestHeaderWhitelist(it->key, it->value)) | 92 if (isOnAccessControlSimpleRequestHeaderWhitelist(it->key, it->value)) |
| 90 m_simpleRequestHeaders.add(it->key, it->value); | 93 m_simpleRequestHeaders.add(it->key, it->value); |
| 91 } | 94 } |
| 92 | 95 |
| 93 if (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossO riginRequests) { | 96 if (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossO riginRequests) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 131 ResourceRequest preflightRequest = createAccessControlPreflightReque st(*m_actualRequest, securityOrigin()); | 134 ResourceRequest preflightRequest = createAccessControlPreflightReque st(*m_actualRequest, securityOrigin()); |
| 132 loadRequest(preflightRequest); | 135 loadRequest(preflightRequest); |
| 133 } | 136 } |
| 134 } | 137 } |
| 135 } | 138 } |
| 136 | 139 |
| 137 DocumentThreadableLoader::~DocumentThreadableLoader() | 140 DocumentThreadableLoader::~DocumentThreadableLoader() |
| 138 { | 141 { |
| 139 } | 142 } |
| 140 | 143 |
| 144 void DocumentThreadableLoader::overrideTimeout(unsigned long timeoutMilliseconds ) | |
| 145 { | |
| 146 if (!m_async) | |
| 147 return; | |
| 148 m_timeoutTimer.stop(); | |
| 149 // At the time of this method's implementation, it is only ever called by | |
| 150 // XMLHttpRequest, when the timeout attribute is set after sending the | |
| 151 // request. | |
| 152 // | |
| 153 // The XHR request says to resolve the time relative to when the request | |
| 154 // was initially sent, however other uses of this method may need to | |
| 155 // behave differently, in which case this should be re-arranged somehow. | |
| 156 if (timeoutMilliseconds && m_requestStarted > 0.0) { | |
| 157 double elapsedTime = monotonicallyIncreasingTime() - m_requestStarted; | |
| 158 double nextFire = timeoutMilliseconds / 1000.0; | |
| 159 double resolvedTime = nextFire > elapsedTime ? nextFire - elapsedTime : 0.0; | |
|
eseidel
2014/05/21 21:41:50
std:min(nextfire - elapsedTime, 0) may be simpler.
| |
| 160 m_timeoutTimer.startOneShot(resolvedTime, FROM_HERE); | |
| 161 } | |
| 162 } | |
| 163 | |
| 141 void DocumentThreadableLoader::cancel() | 164 void DocumentThreadableLoader::cancel() |
| 142 { | 165 { |
| 143 cancelWithError(ResourceError()); | 166 cancelWithError(ResourceError()); |
| 144 } | 167 } |
| 145 | 168 |
| 146 void DocumentThreadableLoader::cancelWithError(const ResourceError& error) | 169 void DocumentThreadableLoader::cancelWithError(const ResourceError& error) |
| 147 { | 170 { |
| 148 RefPtr<DocumentThreadableLoader> protect(this); | 171 RefPtr<DocumentThreadableLoader> protect(this); |
| 149 | 172 |
| 150 // Cancel can re-enter and m_resource might be null here as a result. | 173 // Cancel can re-enter and m_resource might be null here as a result. |
| 151 if (m_client && resource()) { | 174 if (m_client && resource()) { |
| 152 ResourceError errorForCallback = error; | 175 ResourceError errorForCallback = error; |
| 153 if (errorForCallback.isNull()) { | 176 if (errorForCallback.isNull()) { |
| 154 // FIXME: This error is sent to the client in didFail(), so it shoul d not be an internal one. Use FrameLoaderClient::cancelledError() instead. | 177 // FIXME: This error is sent to the client in didFail(), so it shoul d not be an internal one. Use FrameLoaderClient::cancelledError() instead. |
| 155 errorForCallback = ResourceError(errorDomainBlinkInternal, 0, resour ce()->url().string(), "Load cancelled"); | 178 errorForCallback = ResourceError(errorDomainBlinkInternal, 0, resour ce()->url().string(), "Load cancelled"); |
| 156 errorForCallback.setIsCancellation(true); | 179 errorForCallback.setIsCancellation(true); |
| 157 } | 180 } |
| 158 m_client->didFail(errorForCallback); | 181 m_client->didFail(errorForCallback); |
| 159 } | 182 } |
| 160 clearResource(); | 183 clearResource(); |
| 161 m_client = 0; | 184 m_client = 0; |
| 185 m_requestStarted = 0.0; | |
| 162 } | 186 } |
| 163 | 187 |
| 164 void DocumentThreadableLoader::setDefersLoading(bool value) | 188 void DocumentThreadableLoader::setDefersLoading(bool value) |
| 165 { | 189 { |
| 166 if (resource()) | 190 if (resource()) |
| 167 resource()->setDefersLoading(value); | 191 resource()->setDefersLoading(value); |
| 168 } | 192 } |
| 169 | 193 |
| 170 void DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequ est& request, const ResourceResponse& redirectResponse) | 194 void DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequ est& request, const ResourceResponse& redirectResponse) |
| 171 { | 195 { |
| 172 ASSERT(m_client); | 196 ASSERT(m_client); |
| 173 ASSERT_UNUSED(resource, resource == this->resource()); | 197 ASSERT_UNUSED(resource, resource == this->resource()); |
| 174 | 198 |
| 175 RefPtr<DocumentThreadableLoader> protect(this); | 199 RefPtr<DocumentThreadableLoader> protect(this); |
| 176 if (!isAllowedByPolicy(request.url())) { | 200 if (!isAllowedByPolicy(request.url())) { |
| 177 m_client->didFailRedirectCheck(); | 201 m_client->didFailRedirectCheck(); |
| 178 request = ResourceRequest(); | 202 request = ResourceRequest(); |
|
tyoshino (SeeGerritForStatus)
2014/05/28 02:21:26
m_requestStarted = 0.0;
| |
| 179 return; | 203 return; |
| 180 } | 204 } |
| 181 | 205 |
| 182 // Allow same origin requests to continue after allowing clients to audit th e redirect. | 206 // Allow same origin requests to continue after allowing clients to audit th e redirect. |
| 183 if (isAllowedRedirect(request.url())) { | 207 if (isAllowedRedirect(request.url())) { |
| 184 if (m_client->isDocumentThreadableLoaderClient()) | 208 if (m_client->isDocumentThreadableLoaderClient()) |
| 185 static_cast<DocumentThreadableLoaderClient*>(m_client)->willSendRequ est(request, redirectResponse); | 209 static_cast<DocumentThreadableLoaderClient*>(m_client)->willSendRequ est(request, redirectResponse); |
| 186 return; | 210 return; |
| 187 } | 211 } |
| 188 | 212 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 234 } | 258 } |
| 235 makeCrossOriginAccessRequest(request); | 259 makeCrossOriginAccessRequest(request); |
| 236 return; | 260 return; |
| 237 } | 261 } |
| 238 | 262 |
| 239 ResourceError error(errorDomainBlinkInternal, 0, redirectResponse.url(). string(), accessControlErrorDescription); | 263 ResourceError error(errorDomainBlinkInternal, 0, redirectResponse.url(). string(), accessControlErrorDescription); |
| 240 m_client->didFailAccessControlCheck(error); | 264 m_client->didFailAccessControlCheck(error); |
| 241 } else { | 265 } else { |
| 242 m_client->didFailRedirectCheck(); | 266 m_client->didFailRedirectCheck(); |
| 243 } | 267 } |
| 244 request = ResourceRequest(); | 268 request = ResourceRequest(); |
|
tyoshino (SeeGerritForStatus)
2014/05/28 02:21:26
m_requestStarted = 0.0;
| |
| 245 } | 269 } |
| 246 | 270 |
| 247 void DocumentThreadableLoader::dataSent(Resource* resource, unsigned long long b ytesSent, unsigned long long totalBytesToBeSent) | 271 void DocumentThreadableLoader::dataSent(Resource* resource, unsigned long long b ytesSent, unsigned long long totalBytesToBeSent) |
| 248 { | 272 { |
| 249 ASSERT(m_client); | 273 ASSERT(m_client); |
| 250 ASSERT_UNUSED(resource, resource == this->resource()); | 274 ASSERT_UNUSED(resource, resource == this->resource()); |
| 251 m_client->didSendData(bytesSent, totalBytesToBeSent); | 275 m_client->didSendData(bytesSent, totalBytesToBeSent); |
| 252 } | 276 } |
| 253 | 277 |
| 254 void DocumentThreadableLoader::dataDownloaded(Resource* resource, int dataLength ) | 278 void DocumentThreadableLoader::dataDownloaded(Resource* resource, int dataLength ) |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 330 { | 354 { |
| 331 ASSERT(m_client); | 355 ASSERT(m_client); |
| 332 ASSERT(resource == this->resource()); | 356 ASSERT(resource == this->resource()); |
| 333 | 357 |
| 334 m_timeoutTimer.stop(); | 358 m_timeoutTimer.stop(); |
| 335 | 359 |
| 336 if (resource->errorOccurred()) | 360 if (resource->errorOccurred()) |
| 337 m_client->didFail(resource->resourceError()); | 361 m_client->didFail(resource->resourceError()); |
| 338 else | 362 else |
| 339 didFinishLoading(resource->identifier(), resource->loadFinishTime()); | 363 didFinishLoading(resource->identifier(), resource->loadFinishTime()); |
| 364 | |
| 365 m_requestStarted = 0.0; | |
|
tyoshino (SeeGerritForStatus)
2014/05/28 02:21:26
not here. see below
| |
| 340 } | 366 } |
| 341 | 367 |
| 342 void DocumentThreadableLoader::didFinishLoading(unsigned long identifier, double finishTime) | 368 void DocumentThreadableLoader::didFinishLoading(unsigned long identifier, double finishTime) |
| 343 { | 369 { |
| 344 if (m_actualRequest) { | 370 if (m_actualRequest) { |
| 345 ASSERT(!m_sameOriginRequest); | 371 ASSERT(!m_sameOriginRequest); |
| 346 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); | 372 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); |
| 347 preflightSuccess(); | 373 preflightSuccess(); |
| 348 } else | 374 } else |
| 349 m_client->didFinishLoading(identifier, finishTime); | 375 m_client->didFinishLoading(identifier, finishTime); |
|
tyoshino (SeeGerritForStatus)
2014/05/28 02:21:26
m_requestStarted = 0.0;
inside else block
| |
| 350 } | 376 } |
| 351 | 377 |
| 352 void DocumentThreadableLoader::didTimeout(Timer<DocumentThreadableLoader>* timer ) | 378 void DocumentThreadableLoader::didTimeout(Timer<DocumentThreadableLoader>* timer ) |
| 353 { | 379 { |
| 354 ASSERT_UNUSED(timer, timer == &m_timeoutTimer); | 380 ASSERT_UNUSED(timer, timer == &m_timeoutTimer); |
| 355 | 381 |
| 356 // Using values from net/base/net_error_list.h ERR_TIMED_OUT, | 382 // Using values from net/base/net_error_list.h ERR_TIMED_OUT, |
| 357 // Same as existing FIXME above - this error should be coming from FrameLoad erClient to be identifiable. | 383 // Same as existing FIXME above - this error should be coming from FrameLoad erClient to be identifiable. |
| 358 static const int timeoutError = -7; | 384 static const int timeoutError = -7; |
| 359 ResourceError error("net", timeoutError, resource()->url(), String()); | 385 ResourceError error("net", timeoutError, resource()->url(), String()); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 370 | 396 |
| 371 clearResource(); | 397 clearResource(); |
| 372 | 398 |
| 373 loadRequest(*actualRequest); | 399 loadRequest(*actualRequest); |
| 374 } | 400 } |
| 375 | 401 |
| 376 void DocumentThreadableLoader::preflightFailure(const String& url, const String& errorDescription) | 402 void DocumentThreadableLoader::preflightFailure(const String& url, const String& errorDescription) |
| 377 { | 403 { |
| 378 ResourceError error(errorDomainBlinkInternal, 0, url, errorDescription); | 404 ResourceError error(errorDomainBlinkInternal, 0, url, errorDescription); |
| 379 m_actualRequest = nullptr; // Prevent didFinishLoading() from bypassing acce ss check. | 405 m_actualRequest = nullptr; // Prevent didFinishLoading() from bypassing acce ss check. |
| 380 m_client->didFailAccessControlCheck(error); | 406 m_client->didFailAccessControlCheck(error); |
|
tyoshino (SeeGerritForStatus)
2014/05/28 02:21:26
m_requestStarted = 0.0;
| |
| 381 } | 407 } |
| 382 | 408 |
| 383 void DocumentThreadableLoader::loadRequest(const ResourceRequest& request) | 409 void DocumentThreadableLoader::loadRequest(const ResourceRequest& request) |
| 384 { | 410 { |
| 385 // Any credential should have been removed from the cross-site requests. | 411 // Any credential should have been removed from the cross-site requests. |
| 386 const KURL& requestURL = request.url(); | 412 const KURL& requestURL = request.url(); |
| 387 ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); | 413 ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); |
| 388 ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); | 414 ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); |
| 389 | 415 |
| 390 ThreadableLoaderOptions options = m_options; | 416 ThreadableLoaderOptions options = m_options; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 412 | 438 |
| 413 FetchRequest fetchRequest(request, m_options.initiator, options); | 439 FetchRequest fetchRequest(request, m_options.initiator, options); |
| 414 ResourcePtr<Resource> resource = m_document.fetcher()->fetchSynchronously(fe tchRequest); | 440 ResourcePtr<Resource> resource = m_document.fetcher()->fetchSynchronously(fe tchRequest); |
| 415 ResourceResponse response = resource ? resource->response() : ResourceRespon se(); | 441 ResourceResponse response = resource ? resource->response() : ResourceRespon se(); |
| 416 unsigned long identifier = resource ? resource->identifier() : std::numeric_ limits<unsigned long>::max(); | 442 unsigned long identifier = resource ? resource->identifier() : std::numeric_ limits<unsigned long>::max(); |
| 417 ResourceError error = resource ? resource->resourceError() : ResourceError() ; | 443 ResourceError error = resource ? resource->resourceError() : ResourceError() ; |
| 418 | 444 |
| 419 InspectorInstrumentation::documentThreadableLoaderStartedLoadingForClient(&m _document, identifier, m_client); | 445 InspectorInstrumentation::documentThreadableLoaderStartedLoadingForClient(&m _document, identifier, m_client); |
| 420 | 446 |
| 421 if (!resource) { | 447 if (!resource) { |
| 422 m_client->didFail(error); | 448 m_client->didFail(error); |
|
tyoshino (SeeGerritForStatus)
2014/05/28 02:21:26
m_requestStarted = 0.0;
unnecessary for sync case
| |
| 423 return; | 449 return; |
| 424 } | 450 } |
| 425 | 451 |
| 426 // No exception for file:/// resources, see <rdar://problem/4962298>. | 452 // No exception for file:/// resources, see <rdar://problem/4962298>. |
| 427 // Also, if we have an HTTP response, then it wasn't a network error in fact . | 453 // Also, if we have an HTTP response, then it wasn't a network error in fact . |
| 428 if (!error.isNull() && !requestURL.isLocalFile() && response.httpStatusCode( ) <= 0) { | 454 if (!error.isNull() && !requestURL.isLocalFile() && response.httpStatusCode( ) <= 0) { |
| 429 m_client->didFail(error); | 455 m_client->didFail(error); |
|
tyoshino (SeeGerritForStatus)
2014/05/28 02:21:26
m_requestStarted = 0.0;
unnecessary for sync case
| |
| 430 return; | 456 return; |
| 431 } | 457 } |
| 432 | 458 |
| 433 // FIXME: A synchronous request does not tell us whether a redirect happened or not, so we guess by comparing the | 459 // FIXME: A synchronous request does not tell us whether a redirect happened or not, so we guess by comparing the |
| 434 // 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 | 460 // 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 |
| 435 // requested. Also comparing the request and response URLs as strings will f ail if the requestURL still has its credentials. | 461 // requested. Also comparing the request and response URLs as strings will f ail if the requestURL still has its credentials. |
| 436 if (requestURL != response.url() && (!isAllowedByPolicy(response.url()) || ! isAllowedRedirect(response.url()))) { | 462 if (requestURL != response.url() && (!isAllowedByPolicy(response.url()) || ! isAllowedRedirect(response.url()))) { |
| 437 m_client->didFailRedirectCheck(); | 463 m_client->didFailRedirectCheck(); |
|
tyoshino (SeeGerritForStatus)
2014/05/28 02:21:26
m_requestStarted = 0.0;
unnecessary for sync case
| |
| 438 return; | 464 return; |
| 439 } | 465 } |
| 440 | 466 |
| 441 didReceiveResponse(identifier, response); | 467 didReceiveResponse(identifier, response); |
| 442 | 468 |
| 443 SharedBuffer* data = resource->resourceBuffer(); | 469 SharedBuffer* data = resource->resourceBuffer(); |
| 444 if (data) | 470 if (data) |
| 445 didReceiveData(data->data(), data->size()); | 471 didReceiveData(data->data(), data->size()); |
| 446 | 472 |
| 447 didFinishLoading(identifier, 0.0); | 473 didFinishLoading(identifier, 0.0); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 461 return true; | 487 return true; |
| 462 return m_document.contentSecurityPolicy()->allowConnectToSource(url); | 488 return m_document.contentSecurityPolicy()->allowConnectToSource(url); |
| 463 } | 489 } |
| 464 | 490 |
| 465 SecurityOrigin* DocumentThreadableLoader::securityOrigin() const | 491 SecurityOrigin* DocumentThreadableLoader::securityOrigin() const |
| 466 { | 492 { |
| 467 return m_options.securityOrigin ? m_options.securityOrigin.get() : m_documen t.securityOrigin(); | 493 return m_options.securityOrigin ? m_options.securityOrigin.get() : m_documen t.securityOrigin(); |
| 468 } | 494 } |
| 469 | 495 |
| 470 } // namespace WebCore | 496 } // namespace WebCore |
| OLD | NEW |