Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(704)

Side by Side Diff: Source/core/loader/DocumentThreadableLoader.cpp

Issue 273993002: Allow XHR timeout attribute to be overridden after send(), per spec (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Reset m_requestStartedSeconds in a few extra places +fix bitrot Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/core/loader/DocumentThreadableLoader.h ('k') | Source/core/loader/ThreadableLoader.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « Source/core/loader/DocumentThreadableLoader.h ('k') | Source/core/loader/ThreadableLoader.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698