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_requestStartedSeconds(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_requestStartedSeconds = 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_requestStartedSeconds > 0.0) { | |
157 double elapsedTime = monotonicallyIncreasingTime() - m_requestStartedSec onds; | |
158 double nextFire = timeoutMilliseconds / 1000.0; | |
159 double resolvedTime = std::max(nextFire - elapsedTime, 0.0); | |
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_requestStartedSeconds = 0.0; | |
eseidel
2014/05/28 22:06:37
If we start to clear multiple things at the same t
| |
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(); |
203 m_requestStartedSeconds = 0.0; | |
179 return; | 204 return; |
180 } | 205 } |
181 | 206 |
182 // Allow same origin requests to continue after allowing clients to audit th e redirect. | 207 // Allow same origin requests to continue after allowing clients to audit th e redirect. |
183 if (isAllowedRedirect(request.url())) { | 208 if (isAllowedRedirect(request.url())) { |
184 if (m_client->isDocumentThreadableLoaderClient()) | 209 if (m_client->isDocumentThreadableLoaderClient()) |
185 static_cast<DocumentThreadableLoaderClient*>(m_client)->willSendRequ est(request, redirectResponse); | 210 static_cast<DocumentThreadableLoaderClient*>(m_client)->willSendRequ est(request, redirectResponse); |
186 return; | 211 return; |
187 } | 212 } |
188 | 213 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
235 makeCrossOriginAccessRequest(request); | 260 makeCrossOriginAccessRequest(request); |
236 return; | 261 return; |
237 } | 262 } |
238 | 263 |
239 ResourceError error(errorDomainBlinkInternal, 0, redirectResponse.url(). string(), accessControlErrorDescription); | 264 ResourceError error(errorDomainBlinkInternal, 0, redirectResponse.url(). string(), accessControlErrorDescription); |
240 m_client->didFailAccessControlCheck(error); | 265 m_client->didFailAccessControlCheck(error); |
241 } else { | 266 } else { |
242 m_client->didFailRedirectCheck(); | 267 m_client->didFailRedirectCheck(); |
243 } | 268 } |
244 request = ResourceRequest(); | 269 request = ResourceRequest(); |
270 m_requestStartedSeconds = 0.0; | |
245 } | 271 } |
246 | 272 |
247 void DocumentThreadableLoader::dataSent(Resource* resource, unsigned long long b ytesSent, unsigned long long totalBytesToBeSent) | 273 void DocumentThreadableLoader::dataSent(Resource* resource, unsigned long long b ytesSent, unsigned long long totalBytesToBeSent) |
248 { | 274 { |
249 ASSERT(m_client); | 275 ASSERT(m_client); |
250 ASSERT_UNUSED(resource, resource == this->resource()); | 276 ASSERT_UNUSED(resource, resource == this->resource()); |
251 m_client->didSendData(bytesSent, totalBytesToBeSent); | 277 m_client->didSendData(bytesSent, totalBytesToBeSent); |
252 } | 278 } |
253 | 279 |
254 void DocumentThreadableLoader::dataDownloaded(Resource* resource, int dataLength ) | 280 void DocumentThreadableLoader::dataDownloaded(Resource* resource, int dataLength ) |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
346 else | 372 else |
347 handleSuccessfulFinish(resource->identifier(), resource->loadFinishTime( )); | 373 handleSuccessfulFinish(resource->identifier(), resource->loadFinishTime( )); |
348 } | 374 } |
349 | 375 |
350 void DocumentThreadableLoader::handleSuccessfulFinish(unsigned long identifier, double finishTime) | 376 void DocumentThreadableLoader::handleSuccessfulFinish(unsigned long identifier, double finishTime) |
351 { | 377 { |
352 if (m_actualRequest) { | 378 if (m_actualRequest) { |
353 ASSERT(!m_sameOriginRequest); | 379 ASSERT(!m_sameOriginRequest); |
354 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); | 380 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); |
355 loadActualRequest(); | 381 loadActualRequest(); |
356 } else | 382 } else { |
357 m_client->didFinishLoading(identifier, finishTime); | 383 m_client->didFinishLoading(identifier, finishTime); |
384 m_requestStartedSeconds = 0.0; | |
385 } | |
358 } | 386 } |
359 | 387 |
360 void DocumentThreadableLoader::didTimeout(Timer<DocumentThreadableLoader>* timer ) | 388 void DocumentThreadableLoader::didTimeout(Timer<DocumentThreadableLoader>* timer ) |
361 { | 389 { |
362 ASSERT_UNUSED(timer, timer == &m_timeoutTimer); | 390 ASSERT_UNUSED(timer, timer == &m_timeoutTimer); |
363 | 391 |
364 // Using values from net/base/net_error_list.h ERR_TIMED_OUT, | 392 // Using values from net/base/net_error_list.h ERR_TIMED_OUT, |
365 // Same as existing FIXME above - this error should be coming from FrameLoad erClient to be identifiable. | 393 // Same as existing FIXME above - this error should be coming from FrameLoad erClient to be identifiable. |
366 static const int timeoutError = -7; | 394 static const int timeoutError = -7; |
367 ResourceError error("net", timeoutError, resource()->url(), String()); | 395 ResourceError error("net", timeoutError, resource()->url(), String()); |
(...skipping 14 matching lines...) Expand all Loading... | |
382 } | 410 } |
383 | 411 |
384 void DocumentThreadableLoader::handlePreflightFailure(const String& url, const S tring& errorDescription) | 412 void DocumentThreadableLoader::handlePreflightFailure(const String& url, const S tring& errorDescription) |
385 { | 413 { |
386 ResourceError error(errorDomainBlinkInternal, 0, url, errorDescription); | 414 ResourceError error(errorDomainBlinkInternal, 0, url, errorDescription); |
387 | 415 |
388 // Prevent handleSuccessfulFinish() from bypassing access check. | 416 // Prevent handleSuccessfulFinish() from bypassing access check. |
389 m_actualRequest = nullptr; | 417 m_actualRequest = nullptr; |
390 | 418 |
391 m_client->didFailAccessControlCheck(error); | 419 m_client->didFailAccessControlCheck(error); |
420 m_requestStartedSeconds = 0.0; | |
392 } | 421 } |
393 | 422 |
394 void DocumentThreadableLoader::loadRequest(const ResourceRequest& request) | 423 void DocumentThreadableLoader::loadRequest(const ResourceRequest& request) |
395 { | 424 { |
396 // Any credential should have been removed from the cross-site requests. | 425 // Any credential should have been removed from the cross-site requests. |
397 const KURL& requestURL = request.url(); | 426 const KURL& requestURL = request.url(); |
398 ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); | 427 ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); |
399 ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); | 428 ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); |
400 | 429 |
401 ThreadableLoaderOptions options = m_options; | 430 ThreadableLoaderOptions options = m_options; |
(...skipping 22 matching lines...) Expand all Loading... | |
424 FetchRequest fetchRequest(request, m_options.initiator, options); | 453 FetchRequest fetchRequest(request, m_options.initiator, options); |
425 ResourcePtr<Resource> resource = m_document.fetcher()->fetchSynchronously(fe tchRequest); | 454 ResourcePtr<Resource> resource = m_document.fetcher()->fetchSynchronously(fe tchRequest); |
426 ResourceResponse response = resource ? resource->response() : ResourceRespon se(); | 455 ResourceResponse response = resource ? resource->response() : ResourceRespon se(); |
427 unsigned long identifier = resource ? resource->identifier() : std::numeric_ limits<unsigned long>::max(); | 456 unsigned long identifier = resource ? resource->identifier() : std::numeric_ limits<unsigned long>::max(); |
428 ResourceError error = resource ? resource->resourceError() : ResourceError() ; | 457 ResourceError error = resource ? resource->resourceError() : ResourceError() ; |
429 | 458 |
430 InspectorInstrumentation::documentThreadableLoaderStartedLoadingForClient(&m _document, identifier, m_client); | 459 InspectorInstrumentation::documentThreadableLoaderStartedLoadingForClient(&m _document, identifier, m_client); |
431 | 460 |
432 if (!resource) { | 461 if (!resource) { |
433 m_client->didFail(error); | 462 m_client->didFail(error); |
463 m_requestStartedSeconds = 0.0; // Unnecessary for synchronous request, b ut for API consistency. | |
434 return; | 464 return; |
435 } | 465 } |
436 | 466 |
437 // No exception for file:/// resources, see <rdar://problem/4962298>. | 467 // No exception for file:/// resources, see <rdar://problem/4962298>. |
438 // Also, if we have an HTTP response, then it wasn't a network error in fact . | 468 // Also, if we have an HTTP response, then it wasn't a network error in fact . |
439 if (!error.isNull() && !requestURL.isLocalFile() && response.httpStatusCode( ) <= 0) { | 469 if (!error.isNull() && !requestURL.isLocalFile() && response.httpStatusCode( ) <= 0) { |
440 m_client->didFail(error); | 470 m_client->didFail(error); |
441 return; | 471 return; |
442 } | 472 } |
443 | 473 |
444 // FIXME: A synchronous request does not tell us whether a redirect happened or not, so we guess by comparing the | 474 // FIXME: A synchronous request does not tell us whether a redirect happened or not, so we guess by comparing the |
445 // 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 | 475 // 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 |
446 // requested. Also comparing the request and response URLs as strings will f ail if the requestURL still has its credentials. | 476 // requested. Also comparing the request and response URLs as strings will f ail if the requestURL still has its credentials. |
447 if (requestURL != response.url() && (!isAllowedByPolicy(response.url()) || ! isAllowedRedirect(response.url()))) { | 477 if (requestURL != response.url() && (!isAllowedByPolicy(response.url()) || ! isAllowedRedirect(response.url()))) { |
448 m_client->didFailRedirectCheck(); | 478 m_client->didFailRedirectCheck(); |
479 m_requestStartedSeconds = 0.0; // Unnecessary for synchronous request, b ut for API consistency. | |
449 return; | 480 return; |
450 } | 481 } |
451 | 482 |
452 handleResponse(identifier, response); | 483 handleResponse(identifier, response); |
453 | 484 |
454 SharedBuffer* data = resource->resourceBuffer(); | 485 SharedBuffer* data = resource->resourceBuffer(); |
455 if (data) | 486 if (data) |
456 handleReceivedData(data->data(), data->size()); | 487 handleReceivedData(data->data(), data->size()); |
457 | 488 |
458 handleSuccessfulFinish(identifier, 0.0); | 489 handleSuccessfulFinish(identifier, 0.0); |
(...skipping 13 matching lines...) Expand all Loading... | |
472 return true; | 503 return true; |
473 return m_document.contentSecurityPolicy()->allowConnectToSource(url); | 504 return m_document.contentSecurityPolicy()->allowConnectToSource(url); |
474 } | 505 } |
475 | 506 |
476 SecurityOrigin* DocumentThreadableLoader::securityOrigin() const | 507 SecurityOrigin* DocumentThreadableLoader::securityOrigin() const |
477 { | 508 { |
478 return m_options.securityOrigin ? m_options.securityOrigin.get() : m_documen t.securityOrigin(); | 509 return m_options.securityOrigin ? m_options.securityOrigin.get() : m_documen t.securityOrigin(); |
479 } | 510 } |
480 | 511 |
481 } // namespace WebCore | 512 } // namespace WebCore |
OLD | NEW |