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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 : m_client(client) | 74 : m_client(client) |
75 , m_document(document) | 75 , m_document(document) |
76 , m_options(options) | 76 , m_options(options) |
77 , m_resourceLoaderOptions(resourceLoaderOptions) | 77 , m_resourceLoaderOptions(resourceLoaderOptions) |
78 , m_forceDoNotAllowStoredCredentials(false) | 78 , m_forceDoNotAllowStoredCredentials(false) |
79 , m_securityOrigin(m_resourceLoaderOptions.securityOrigin) | 79 , m_securityOrigin(m_resourceLoaderOptions.securityOrigin) |
80 , m_sameOriginRequest(securityOrigin()->canRequest(request.url())) | 80 , m_sameOriginRequest(securityOrigin()->canRequest(request.url())) |
81 , m_simpleRequest(true) | 81 , m_simpleRequest(true) |
82 , m_async(blockingBehavior == LoadAsynchronously) | 82 , m_async(blockingBehavior == LoadAsynchronously) |
83 , m_timeoutTimer(this, &DocumentThreadableLoader::didTimeout) | 83 , m_timeoutTimer(this, &DocumentThreadableLoader::didTimeout) |
| 84 , m_requestStartedSeconds(0.0) |
84 { | 85 { |
85 ASSERT(client); | 86 ASSERT(client); |
86 // Setting an outgoing referer is only supported in the async code path. | 87 // Setting an outgoing referer is only supported in the async code path. |
87 ASSERT(m_async || request.httpReferrer().isEmpty()); | 88 ASSERT(m_async || request.httpReferrer().isEmpty()); |
88 | 89 |
| 90 m_requestStartedSeconds = monotonicallyIncreasingTime(); |
| 91 |
89 // Save any CORS simple headers on the request here. If this request redirec
ts cross-origin, we cancel the old request | 92 // Save any CORS simple headers on the request here. If this request redirec
ts cross-origin, we cancel the old request |
90 // create a new one, and copy these headers. | 93 // create a new one, and copy these headers. |
91 const HTTPHeaderMap& headerMap = request.httpHeaderFields(); | 94 const HTTPHeaderMap& headerMap = request.httpHeaderFields(); |
92 HTTPHeaderMap::const_iterator end = headerMap.end(); | 95 HTTPHeaderMap::const_iterator end = headerMap.end(); |
93 for (HTTPHeaderMap::const_iterator it = headerMap.begin(); it != end; ++it)
{ | 96 for (HTTPHeaderMap::const_iterator it = headerMap.begin(); it != end; ++it)
{ |
94 if (FetchUtils::isSimpleHeader(it->key, it->value)) | 97 if (FetchUtils::isSimpleHeader(it->key, it->value)) |
95 m_simpleRequestHeaders.add(it->key, it->value); | 98 m_simpleRequestHeaders.add(it->key, it->value); |
96 } | 99 } |
97 | 100 |
98 if (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossO
riginRequests) { | 101 if (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossO
riginRequests) { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 preflightOptions.allowCredentials = DoNotAllowStoredCredentials; | 148 preflightOptions.allowCredentials = DoNotAllowStoredCredentials; |
146 loadRequest(preflightRequest, preflightOptions); | 149 loadRequest(preflightRequest, preflightOptions); |
147 } | 150 } |
148 } | 151 } |
149 } | 152 } |
150 | 153 |
151 DocumentThreadableLoader::~DocumentThreadableLoader() | 154 DocumentThreadableLoader::~DocumentThreadableLoader() |
152 { | 155 { |
153 } | 156 } |
154 | 157 |
| 158 void DocumentThreadableLoader::overrideTimeout(unsigned long timeoutMilliseconds
) |
| 159 { |
| 160 ASSERT(m_async); |
| 161 ASSERT(m_requestStartedSeconds > 0.0); |
| 162 m_timeoutTimer.stop(); |
| 163 // At the time of this method's implementation, it is only ever called by |
| 164 // XMLHttpRequest, when the timeout attribute is set after sending the |
| 165 // request. |
| 166 // |
| 167 // The XHR request says to resolve the time relative to when the request |
| 168 // was initially sent, however other uses of this method may need to |
| 169 // behave differently, in which case this should be re-arranged somehow. |
| 170 if (timeoutMilliseconds) { |
| 171 double elapsedTime = monotonicallyIncreasingTime() - m_requestStartedSec
onds; |
| 172 double nextFire = timeoutMilliseconds / 1000.0; |
| 173 double resolvedTime = std::max(nextFire - elapsedTime, 0.0); |
| 174 m_timeoutTimer.startOneShot(resolvedTime, FROM_HERE); |
| 175 } |
| 176 } |
| 177 |
155 void DocumentThreadableLoader::cancel() | 178 void DocumentThreadableLoader::cancel() |
156 { | 179 { |
157 cancelWithError(ResourceError()); | 180 cancelWithError(ResourceError()); |
158 } | 181 } |
159 | 182 |
160 void DocumentThreadableLoader::cancelWithError(const ResourceError& error) | 183 void DocumentThreadableLoader::cancelWithError(const ResourceError& error) |
161 { | 184 { |
162 RefPtr<DocumentThreadableLoader> protect(this); | 185 RefPtr<DocumentThreadableLoader> protect(this); |
163 | 186 |
164 // Cancel can re-enter and m_resource might be null here as a result. | 187 // Cancel can re-enter and m_resource might be null here as a result. |
165 if (m_client && resource()) { | 188 if (m_client && resource()) { |
166 ResourceError errorForCallback = error; | 189 ResourceError errorForCallback = error; |
167 if (errorForCallback.isNull()) { | 190 if (errorForCallback.isNull()) { |
168 // FIXME: This error is sent to the client in didFail(), so it shoul
d not be an internal one. Use FrameLoaderClient::cancelledError() instead. | 191 // FIXME: This error is sent to the client in didFail(), so it shoul
d not be an internal one. Use FrameLoaderClient::cancelledError() instead. |
169 errorForCallback = ResourceError(errorDomainBlinkInternal, 0, resour
ce()->url().string(), "Load cancelled"); | 192 errorForCallback = ResourceError(errorDomainBlinkInternal, 0, resour
ce()->url().string(), "Load cancelled"); |
170 errorForCallback.setIsCancellation(true); | 193 errorForCallback.setIsCancellation(true); |
171 } | 194 } |
172 m_client->didFail(errorForCallback); | 195 m_client->didFail(errorForCallback); |
173 } | 196 } |
174 clearResource(); | 197 clearResource(); |
175 m_client = 0; | 198 m_client = 0; |
| 199 m_requestStartedSeconds = 0.0; |
176 } | 200 } |
177 | 201 |
178 void DocumentThreadableLoader::setDefersLoading(bool value) | 202 void DocumentThreadableLoader::setDefersLoading(bool value) |
179 { | 203 { |
180 if (resource()) | 204 if (resource()) |
181 resource()->setDefersLoading(value); | 205 resource()->setDefersLoading(value); |
182 } | 206 } |
183 | 207 |
184 void DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequ
est& request, const ResourceResponse& redirectResponse) | 208 void DocumentThreadableLoader::redirectReceived(Resource* resource, ResourceRequ
est& request, const ResourceResponse& redirectResponse) |
185 { | 209 { |
186 ASSERT(m_client); | 210 ASSERT(m_client); |
187 ASSERT_UNUSED(resource, resource == this->resource()); | 211 ASSERT_UNUSED(resource, resource == this->resource()); |
188 | 212 |
189 RefPtr<DocumentThreadableLoader> protect(this); | 213 RefPtr<DocumentThreadableLoader> protect(this); |
190 | 214 |
191 // FIXME: Support redirect in Fetch API. | 215 // FIXME: Support redirect in Fetch API. |
192 if (resource->resourceRequest().requestContext() == blink::WebURLRequest::Re
questContextFetch) { | 216 if (resource->resourceRequest().requestContext() == blink::WebURLRequest::Re
questContextFetch) { |
193 m_client->didFailRedirectCheck(); | 217 m_client->didFailRedirectCheck(); |
194 request = ResourceRequest(); | 218 request = ResourceRequest(); |
195 return; | 219 return; |
196 } | 220 } |
197 | 221 |
198 if (!isAllowedByPolicy(request.url())) { | 222 if (!isAllowedByPolicy(request.url())) { |
199 m_client->didFailRedirectCheck(); | 223 m_client->didFailRedirectCheck(); |
200 request = ResourceRequest(); | 224 request = ResourceRequest(); |
| 225 m_requestStartedSeconds = 0.0; |
201 return; | 226 return; |
202 } | 227 } |
203 | 228 |
204 // Allow same origin requests to continue after allowing clients to audit th
e redirect. | 229 // Allow same origin requests to continue after allowing clients to audit th
e redirect. |
205 if (isAllowedRedirect(request.url())) { | 230 if (isAllowedRedirect(request.url())) { |
206 if (m_client->isDocumentThreadableLoaderClient()) | 231 if (m_client->isDocumentThreadableLoaderClient()) |
207 static_cast<DocumentThreadableLoaderClient*>(m_client)->willSendRequ
est(request, redirectResponse); | 232 static_cast<DocumentThreadableLoaderClient*>(m_client)->willSendRequ
est(request, redirectResponse); |
208 return; | 233 return; |
209 } | 234 } |
210 | 235 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 makeCrossOriginAccessRequest(request); | 282 makeCrossOriginAccessRequest(request); |
258 return; | 283 return; |
259 } | 284 } |
260 | 285 |
261 ResourceError error(errorDomainBlinkInternal, 0, redirectResponse.url().
string(), accessControlErrorDescription); | 286 ResourceError error(errorDomainBlinkInternal, 0, redirectResponse.url().
string(), accessControlErrorDescription); |
262 m_client->didFailAccessControlCheck(error); | 287 m_client->didFailAccessControlCheck(error); |
263 } else { | 288 } else { |
264 m_client->didFailRedirectCheck(); | 289 m_client->didFailRedirectCheck(); |
265 } | 290 } |
266 request = ResourceRequest(); | 291 request = ResourceRequest(); |
| 292 m_requestStartedSeconds = 0.0; |
267 } | 293 } |
268 | 294 |
269 void DocumentThreadableLoader::dataSent(Resource* resource, unsigned long long b
ytesSent, unsigned long long totalBytesToBeSent) | 295 void DocumentThreadableLoader::dataSent(Resource* resource, unsigned long long b
ytesSent, unsigned long long totalBytesToBeSent) |
270 { | 296 { |
271 ASSERT(m_client); | 297 ASSERT(m_client); |
272 ASSERT_UNUSED(resource, resource == this->resource()); | 298 ASSERT_UNUSED(resource, resource == this->resource()); |
273 m_client->didSendData(bytesSent, totalBytesToBeSent); | 299 m_client->didSendData(bytesSent, totalBytesToBeSent); |
274 } | 300 } |
275 | 301 |
276 void DocumentThreadableLoader::dataDownloaded(Resource* resource, int dataLength
) | 302 void DocumentThreadableLoader::dataDownloaded(Resource* resource, int dataLength
) |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 handleSuccessfulFinish(resource->identifier(), resource->loadFinishTime(
)); | 415 handleSuccessfulFinish(resource->identifier(), resource->loadFinishTime(
)); |
390 } | 416 } |
391 | 417 |
392 void DocumentThreadableLoader::handleSuccessfulFinish(unsigned long identifier,
double finishTime) | 418 void DocumentThreadableLoader::handleSuccessfulFinish(unsigned long identifier,
double finishTime) |
393 { | 419 { |
394 if (m_actualRequest) { | 420 if (m_actualRequest) { |
395 ASSERT(!m_sameOriginRequest); | 421 ASSERT(!m_sameOriginRequest); |
396 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); | 422 ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); |
397 loadActualRequest(); | 423 loadActualRequest(); |
398 } else { | 424 } else { |
| 425 // FIXME: Should prevent timeout from being overridden after finished lo
ading, without |
| 426 // resetting m_requestStartedSeconds to 0.0 |
399 m_client->didFinishLoading(identifier, finishTime); | 427 m_client->didFinishLoading(identifier, finishTime); |
400 } | 428 } |
401 } | 429 } |
402 | 430 |
403 void DocumentThreadableLoader::didTimeout(Timer<DocumentThreadableLoader>* timer
) | 431 void DocumentThreadableLoader::didTimeout(Timer<DocumentThreadableLoader>* timer
) |
404 { | 432 { |
405 ASSERT_UNUSED(timer, timer == &m_timeoutTimer); | 433 ASSERT_UNUSED(timer, timer == &m_timeoutTimer); |
406 | 434 |
407 // Using values from net/base/net_error_list.h ERR_TIMED_OUT, | 435 // Using values from net/base/net_error_list.h ERR_TIMED_OUT, |
408 // Same as existing FIXME above - this error should be coming from FrameLoad
erClient to be identifiable. | 436 // Same as existing FIXME above - this error should be coming from FrameLoad
erClient to be identifiable. |
(...skipping 17 matching lines...) Expand all Loading... |
426 loadRequest(*actualRequest, *actualOptions); | 454 loadRequest(*actualRequest, *actualOptions); |
427 } | 455 } |
428 | 456 |
429 void DocumentThreadableLoader::handlePreflightFailure(const String& url, const S
tring& errorDescription) | 457 void DocumentThreadableLoader::handlePreflightFailure(const String& url, const S
tring& errorDescription) |
430 { | 458 { |
431 ResourceError error(errorDomainBlinkInternal, 0, url, errorDescription); | 459 ResourceError error(errorDomainBlinkInternal, 0, url, errorDescription); |
432 | 460 |
433 // Prevent handleSuccessfulFinish() from bypassing access check. | 461 // Prevent handleSuccessfulFinish() from bypassing access check. |
434 m_actualRequest = nullptr; | 462 m_actualRequest = nullptr; |
435 | 463 |
| 464 // FIXME: Should prevent timeout from being overridden after preflight failu
re, without |
| 465 // resetting m_requestStartedSeconds to 0.0 |
436 m_client->didFailAccessControlCheck(error); | 466 m_client->didFailAccessControlCheck(error); |
437 } | 467 } |
438 | 468 |
439 void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, Resou
rceLoaderOptions resourceLoaderOptions) | 469 void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, Resou
rceLoaderOptions resourceLoaderOptions) |
440 { | 470 { |
441 // Any credential should have been removed from the cross-site requests. | 471 // Any credential should have been removed from the cross-site requests. |
442 const KURL& requestURL = request.url(); | 472 const KURL& requestURL = request.url(); |
443 ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); | 473 ASSERT(m_sameOriginRequest || requestURL.user().isEmpty()); |
444 ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); | 474 ASSERT(m_sameOriginRequest || requestURL.pass().isEmpty()); |
445 | 475 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 return DoNotAllowStoredCredentials; | 561 return DoNotAllowStoredCredentials; |
532 return m_resourceLoaderOptions.allowCredentials; | 562 return m_resourceLoaderOptions.allowCredentials; |
533 } | 563 } |
534 | 564 |
535 SecurityOrigin* DocumentThreadableLoader::securityOrigin() const | 565 SecurityOrigin* DocumentThreadableLoader::securityOrigin() const |
536 { | 566 { |
537 return m_securityOrigin ? m_securityOrigin.get() : m_document.securityOrigin
(); | 567 return m_securityOrigin ? m_securityOrigin.get() : m_document.securityOrigin
(); |
538 } | 568 } |
539 | 569 |
540 } // namespace blink | 570 } // namespace blink |
OLD | NEW |