| 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) |
| 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 |
| 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 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 m_sameOriginRequest = securityOrigin()->canRequest(m_url); | 758 m_sameOriginRequest = securityOrigin()->canRequest(m_url); |
| 745 | 759 |
| 746 // We also remember whether upload events should be allowed for this request
in case the upload listeners are | 760 // We also remember whether upload events should be allowed for this request
in case the upload listeners are |
| 747 // added after the request is started. | 761 // added after the request is started. |
| 748 m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !isSimpleCros
sOriginAccessRequest(m_method, m_requestHeaders); | 762 m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !isSimpleCros
sOriginAccessRequest(m_method, m_requestHeaders); |
| 749 | 763 |
| 750 ResourceRequest request(m_url); | 764 ResourceRequest request(m_url); |
| 751 request.setHTTPMethod(m_method); | 765 request.setHTTPMethod(m_method); |
| 752 request.setTargetType(ResourceRequest::TargetIsXHR); | 766 request.setTargetType(ResourceRequest::TargetIsXHR); |
| 753 | 767 |
| 768 // When "blob" is specified for the responseType attribute, |
| 769 // we redirect the downloaded data to a file-handle directly |
| 770 // and get the file-path as the result. |
| 771 if (responseTypeCode() == ResponseTypeBlob) |
| 772 request.setDownloadToFile(true); |
| 773 |
| 754 InspectorInstrumentation::willLoadXHR(scriptExecutionContext(), this, m_meth
od, m_url, m_async, m_requestEntityBody ? m_requestEntityBody->deepCopy() : 0, m
_requestHeaders, m_includeCredentials); | 774 InspectorInstrumentation::willLoadXHR(scriptExecutionContext(), this, m_meth
od, m_url, m_async, m_requestEntityBody ? m_requestEntityBody->deepCopy() : 0, m
_requestHeaders, m_includeCredentials); |
| 755 | 775 |
| 756 if (m_requestEntityBody) { | 776 if (m_requestEntityBody) { |
| 757 ASSERT(m_method != "GET"); | 777 ASSERT(m_method != "GET"); |
| 758 ASSERT(m_method != "HEAD"); | 778 ASSERT(m_method != "HEAD"); |
| 759 request.setHTTPBody(m_requestEntityBody.release()); | 779 request.setHTTPBody(m_requestEntityBody.release()); |
| 760 } | 780 } |
| 761 | 781 |
| 762 if (m_requestHeaders.size() > 0) | 782 if (m_requestHeaders.size() > 0) |
| 763 request.addHTTPHeaderFields(m_requestHeaders); | 783 request.addHTTPHeaderFields(m_requestHeaders); |
| 764 | 784 |
| 765 ThreadableLoaderOptions options; | 785 ThreadableLoaderOptions options; |
| 766 options.sendLoadCallbacks = SendCallbacks; | 786 options.sendLoadCallbacks = SendCallbacks; |
| 767 options.sniffContent = DoNotSniffContent; | 787 options.sniffContent = DoNotSniffContent; |
| 768 options.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight; | 788 options.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight; |
| 769 options.allowCredentials = (m_sameOriginRequest || m_includeCredentials) ? A
llowStoredCredentials : DoNotAllowStoredCredentials; | 789 options.allowCredentials = (m_sameOriginRequest || m_includeCredentials) ? A
llowStoredCredentials : DoNotAllowStoredCredentials; |
| 770 options.credentialsRequested = m_includeCredentials ? ClientRequestedCredent
ials : ClientDidNotRequestCredentials; | 790 options.credentialsRequested = m_includeCredentials ? ClientRequestedCredent
ials : ClientDidNotRequestCredentials; |
| 771 options.crossOriginRequestPolicy = UseAccessControl; | 791 options.crossOriginRequestPolicy = UseAccessControl; |
| 772 options.securityOrigin = securityOrigin(); | 792 options.securityOrigin = securityOrigin(); |
| 773 options.initiator = FetchInitiatorTypeNames::xmlhttprequest; | 793 options.initiator = FetchInitiatorTypeNames::xmlhttprequest; |
| 774 options.contentSecurityPolicyEnforcement = ContentSecurityPolicy::shouldBypa
ssMainWorld(scriptExecutionContext()) ? DoNotEnforceContentSecurityPolicy : Enfo
rceConnectSrcDirective; | 794 options.contentSecurityPolicyEnforcement = ContentSecurityPolicy::shouldBypa
ssMainWorld(scriptExecutionContext()) ? DoNotEnforceContentSecurityPolicy : Enfo
rceConnectSrcDirective; |
| 775 options.mixedContentBlockingTreatment = TreatAsActiveContent; | 795 options.mixedContentBlockingTreatment = TreatAsActiveContent; |
| 776 options.timeoutMilliseconds = m_timeoutMilliseconds; | 796 options.timeoutMilliseconds = m_timeoutMilliseconds; |
| 777 | 797 |
| 798 // Since we redirect the downloaded data to a file-handle directly |
| 799 // when "blob" is specified for the responseType attribute, |
| 800 // buffering is not needed. |
| 801 if (responseTypeCode() == ResponseTypeBlob) |
| 802 options.dataBufferingPolicy = DoNotBufferData; |
| 803 |
| 778 m_exceptionCode = 0; | 804 m_exceptionCode = 0; |
| 779 m_error = false; | 805 m_error = false; |
| 780 | 806 |
| 781 if (m_async) { | 807 if (m_async) { |
| 782 if (m_upload) | 808 if (m_upload) |
| 783 request.setReportUploadProgress(true); | 809 request.setReportUploadProgress(true); |
| 784 | 810 |
| 785 // ThreadableLoader::create can return null here, for example if we're n
o longer attached to a page. | 811 // ThreadableLoader::create can return null here, for example if we're n
o longer attached to a page. |
| 786 // This is true while running onunload handlers. | 812 // This is true while running onunload handlers. |
| 787 // FIXME: Maybe we need to be able to send XMLHttpRequests from onunload
, <http://bugs.webkit.org/show_bug.cgi?id=10904>. | 813 // 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... |
| 1168 m_response.setHTTPHeaderField("Content-Type", m_mimeTypeOverride); | 1194 m_response.setHTTPHeaderField("Content-Type", m_mimeTypeOverride); |
| 1169 m_responseEncoding = extractCharsetFromMediaType(m_mimeTypeOverride); | 1195 m_responseEncoding = extractCharsetFromMediaType(m_mimeTypeOverride); |
| 1170 } | 1196 } |
| 1171 | 1197 |
| 1172 if (m_responseEncoding.isEmpty()) | 1198 if (m_responseEncoding.isEmpty()) |
| 1173 m_responseEncoding = response.textEncodingName(); | 1199 m_responseEncoding = response.textEncodingName(); |
| 1174 } | 1200 } |
| 1175 | 1201 |
| 1176 void XMLHttpRequest::didReceiveData(const char* data, int len) | 1202 void XMLHttpRequest::didReceiveData(const char* data, int len) |
| 1177 { | 1203 { |
| 1204 ASSERT(m_responseTypeCode != ResponseTypeBlob); |
| 1205 |
| 1178 if (m_error) | 1206 if (m_error) |
| 1179 return; | 1207 return; |
| 1180 | 1208 |
| 1181 if (m_state < HEADERS_RECEIVED) | 1209 if (m_state < HEADERS_RECEIVED) |
| 1182 changeState(HEADERS_RECEIVED); | 1210 changeState(HEADERS_RECEIVED); |
| 1183 | 1211 |
| 1184 bool useDecoder = m_responseTypeCode == ResponseTypeDefault || m_responseTyp
eCode == ResponseTypeText || m_responseTypeCode == ResponseTypeJSON || m_respons
eTypeCode == ResponseTypeDocument; | 1212 bool useDecoder = m_responseTypeCode == ResponseTypeDefault || m_responseTyp
eCode == ResponseTypeText || m_responseTypeCode == ResponseTypeJSON || m_respons
eTypeCode == ResponseTypeDocument; |
| 1185 | 1213 |
| 1186 if (useDecoder && !m_decoder) { | 1214 if (useDecoder && !m_decoder) { |
| 1187 if (m_responseTypeCode == ResponseTypeJSON) | 1215 if (m_responseTypeCode == ResponseTypeJSON) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1200 } | 1228 } |
| 1201 | 1229 |
| 1202 if (!len) | 1230 if (!len) |
| 1203 return; | 1231 return; |
| 1204 | 1232 |
| 1205 if (len == -1) | 1233 if (len == -1) |
| 1206 len = strlen(data); | 1234 len = strlen(data); |
| 1207 | 1235 |
| 1208 if (useDecoder) { | 1236 if (useDecoder) { |
| 1209 m_responseText = m_responseText.concatenateWith(m_decoder->decode(data,
len)); | 1237 m_responseText = m_responseText.concatenateWith(m_decoder->decode(data,
len)); |
| 1210 } else if (m_responseTypeCode == ResponseTypeArrayBuffer || m_responseTypeCo
de == ResponseTypeBlob) { | 1238 } else if (m_responseTypeCode == ResponseTypeArrayBuffer) { |
| 1211 // Buffer binary data. | 1239 // Buffer binary data. |
| 1212 if (!m_binaryResponseBuilder) | 1240 if (!m_binaryResponseBuilder) |
| 1213 m_binaryResponseBuilder = SharedBuffer::create(); | 1241 m_binaryResponseBuilder = SharedBuffer::create(); |
| 1214 m_binaryResponseBuilder->append(data, len); | 1242 m_binaryResponseBuilder->append(data, len); |
| 1215 } else if (m_responseTypeCode == ResponseTypeStream) { | 1243 } else if (m_responseTypeCode == ResponseTypeStream) { |
| 1216 if (!m_responseStream) | 1244 if (!m_responseStream) |
| 1217 m_responseStream = Stream::create(responseMIMEType()); | 1245 m_responseStream = Stream::create(responseMIMEType()); |
| 1218 m_responseStream->addData(data, len); | 1246 m_responseStream->addData(data, len); |
| 1219 } | 1247 } |
| 1220 | 1248 |
| 1221 if (!m_error) { | 1249 if (!m_error) |
| 1222 long long expectedLength = m_response.expectedContentLength(); | 1250 trackProgress(len); |
| 1223 m_receivedLength += len; | 1251 } |
| 1224 | 1252 |
| 1225 if (m_async) { | 1253 void XMLHttpRequest::didDownloadData(int len) |
| 1226 bool lengthComputable = expectedLength > 0 && m_receivedLength <= ex
pectedLength; | 1254 { |
| 1227 unsigned long long total = lengthComputable ? expectedLength : 0; | 1255 ASSERT(m_responseTypeCode == ResponseTypeBlob); |
| 1228 m_progressEventThrottle.dispatchProgressEvent(lengthComputable, m_re
ceivedLength, total); | |
| 1229 } | |
| 1230 | 1256 |
| 1231 if (m_state != LOADING) | 1257 if (m_error) |
| 1232 changeState(LOADING); | 1258 return; |
| 1233 else | 1259 |
| 1234 // Firefox calls readyStateChanged every time it receives data, 4449
442 | 1260 if (m_state < HEADERS_RECEIVED) |
| 1235 callReadyStateChangeListener(); | 1261 changeState(HEADERS_RECEIVED); |
| 1236 } | 1262 |
| 1263 if (!len) |
| 1264 return; |
| 1265 |
| 1266 if (!m_error) |
| 1267 trackProgress(len); |
| 1237 } | 1268 } |
| 1238 | 1269 |
| 1239 void XMLHttpRequest::didTimeout() | 1270 void XMLHttpRequest::didTimeout() |
| 1240 { | 1271 { |
| 1241 // internalAbort() calls dropProtection(), which may release the last refere
nce. | 1272 // internalAbort() calls dropProtection(), which may release the last refere
nce. |
| 1242 RefPtr<XMLHttpRequest> protect(this); | 1273 RefPtr<XMLHttpRequest> protect(this); |
| 1243 internalAbort(); | 1274 internalAbort(); |
| 1244 | 1275 |
| 1245 clearResponse(); | 1276 clearResponse(); |
| 1246 clearRequest(); | 1277 clearRequest(); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1294 { | 1325 { |
| 1295 return eventNames().interfaceForXMLHttpRequest; | 1326 return eventNames().interfaceForXMLHttpRequest; |
| 1296 } | 1327 } |
| 1297 | 1328 |
| 1298 ScriptExecutionContext* XMLHttpRequest::scriptExecutionContext() const | 1329 ScriptExecutionContext* XMLHttpRequest::scriptExecutionContext() const |
| 1299 { | 1330 { |
| 1300 return ActiveDOMObject::scriptExecutionContext(); | 1331 return ActiveDOMObject::scriptExecutionContext(); |
| 1301 } | 1332 } |
| 1302 | 1333 |
| 1303 } // namespace WebCore | 1334 } // namespace WebCore |
| OLD | NEW |