OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved. |
3 * Copyright (C) 2005-2007 Alexey Proskuryakov <ap@webkit.org> | 3 * Copyright (C) 2005-2007 Alexey Proskuryakov <ap@webkit.org> |
4 * Copyright (C) 2007, 2008 Julien Chaffraix <jchaffraix@webkit.org> | 4 * Copyright (C) 2007, 2008 Julien Chaffraix <jchaffraix@webkit.org> |
5 * Copyright (C) 2008, 2011 Google Inc. All rights reserved. | 5 * Copyright (C) 2008, 2011 Google Inc. All rights reserved. |
6 * Copyright (C) 2012 Intel Corporation | 6 * Copyright (C) 2012 Intel Corporation |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Lesser General Public | 9 * modify it under the terms of the GNU Lesser General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
268 } | 268 } |
269 m_createdDocument = true; | 269 m_createdDocument = true; |
270 } | 270 } |
271 | 271 |
272 return m_responseDocument.get(); | 272 return m_responseDocument.get(); |
273 } | 273 } |
274 | 274 |
275 Blob* XMLHttpRequest::responseBlob() | 275 Blob* XMLHttpRequest::responseBlob() |
276 { | 276 { |
277 ASSERT(m_responseTypeCode == ResponseTypeBlob); | 277 ASSERT(m_responseTypeCode == ResponseTypeBlob); |
278 ASSERT(!m_binaryResponseBuilder.get()); | |
278 | 279 |
279 // We always return null before DONE. | 280 // We always return null before DONE. |
280 if (m_error || m_state != DONE) | 281 if (m_error || m_state != DONE) |
281 return 0; | 282 return 0; |
282 | 283 |
283 if (!m_responseBlob) { | 284 if (!m_responseBlob) { |
284 // FIXME: This causes two (or more) unnecessary copies of the data. | 285 // When "blob" is specified for the responseType attribute, |
285 // Chromium stores blob data in the browser process, so we're pulling th e data | 286 // we redirect the downloaded data to a file-handle directly |
286 // from the network only to copy it into the renderer to copy it back to the browser. | 287 // in the browser process. |
287 // Ideally we'd get the blob/file-handle from the ResourceResponse direc tly | 288 // We get the file-path from the ResourceResponse directly |
288 // instead of copying the bytes. Embedders who store blob data in the | 289 // instead of copying the bytes between the browser and the renderer. |
289 // same process as WebCore would at least to teach BlobData to take | |
290 // a SharedBuffer, even if they don't get the Blob from the network laye r directly. | |
291 OwnPtr<BlobData> blobData = BlobData::create(); | 290 OwnPtr<BlobData> blobData = BlobData::create(); |
291 const String& filePath = m_response.downloadedFilePath(); | |
292 // If we errored out or got no data, we still return a blob, just an emp ty one. | 292 // If we errored out or got no data, we still return a blob, just an emp ty one. |
293 size_t size = 0; | 293 if (!filePath.isEmpty() && m_receivedLength) { |
294 if (m_binaryResponseBuilder) { | 294 blobData->appendFile(filePath); |
295 RefPtr<RawData> rawData = RawData::create(); | |
296 size = m_binaryResponseBuilder->size(); | |
297 rawData->mutableData()->append(m_binaryResponseBuilder->data(), size ); | |
298 blobData->appendData(rawData, 0, BlobDataItem::toEndOfFile); | |
299 blobData->setContentType(responseMIMEType()); // responseMIMEType de faults to text/xml which may be incorrect. | 295 blobData->setContentType(responseMIMEType()); // responseMIMEType de faults to text/xml which may be incorrect. |
300 m_binaryResponseBuilder.clear(); | |
301 } | 296 } |
302 m_responseBlob = Blob::create(blobData.release(), size); | 297 m_responseBlob = Blob::create(blobData.release(), m_receivedLength); |
303 } | 298 } |
304 | 299 |
305 return m_responseBlob.get(); | 300 return m_responseBlob.get(); |
306 } | 301 } |
307 | 302 |
308 ArrayBuffer* XMLHttpRequest::responseArrayBuffer() | 303 ArrayBuffer* XMLHttpRequest::responseArrayBuffer() |
309 { | 304 { |
310 ASSERT(m_responseTypeCode == ResponseTypeArrayBuffer); | 305 ASSERT(m_responseTypeCode == ResponseTypeArrayBuffer); |
311 | 306 |
312 if (m_error || m_state != DONE) | 307 if (m_error || m_state != DONE) |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
404 return ""; | 399 return ""; |
405 } | 400 } |
406 | 401 |
407 XMLHttpRequestUpload* XMLHttpRequest::upload() | 402 XMLHttpRequestUpload* XMLHttpRequest::upload() |
408 { | 403 { |
409 if (!m_upload) | 404 if (!m_upload) |
410 m_upload = XMLHttpRequestUpload::create(this); | 405 m_upload = XMLHttpRequestUpload::create(this); |
411 return m_upload.get(); | 406 return m_upload.get(); |
412 } | 407 } |
413 | 408 |
409 void XMLHttpRequest::trackProgress(int len) | |
abarth-chromium
2013/10/13 05:20:30
len -> length
yusukesuzuki
2013/10/24 15:22:41
Done.
| |
410 { | |
411 long long expectedLength = m_response.expectedContentLength(); | |
412 m_receivedLength += len; | |
413 | |
414 if (m_async) { | |
415 bool lengthComputable = expectedLength > 0 && m_receivedLength <= expect edLength; | |
416 unsigned long long total = lengthComputable ? expectedLength : 0; | |
417 m_progressEventThrottle.dispatchProgressEvent(lengthComputable, m_receiv edLength, total); | |
418 } | |
419 | |
420 if (m_state != LOADING) { | |
421 changeState(LOADING); | |
422 } else { | |
423 // Firefox calls readyStateChanged every time it receives data, 4449442 | |
abarth-chromium
2013/10/13 05:20:30
4449442 <-- What is this number? Can we make it a
tyoshino (SeeGerritForStatus)
2013/10/16 07:57:56
This is Apple Radar ID. I've replaced this with ex
yusukesuzuki
2013/10/24 15:22:41
Right. I've rebased and this issue is fixed by tha
| |
424 callReadyStateChangeListener(); | |
425 } | |
426 } | |
427 | |
414 void XMLHttpRequest::changeState(State newState) | 428 void XMLHttpRequest::changeState(State newState) |
415 { | 429 { |
416 if (m_state != newState) { | 430 if (m_state != newState) { |
417 m_state = newState; | 431 m_state = newState; |
418 callReadyStateChangeListener(); | 432 callReadyStateChangeListener(); |
419 } | 433 } |
420 } | 434 } |
421 | 435 |
422 void XMLHttpRequest::callReadyStateChangeListener() | 436 void XMLHttpRequest::callReadyStateChangeListener() |
423 { | 437 { |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
746 m_sameOriginRequest = securityOrigin()->canRequest(m_url); | 760 m_sameOriginRequest = securityOrigin()->canRequest(m_url); |
747 | 761 |
748 // We also remember whether upload events should be allowed for this request in case the upload listeners are | 762 // We also remember whether upload events should be allowed for this request in case the upload listeners are |
749 // added after the request is started. | 763 // added after the request is started. |
750 m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !isSimpleCros sOriginAccessRequest(m_method, m_requestHeaders); | 764 m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !isSimpleCros sOriginAccessRequest(m_method, m_requestHeaders); |
751 | 765 |
752 ResourceRequest request(m_url); | 766 ResourceRequest request(m_url); |
753 request.setHTTPMethod(m_method); | 767 request.setHTTPMethod(m_method); |
754 request.setTargetType(ResourceRequest::TargetIsXHR); | 768 request.setTargetType(ResourceRequest::TargetIsXHR); |
755 | 769 |
770 // When "blob" is specified for the responseType attribute, | |
771 // we redirect the downloaded data to a file-handle directly | |
772 // and get the file-path as the result. | |
773 if (responseTypeCode() == ResponseTypeBlob) | |
774 request.setDownloadToFile(true); | |
775 | |
756 InspectorInstrumentation::willLoadXHR(scriptExecutionContext(), this, m_meth od, m_url, m_async, m_requestEntityBody ? m_requestEntityBody->deepCopy() : 0, m _requestHeaders, m_includeCredentials); | 776 InspectorInstrumentation::willLoadXHR(scriptExecutionContext(), this, m_meth od, m_url, m_async, m_requestEntityBody ? m_requestEntityBody->deepCopy() : 0, m _requestHeaders, m_includeCredentials); |
757 | 777 |
758 if (m_requestEntityBody) { | 778 if (m_requestEntityBody) { |
759 ASSERT(m_method != "GET"); | 779 ASSERT(m_method != "GET"); |
760 ASSERT(m_method != "HEAD"); | 780 ASSERT(m_method != "HEAD"); |
761 request.setHTTPBody(m_requestEntityBody.release()); | 781 request.setHTTPBody(m_requestEntityBody.release()); |
762 } | 782 } |
763 | 783 |
764 if (m_requestHeaders.size() > 0) | 784 if (m_requestHeaders.size() > 0) |
765 request.addHTTPHeaderFields(m_requestHeaders); | 785 request.addHTTPHeaderFields(m_requestHeaders); |
766 | 786 |
767 ThreadableLoaderOptions options; | 787 ThreadableLoaderOptions options; |
768 options.sendLoadCallbacks = SendCallbacks; | 788 options.sendLoadCallbacks = SendCallbacks; |
769 options.sniffContent = DoNotSniffContent; | 789 options.sniffContent = DoNotSniffContent; |
770 options.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight; | 790 options.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight; |
771 options.allowCredentials = (m_sameOriginRequest || m_includeCredentials) ? A llowStoredCredentials : DoNotAllowStoredCredentials; | 791 options.allowCredentials = (m_sameOriginRequest || m_includeCredentials) ? A llowStoredCredentials : DoNotAllowStoredCredentials; |
772 options.credentialsRequested = m_includeCredentials ? ClientRequestedCredent ials : ClientDidNotRequestCredentials; | 792 options.credentialsRequested = m_includeCredentials ? ClientRequestedCredent ials : ClientDidNotRequestCredentials; |
773 options.crossOriginRequestPolicy = UseAccessControl; | 793 options.crossOriginRequestPolicy = UseAccessControl; |
774 options.securityOrigin = securityOrigin(); | 794 options.securityOrigin = securityOrigin(); |
775 options.initiator = FetchInitiatorTypeNames::xmlhttprequest; | 795 options.initiator = FetchInitiatorTypeNames::xmlhttprequest; |
776 options.contentSecurityPolicyEnforcement = ContentSecurityPolicy::shouldBypa ssMainWorld(scriptExecutionContext()) ? DoNotEnforceContentSecurityPolicy : Enfo rceConnectSrcDirective; | 796 options.contentSecurityPolicyEnforcement = ContentSecurityPolicy::shouldBypa ssMainWorld(scriptExecutionContext()) ? DoNotEnforceContentSecurityPolicy : Enfo rceConnectSrcDirective; |
777 options.mixedContentBlockingTreatment = TreatAsActiveContent; | 797 options.mixedContentBlockingTreatment = TreatAsActiveContent; |
778 options.timeoutMilliseconds = m_timeoutMilliseconds; | 798 options.timeoutMilliseconds = m_timeoutMilliseconds; |
779 | 799 |
800 // Since we redirect the downloaded data to a file-handle directly | |
801 // when "blob" is specified for the responseType attribute, | |
802 // buffering is not needed. | |
803 if (responseTypeCode() == ResponseTypeBlob) | |
804 options.dataBufferingPolicy = DoNotBufferData; | |
805 | |
780 m_exceptionCode = 0; | 806 m_exceptionCode = 0; |
781 m_error = false; | 807 m_error = false; |
782 | 808 |
783 if (m_async) { | 809 if (m_async) { |
784 if (m_upload) | 810 if (m_upload) |
785 request.setReportUploadProgress(true); | 811 request.setReportUploadProgress(true); |
786 | 812 |
787 // ThreadableLoader::create can return null here, for example if we're n o longer attached to a page. | 813 // ThreadableLoader::create can return null here, for example if we're n o longer attached to a page. |
788 // This is true while running onunload handlers. | 814 // This is true while running onunload handlers. |
789 // FIXME: Maybe we need to be able to send XMLHttpRequests from onunload , <http://bugs.webkit.org/show_bug.cgi?id=10904>. | 815 // FIXME: Maybe we need to be able to send XMLHttpRequests from onunload , <http://bugs.webkit.org/show_bug.cgi?id=10904>. |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1195 m_response.setHTTPHeaderField("Content-Type", m_mimeTypeOverride); | 1221 m_response.setHTTPHeaderField("Content-Type", m_mimeTypeOverride); |
1196 m_responseEncoding = extractCharsetFromMediaType(m_mimeTypeOverride); | 1222 m_responseEncoding = extractCharsetFromMediaType(m_mimeTypeOverride); |
1197 } | 1223 } |
1198 | 1224 |
1199 if (m_responseEncoding.isEmpty()) | 1225 if (m_responseEncoding.isEmpty()) |
1200 m_responseEncoding = response.textEncodingName(); | 1226 m_responseEncoding = response.textEncodingName(); |
1201 } | 1227 } |
1202 | 1228 |
1203 void XMLHttpRequest::didReceiveData(const char* data, int len) | 1229 void XMLHttpRequest::didReceiveData(const char* data, int len) |
1204 { | 1230 { |
1231 ASSERT(m_responseTypeCode != ResponseTypeBlob); | |
1232 | |
1205 if (m_error) | 1233 if (m_error) |
1206 return; | 1234 return; |
1207 | 1235 |
1208 if (m_state < HEADERS_RECEIVED) | 1236 if (m_state < HEADERS_RECEIVED) |
1209 changeState(HEADERS_RECEIVED); | 1237 changeState(HEADERS_RECEIVED); |
1210 | 1238 |
1211 bool useDecoder = m_responseTypeCode == ResponseTypeDefault || m_responseTyp eCode == ResponseTypeText || m_responseTypeCode == ResponseTypeJSON || m_respons eTypeCode == ResponseTypeDocument; | 1239 bool useDecoder = m_responseTypeCode == ResponseTypeDefault || m_responseTyp eCode == ResponseTypeText || m_responseTypeCode == ResponseTypeJSON || m_respons eTypeCode == ResponseTypeDocument; |
1212 | 1240 |
1213 if (useDecoder && !m_decoder) { | 1241 if (useDecoder && !m_decoder) { |
1214 if (m_responseTypeCode == ResponseTypeJSON) | 1242 if (m_responseTypeCode == ResponseTypeJSON) |
(...skipping 12 matching lines...) Expand all Loading... | |
1227 } | 1255 } |
1228 | 1256 |
1229 if (!len) | 1257 if (!len) |
1230 return; | 1258 return; |
1231 | 1259 |
1232 if (len == -1) | 1260 if (len == -1) |
1233 len = strlen(data); | 1261 len = strlen(data); |
1234 | 1262 |
1235 if (useDecoder) { | 1263 if (useDecoder) { |
1236 m_responseText = m_responseText.concatenateWith(m_decoder->decode(data, len)); | 1264 m_responseText = m_responseText.concatenateWith(m_decoder->decode(data, len)); |
1237 } else if (m_responseTypeCode == ResponseTypeArrayBuffer || m_responseTypeCo de == ResponseTypeBlob) { | 1265 } else if (m_responseTypeCode == ResponseTypeArrayBuffer) { |
1238 // Buffer binary data. | 1266 // Buffer binary data. |
1239 if (!m_binaryResponseBuilder) | 1267 if (!m_binaryResponseBuilder) |
1240 m_binaryResponseBuilder = SharedBuffer::create(); | 1268 m_binaryResponseBuilder = SharedBuffer::create(); |
1241 m_binaryResponseBuilder->append(data, len); | 1269 m_binaryResponseBuilder->append(data, len); |
1242 } else if (m_responseTypeCode == ResponseTypeStream) { | 1270 } else if (m_responseTypeCode == ResponseTypeStream) { |
1243 if (!m_responseStream) | 1271 if (!m_responseStream) |
1244 m_responseStream = Stream::create(responseMIMEType()); | 1272 m_responseStream = Stream::create(responseMIMEType()); |
1245 m_responseStream->addData(data, len); | 1273 m_responseStream->addData(data, len); |
1246 } | 1274 } |
1247 | 1275 |
1248 if (!m_error) { | 1276 if (!m_error) |
1249 long long expectedLength = m_response.expectedContentLength(); | 1277 trackProgress(len); |
1250 m_receivedLength += len; | 1278 } |
1251 | 1279 |
1252 if (m_async) { | 1280 void XMLHttpRequest::didDownloadData(int len) |
1253 bool lengthComputable = expectedLength > 0 && m_receivedLength <= ex pectedLength; | 1281 { |
1254 unsigned long long total = lengthComputable ? expectedLength : 0; | 1282 ASSERT(m_responseTypeCode == ResponseTypeBlob); |
1255 m_progressEventThrottle.dispatchProgressEvent(lengthComputable, m_re ceivedLength, total); | |
1256 } | |
1257 | 1283 |
1258 if (m_state != LOADING) | 1284 if (m_error) |
1259 changeState(LOADING); | 1285 return; |
1260 else | 1286 |
1261 // Firefox calls readyStateChanged every time it receives data, 4449 442 | 1287 if (m_state < HEADERS_RECEIVED) |
1262 callReadyStateChangeListener(); | 1288 changeState(HEADERS_RECEIVED); |
1263 } | 1289 |
1290 if (!len) | |
1291 return; | |
1292 | |
1293 if (!m_error) | |
1294 trackProgress(len); | |
1264 } | 1295 } |
1265 | 1296 |
1266 void XMLHttpRequest::handleDidTimeout() | 1297 void XMLHttpRequest::handleDidTimeout() |
1267 { | 1298 { |
1268 // internalAbort() calls dropProtection(), which may release the last refere nce. | 1299 // internalAbort() calls dropProtection(), which may release the last refere nce. |
1269 RefPtr<XMLHttpRequest> protect(this); | 1300 RefPtr<XMLHttpRequest> protect(this); |
1270 | 1301 |
1271 if (!internalAbort()) | 1302 if (!internalAbort()) |
1272 return; | 1303 return; |
1273 | 1304 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1314 { | 1345 { |
1315 return eventNames().interfaceForXMLHttpRequest; | 1346 return eventNames().interfaceForXMLHttpRequest; |
1316 } | 1347 } |
1317 | 1348 |
1318 ScriptExecutionContext* XMLHttpRequest::scriptExecutionContext() const | 1349 ScriptExecutionContext* XMLHttpRequest::scriptExecutionContext() const |
1319 { | 1350 { |
1320 return ActiveDOMObject::scriptExecutionContext(); | 1351 return ActiveDOMObject::scriptExecutionContext(); |
1321 } | 1352 } |
1322 | 1353 |
1323 } // namespace WebCore | 1354 } // namespace WebCore |
OLD | NEW |