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 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
269 } | 269 } |
270 m_createdDocument = true; | 270 m_createdDocument = true; |
271 } | 271 } |
272 | 272 |
273 return m_responseDocument.get(); | 273 return m_responseDocument.get(); |
274 } | 274 } |
275 | 275 |
276 Blob* XMLHttpRequest::responseBlob() | 276 Blob* XMLHttpRequest::responseBlob() |
277 { | 277 { |
278 ASSERT(m_responseTypeCode == ResponseTypeBlob); | 278 ASSERT(m_responseTypeCode == ResponseTypeBlob); |
279 ASSERT(!m_binaryResponseBuilder.get()); | |
279 | 280 |
280 // We always return null before DONE. | 281 // We always return null before DONE. |
281 if (m_error || m_state != DONE) | 282 if (m_error || m_state != DONE) |
282 return 0; | 283 return 0; |
283 | 284 |
284 if (!m_responseBlob) { | 285 if (!m_responseBlob) { |
285 // FIXME: This causes two (or more) unnecessary copies of the data. | 286 // When "blob" is specified for the responseType attribute, |
286 // Chromium stores blob data in the browser process, so we're pulling th e data | 287 // we redirect the downloaded data to a file-handle directly |
287 // from the network only to copy it into the renderer to copy it back to the browser. | 288 // in the browser process. |
288 // Ideally we'd get the blob/file-handle from the ResourceResponse direc tly | 289 // We get the file-path from the ResourceResponse directly |
289 // instead of copying the bytes. Embedders who store blob data in the | 290 // instead of copying the bytes between the browser and the renderer. |
290 // same process as WebCore would at least to teach BlobData to take | |
291 // a SharedBuffer, even if they don't get the Blob from the network laye r directly. | |
292 OwnPtr<BlobData> blobData = BlobData::create(); | 291 OwnPtr<BlobData> blobData = BlobData::create(); |
292 const String& filePath = m_response.downloadedFilePath(); | |
293 // If we errored out or got no data, we still return a blob, just an emp ty one. | 293 // If we errored out or got no data, we still return a blob, just an emp ty one. |
294 size_t size = 0; | 294 if (!filePath.isEmpty() && m_receivedLength) { |
295 if (m_binaryResponseBuilder) { | 295 blobData->appendFile(filePath); |
296 RefPtr<RawData> rawData = RawData::create(); | |
297 size = m_binaryResponseBuilder->size(); | |
298 rawData->mutableData()->append(m_binaryResponseBuilder->data(), size ); | |
299 blobData->appendData(rawData, 0, BlobDataItem::toEndOfFile); | |
300 blobData->setContentType(responseMIMEType()); // responseMIMEType de faults to text/xml which may be incorrect. | 296 blobData->setContentType(responseMIMEType()); // responseMIMEType de faults to text/xml which may be incorrect. |
301 m_binaryResponseBuilder.clear(); | |
302 } | 297 } |
303 m_responseBlob = Blob::create(blobData.release(), size); | 298 m_responseBlob = Blob::create(blobData.release(), m_receivedLength); |
304 } | 299 } |
305 | 300 |
306 return m_responseBlob.get(); | 301 return m_responseBlob.get(); |
307 } | 302 } |
308 | 303 |
309 ArrayBuffer* XMLHttpRequest::responseArrayBuffer() | 304 ArrayBuffer* XMLHttpRequest::responseArrayBuffer() |
310 { | 305 { |
311 ASSERT(m_responseTypeCode == ResponseTypeArrayBuffer); | 306 ASSERT(m_responseTypeCode == ResponseTypeArrayBuffer); |
312 | 307 |
313 if (m_error || m_state != DONE) | 308 if (m_error || m_state != DONE) |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
405 return ""; | 400 return ""; |
406 } | 401 } |
407 | 402 |
408 XMLHttpRequestUpload* XMLHttpRequest::upload() | 403 XMLHttpRequestUpload* XMLHttpRequest::upload() |
409 { | 404 { |
410 if (!m_upload) | 405 if (!m_upload) |
411 m_upload = XMLHttpRequestUpload::create(this); | 406 m_upload = XMLHttpRequestUpload::create(this); |
412 return m_upload.get(); | 407 return m_upload.get(); |
413 } | 408 } |
414 | 409 |
410 void XMLHttpRequest::trackProgress(int len) | |
411 { | |
412 long long expectedLength = m_response.expectedContentLength(); | |
413 m_receivedLength += len; | |
414 | |
415 if (m_async) { | |
416 bool lengthComputable = expectedLength > 0 && m_receivedLength <= expect edLength; | |
417 unsigned long long total = lengthComputable ? expectedLength : 0; | |
418 m_progressEventThrottle.dispatchProgressEvent(lengthComputable, m_receiv edLength, total); | |
419 } | |
420 | |
421 if (m_state != LOADING) { | |
422 changeState(LOADING); | |
423 } else { | |
424 // Firefox calls readyStateChanged every time it receives data, 4449442 | |
425 callReadyStateChangeListener(); | |
426 } | |
427 } | |
428 | |
415 void XMLHttpRequest::changeState(State newState) | 429 void XMLHttpRequest::changeState(State newState) |
416 { | 430 { |
417 if (m_state != newState) { | 431 if (m_state != newState) { |
418 m_state = newState; | 432 m_state = newState; |
419 callReadyStateChangeListener(); | 433 callReadyStateChangeListener(); |
420 } | 434 } |
421 } | 435 } |
422 | 436 |
423 void XMLHttpRequest::callReadyStateChangeListener() | 437 void XMLHttpRequest::callReadyStateChangeListener() |
424 { | 438 { |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
745 m_sameOriginRequest = securityOrigin()->canRequest(m_url); | 759 m_sameOriginRequest = securityOrigin()->canRequest(m_url); |
746 | 760 |
747 // We also remember whether upload events should be allowed for this request in case the upload listeners are | 761 // We also remember whether upload events should be allowed for this request in case the upload listeners are |
748 // added after the request is started. | 762 // added after the request is started. |
749 m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !isSimpleCros sOriginAccessRequest(m_method, m_requestHeaders); | 763 m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !isSimpleCros sOriginAccessRequest(m_method, m_requestHeaders); |
750 | 764 |
751 ResourceRequest request(m_url); | 765 ResourceRequest request(m_url); |
752 request.setHTTPMethod(m_method); | 766 request.setHTTPMethod(m_method); |
753 request.setTargetType(ResourceRequest::TargetIsXHR); | 767 request.setTargetType(ResourceRequest::TargetIsXHR); |
754 | 768 |
769 // When "blob" is specified for the responseType attribute, | |
770 // we redirect the downloaded data to a file-handle directly | |
yusukesuzuki
2013/09/19 07:34:34
Fixed comment.
| |
771 // and get the file-path as the result. | |
772 if (responseTypeCode() == ResponseTypeBlob) | |
773 request.setDownloadToFile(true); | |
774 | |
755 InspectorInstrumentation::willLoadXHR(scriptExecutionContext(), this, m_meth od, m_url, m_async, m_requestEntityBody ? m_requestEntityBody->deepCopy() : 0, m _requestHeaders, m_includeCredentials); | 775 InspectorInstrumentation::willLoadXHR(scriptExecutionContext(), this, m_meth od, m_url, m_async, m_requestEntityBody ? m_requestEntityBody->deepCopy() : 0, m _requestHeaders, m_includeCredentials); |
756 | 776 |
757 if (m_requestEntityBody) { | 777 if (m_requestEntityBody) { |
758 ASSERT(m_method != "GET"); | 778 ASSERT(m_method != "GET"); |
759 ASSERT(m_method != "HEAD"); | 779 ASSERT(m_method != "HEAD"); |
760 request.setHTTPBody(m_requestEntityBody.release()); | 780 request.setHTTPBody(m_requestEntityBody.release()); |
761 } | 781 } |
762 | 782 |
763 if (m_requestHeaders.size() > 0) | 783 if (m_requestHeaders.size() > 0) |
764 request.addHTTPHeaderFields(m_requestHeaders); | 784 request.addHTTPHeaderFields(m_requestHeaders); |
765 | 785 |
766 ThreadableLoaderOptions options; | 786 ThreadableLoaderOptions options; |
767 options.sendLoadCallbacks = SendCallbacks; | 787 options.sendLoadCallbacks = SendCallbacks; |
768 options.sniffContent = DoNotSniffContent; | 788 options.sniffContent = DoNotSniffContent; |
769 options.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight; | 789 options.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight; |
770 options.allowCredentials = (m_sameOriginRequest || m_includeCredentials) ? A llowStoredCredentials : DoNotAllowStoredCredentials; | 790 options.allowCredentials = (m_sameOriginRequest || m_includeCredentials) ? A llowStoredCredentials : DoNotAllowStoredCredentials; |
771 options.credentialsRequested = m_includeCredentials ? ClientRequestedCredent ials : ClientDidNotRequestCredentials; | 791 options.credentialsRequested = m_includeCredentials ? ClientRequestedCredent ials : ClientDidNotRequestCredentials; |
772 options.crossOriginRequestPolicy = m_allowCrossOriginRequests ? AllowCrossOr iginRequests : UseAccessControl; | 792 options.crossOriginRequestPolicy = m_allowCrossOriginRequests ? AllowCrossOr iginRequests : UseAccessControl; |
773 options.securityOrigin = securityOrigin(); | 793 options.securityOrigin = securityOrigin(); |
774 options.initiator = FetchInitiatorTypeNames::xmlhttprequest; | 794 options.initiator = FetchInitiatorTypeNames::xmlhttprequest; |
775 options.contentSecurityPolicyEnforcement = ContentSecurityPolicy::shouldBypa ssMainWorld(scriptExecutionContext()) ? DoNotEnforceContentSecurityPolicy : Enfo rceConnectSrcDirective; | 795 options.contentSecurityPolicyEnforcement = ContentSecurityPolicy::shouldBypa ssMainWorld(scriptExecutionContext()) ? DoNotEnforceContentSecurityPolicy : Enfo rceConnectSrcDirective; |
776 options.mixedContentBlockingTreatment = TreatAsActiveContent; | 796 options.mixedContentBlockingTreatment = TreatAsActiveContent; |
777 options.timeoutMilliseconds = m_timeoutMilliseconds; | 797 options.timeoutMilliseconds = m_timeoutMilliseconds; |
778 | 798 |
799 // Since we redirect the downloaded data to a file-handle directly | |
yusukesuzuki
2013/09/19 07:34:34
Fixed comment.
| |
800 // when "blob" is specified for the responseType attribute, | |
801 // buffering is not needed. | |
802 if (responseTypeCode() == ResponseTypeBlob) | |
803 options.dataBufferingPolicy = DoNotBufferData; | |
804 | |
779 m_exceptionCode = 0; | 805 m_exceptionCode = 0; |
780 m_error = false; | 806 m_error = false; |
781 | 807 |
782 if (m_async) { | 808 if (m_async) { |
783 if (m_upload) | 809 if (m_upload) |
784 request.setReportUploadProgress(true); | 810 request.setReportUploadProgress(true); |
785 | 811 |
786 // ThreadableLoader::create can return null here, for example if we're n o longer attached to a page. | 812 // ThreadableLoader::create can return null here, for example if we're n o longer attached to a page. |
787 // This is true while running onunload handlers. | 813 // This is true while running onunload handlers. |
788 // FIXME: Maybe we need to be able to send XMLHttpRequests from onunload , <http://bugs.webkit.org/show_bug.cgi?id=10904>. | 814 // FIXME: Maybe we need to be able to send XMLHttpRequests from onunload , <http://bugs.webkit.org/show_bug.cgi?id=10904>. |
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1169 m_response.setHTTPHeaderField("Content-Type", m_mimeTypeOverride); | 1195 m_response.setHTTPHeaderField("Content-Type", m_mimeTypeOverride); |
1170 m_responseEncoding = extractCharsetFromMediaType(m_mimeTypeOverride); | 1196 m_responseEncoding = extractCharsetFromMediaType(m_mimeTypeOverride); |
1171 } | 1197 } |
1172 | 1198 |
1173 if (m_responseEncoding.isEmpty()) | 1199 if (m_responseEncoding.isEmpty()) |
1174 m_responseEncoding = response.textEncodingName(); | 1200 m_responseEncoding = response.textEncodingName(); |
1175 } | 1201 } |
1176 | 1202 |
1177 void XMLHttpRequest::didReceiveData(const char* data, int len) | 1203 void XMLHttpRequest::didReceiveData(const char* data, int len) |
1178 { | 1204 { |
1205 ASSERT(m_responseTypeCode != ResponseTypeBlob); | |
1206 | |
1179 if (m_error) | 1207 if (m_error) |
1180 return; | 1208 return; |
1181 | 1209 |
1182 if (m_state < HEADERS_RECEIVED) | 1210 if (m_state < HEADERS_RECEIVED) |
1183 changeState(HEADERS_RECEIVED); | 1211 changeState(HEADERS_RECEIVED); |
1184 | 1212 |
1185 bool useDecoder = m_responseTypeCode == ResponseTypeDefault || m_responseTyp eCode == ResponseTypeText || m_responseTypeCode == ResponseTypeJSON || m_respons eTypeCode == ResponseTypeDocument; | 1213 bool useDecoder = m_responseTypeCode == ResponseTypeDefault || m_responseTyp eCode == ResponseTypeText || m_responseTypeCode == ResponseTypeJSON || m_respons eTypeCode == ResponseTypeDocument; |
1186 | 1214 |
1187 if (useDecoder && !m_decoder) { | 1215 if (useDecoder && !m_decoder) { |
1188 if (m_responseTypeCode == ResponseTypeJSON) | 1216 if (m_responseTypeCode == ResponseTypeJSON) |
(...skipping 12 matching lines...) Expand all Loading... | |
1201 } | 1229 } |
1202 | 1230 |
1203 if (!len) | 1231 if (!len) |
1204 return; | 1232 return; |
1205 | 1233 |
1206 if (len == -1) | 1234 if (len == -1) |
1207 len = strlen(data); | 1235 len = strlen(data); |
1208 | 1236 |
1209 if (useDecoder) { | 1237 if (useDecoder) { |
1210 m_responseText = m_responseText.concatenateWith(m_decoder->decode(data, len)); | 1238 m_responseText = m_responseText.concatenateWith(m_decoder->decode(data, len)); |
1211 } else if (m_responseTypeCode == ResponseTypeArrayBuffer || m_responseTypeCo de == ResponseTypeBlob) { | 1239 } else if (m_responseTypeCode == ResponseTypeArrayBuffer) { |
1212 // Buffer binary data. | 1240 // Buffer binary data. |
1213 if (!m_binaryResponseBuilder) | 1241 if (!m_binaryResponseBuilder) |
1214 m_binaryResponseBuilder = SharedBuffer::create(); | 1242 m_binaryResponseBuilder = SharedBuffer::create(); |
1215 m_binaryResponseBuilder->append(data, len); | 1243 m_binaryResponseBuilder->append(data, len); |
1216 } else if (m_responseTypeCode == ResponseTypeStream) { | 1244 } else if (m_responseTypeCode == ResponseTypeStream) { |
1217 if (!m_responseStream) | 1245 if (!m_responseStream) |
1218 m_responseStream = Stream::create(responseMIMEType()); | 1246 m_responseStream = Stream::create(responseMIMEType()); |
1219 m_responseStream->addData(data, len); | 1247 m_responseStream->addData(data, len); |
1220 } | 1248 } |
1221 | 1249 |
1222 if (!m_error) { | 1250 if (!m_error) |
1223 long long expectedLength = m_response.expectedContentLength(); | 1251 trackProgress(len); |
1224 m_receivedLength += len; | 1252 } |
1225 | 1253 |
1226 if (m_async) { | 1254 void XMLHttpRequest::didDownloadData(int len) |
1227 bool lengthComputable = expectedLength > 0 && m_receivedLength <= ex pectedLength; | 1255 { |
1228 unsigned long long total = lengthComputable ? expectedLength : 0; | 1256 ASSERT(m_responseTypeCode == ResponseTypeBlob); |
1229 m_progressEventThrottle.dispatchProgressEvent(lengthComputable, m_re ceivedLength, total); | |
1230 } | |
1231 | 1257 |
1232 if (m_state != LOADING) | 1258 if (m_error) |
1233 changeState(LOADING); | 1259 return; |
1234 else | 1260 |
1235 // Firefox calls readyStateChanged every time it receives data, 4449 442 | 1261 if (m_state < HEADERS_RECEIVED) |
1236 callReadyStateChangeListener(); | 1262 changeState(HEADERS_RECEIVED); |
1237 } | 1263 |
1264 if (!len) | |
1265 return; | |
1266 | |
1267 if (!m_error) | |
1268 trackProgress(len); | |
1238 } | 1269 } |
1239 | 1270 |
1240 void XMLHttpRequest::didTimeout() | 1271 void XMLHttpRequest::didTimeout() |
1241 { | 1272 { |
1242 // internalAbort() calls dropProtection(), which may release the last refere nce. | 1273 // internalAbort() calls dropProtection(), which may release the last refere nce. |
1243 RefPtr<XMLHttpRequest> protect(this); | 1274 RefPtr<XMLHttpRequest> protect(this); |
1244 internalAbort(); | 1275 internalAbort(); |
1245 | 1276 |
1246 clearResponse(); | 1277 clearResponse(); |
1247 clearRequest(); | 1278 clearRequest(); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1295 { | 1326 { |
1296 return eventNames().interfaceForXMLHttpRequest; | 1327 return eventNames().interfaceForXMLHttpRequest; |
1297 } | 1328 } |
1298 | 1329 |
1299 ScriptExecutionContext* XMLHttpRequest::scriptExecutionContext() const | 1330 ScriptExecutionContext* XMLHttpRequest::scriptExecutionContext() const |
1300 { | 1331 { |
1301 return ActiveDOMObject::scriptExecutionContext(); | 1332 return ActiveDOMObject::scriptExecutionContext(); |
1302 } | 1333 } |
1303 | 1334 |
1304 } // namespace WebCore | 1335 } // namespace WebCore |
OLD | NEW |