| 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 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 return xmlHttpRequest.release(); | 163 return xmlHttpRequest.release(); |
| 164 } | 164 } |
| 165 | 165 |
| 166 XMLHttpRequest::XMLHttpRequest(ExecutionContext* context, PassRefPtr<SecurityOri
gin> securityOrigin) | 166 XMLHttpRequest::XMLHttpRequest(ExecutionContext* context, PassRefPtr<SecurityOri
gin> securityOrigin) |
| 167 : ActiveDOMObject(context) | 167 : ActiveDOMObject(context) |
| 168 , m_async(true) | 168 , m_async(true) |
| 169 , m_includeCredentials(false) | 169 , m_includeCredentials(false) |
| 170 , m_timeoutMilliseconds(0) | 170 , m_timeoutMilliseconds(0) |
| 171 , m_state(UNSENT) | 171 , m_state(UNSENT) |
| 172 , m_createdDocument(false) | 172 , m_createdDocument(false) |
| 173 , m_downloadedBlobLength(0) |
| 173 , m_error(false) | 174 , m_error(false) |
| 174 , m_uploadEventsAllowed(true) | 175 , m_uploadEventsAllowed(true) |
| 175 , m_uploadComplete(false) | 176 , m_uploadComplete(false) |
| 176 , m_sameOriginRequest(true) | 177 , m_sameOriginRequest(true) |
| 177 , m_receivedLength(0) | 178 , m_receivedLength(0) |
| 178 , m_lastSendLineNumber(0) | 179 , m_lastSendLineNumber(0) |
| 179 , m_exceptionCode(0) | 180 , m_exceptionCode(0) |
| 180 , m_progressEventThrottle(this) | 181 , m_progressEventThrottle(this) |
| 181 , m_responseTypeCode(ResponseTypeDefault) | 182 , m_responseTypeCode(ResponseTypeDefault) |
| 182 , m_dropProtectionRunner(this, &XMLHttpRequest::dropProtection) | 183 , m_dropProtectionRunner(this, &XMLHttpRequest::dropProtection) |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 } | 267 } |
| 267 m_createdDocument = true; | 268 m_createdDocument = true; |
| 268 } | 269 } |
| 269 | 270 |
| 270 return m_responseDocument.get(); | 271 return m_responseDocument.get(); |
| 271 } | 272 } |
| 272 | 273 |
| 273 Blob* XMLHttpRequest::responseBlob() | 274 Blob* XMLHttpRequest::responseBlob() |
| 274 { | 275 { |
| 275 ASSERT(m_responseTypeCode == ResponseTypeBlob); | 276 ASSERT(m_responseTypeCode == ResponseTypeBlob); |
| 277 ASSERT(!m_binaryResponseBuilder.get()); |
| 276 | 278 |
| 277 // We always return null before DONE. | 279 // We always return null before DONE. |
| 278 if (m_error || m_state != DONE) | 280 if (m_error || m_state != DONE) |
| 279 return 0; | 281 return 0; |
| 280 | 282 |
| 281 if (!m_responseBlob) { | 283 if (!m_responseBlob) { |
| 282 // FIXME: This causes two (or more) unnecessary copies of the data. | 284 // When "blob" is specified for the responseType attribute, |
| 283 // Chromium stores blob data in the browser process, so we're pulling th
e data | 285 // we redirect the downloaded data to a file-handle directly |
| 284 // from the network only to copy it into the renderer to copy it back to
the browser. | 286 // in the browser process. |
| 285 // Ideally we'd get the blob/file-handle from the ResourceResponse direc
tly | 287 // We get the file-path from the ResourceResponse directly |
| 286 // instead of copying the bytes. Embedders who store blob data in the | 288 // instead of copying the bytes between the browser and the renderer. |
| 287 // same process as WebCore would at least to teach BlobData to take | |
| 288 // a SharedBuffer, even if they don't get the Blob from the network laye
r directly. | |
| 289 OwnPtr<BlobData> blobData = BlobData::create(); | 289 OwnPtr<BlobData> blobData = BlobData::create(); |
| 290 String filePath = m_response.downloadedFilePath(); |
| 290 // If we errored out or got no data, we still return a blob, just an emp
ty one. | 291 // If we errored out or got no data, we still return a blob, just an emp
ty one. |
| 291 size_t size = 0; | 292 if (!filePath.isEmpty() && m_downloadedBlobLength) { |
| 292 if (m_binaryResponseBuilder) { | 293 blobData->appendFile(filePath); |
| 293 RefPtr<RawData> rawData = RawData::create(); | |
| 294 size = m_binaryResponseBuilder->size(); | |
| 295 rawData->mutableData()->append(m_binaryResponseBuilder->data(), size
); | |
| 296 blobData->appendData(rawData, 0, BlobDataItem::toEndOfFile); | |
| 297 blobData->setContentType(responseMIMEType()); // responseMIMEType de
faults to text/xml which may be incorrect. | 294 blobData->setContentType(responseMIMEType()); // responseMIMEType de
faults to text/xml which may be incorrect. |
| 298 m_binaryResponseBuilder.clear(); | |
| 299 } | 295 } |
| 300 m_responseBlob = Blob::create(BlobDataHandle::create(blobData.release(),
size)); | 296 m_responseBlob = Blob::create(BlobDataHandle::create(blobData.release(),
m_downloadedBlobLength)); |
| 301 } | 297 } |
| 302 | 298 |
| 303 return m_responseBlob.get(); | 299 return m_responseBlob.get(); |
| 304 } | 300 } |
| 305 | 301 |
| 306 ArrayBuffer* XMLHttpRequest::responseArrayBuffer() | 302 ArrayBuffer* XMLHttpRequest::responseArrayBuffer() |
| 307 { | 303 { |
| 308 ASSERT(m_responseTypeCode == ResponseTypeArrayBuffer); | 304 ASSERT(m_responseTypeCode == ResponseTypeArrayBuffer); |
| 309 | 305 |
| 310 if (m_error || m_state != DONE) | 306 if (m_error || m_state != DONE) |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 return ""; | 398 return ""; |
| 403 } | 399 } |
| 404 | 400 |
| 405 XMLHttpRequestUpload* XMLHttpRequest::upload() | 401 XMLHttpRequestUpload* XMLHttpRequest::upload() |
| 406 { | 402 { |
| 407 if (!m_upload) | 403 if (!m_upload) |
| 408 m_upload = XMLHttpRequestUpload::create(this); | 404 m_upload = XMLHttpRequestUpload::create(this); |
| 409 return m_upload.get(); | 405 return m_upload.get(); |
| 410 } | 406 } |
| 411 | 407 |
| 408 void XMLHttpRequest::trackProgress(int length) |
| 409 { |
| 410 m_receivedLength += length; |
| 411 |
| 412 if (m_async) |
| 413 dispatchThrottledProgressEventSnapshot(EventTypeNames::progress); |
| 414 |
| 415 if (m_state != LOADING) { |
| 416 changeState(LOADING); |
| 417 } else { |
| 418 // Firefox calls readyStateChanged every time it receives data. Do |
| 419 // the same to align with Firefox. |
| 420 // |
| 421 // FIXME: Make our implementation and the spec consistent. This |
| 422 // behavior was needed when the progress event was not available. |
| 423 dispatchReadyStateChangeEvent(); |
| 424 } |
| 425 } |
| 426 |
| 412 void XMLHttpRequest::changeState(State newState) | 427 void XMLHttpRequest::changeState(State newState) |
| 413 { | 428 { |
| 414 if (m_state != newState) { | 429 if (m_state != newState) { |
| 415 m_state = newState; | 430 m_state = newState; |
| 416 dispatchReadyStateChangeEvent(); | 431 dispatchReadyStateChangeEvent(); |
| 417 } | 432 } |
| 418 } | 433 } |
| 419 | 434 |
| 420 void XMLHttpRequest::dispatchReadyStateChangeEvent() | 435 void XMLHttpRequest::dispatchReadyStateChangeEvent() |
| 421 { | 436 { |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 782 m_sameOriginRequest = securityOrigin()->canRequest(m_url); | 797 m_sameOriginRequest = securityOrigin()->canRequest(m_url); |
| 783 | 798 |
| 784 // We also remember whether upload events should be allowed for this request
in case the upload listeners are | 799 // We also remember whether upload events should be allowed for this request
in case the upload listeners are |
| 785 // added after the request is started. | 800 // added after the request is started. |
| 786 m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !isSimpleCros
sOriginAccessRequest(m_method, m_requestHeaders); | 801 m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !isSimpleCros
sOriginAccessRequest(m_method, m_requestHeaders); |
| 787 | 802 |
| 788 ResourceRequest request(m_url); | 803 ResourceRequest request(m_url); |
| 789 request.setHTTPMethod(m_method); | 804 request.setHTTPMethod(m_method); |
| 790 request.setTargetType(ResourceRequest::TargetIsXHR); | 805 request.setTargetType(ResourceRequest::TargetIsXHR); |
| 791 | 806 |
| 807 // When "blob" is specified for the responseType attribute, |
| 808 // we redirect the downloaded data to a file-handle directly |
| 809 // and get the file-path as the result. |
| 810 if (responseTypeCode() == ResponseTypeBlob) |
| 811 request.setDownloadToFile(true); |
| 812 |
| 792 InspectorInstrumentation::willLoadXHR(executionContext(), this, this, m_meth
od, m_url, m_async, m_requestEntityBody ? m_requestEntityBody->deepCopy() : 0, m
_requestHeaders, m_includeCredentials); | 813 InspectorInstrumentation::willLoadXHR(executionContext(), this, this, m_meth
od, m_url, m_async, m_requestEntityBody ? m_requestEntityBody->deepCopy() : 0, m
_requestHeaders, m_includeCredentials); |
| 793 | 814 |
| 794 if (m_requestEntityBody) { | 815 if (m_requestEntityBody) { |
| 795 ASSERT(m_method != "GET"); | 816 ASSERT(m_method != "GET"); |
| 796 ASSERT(m_method != "HEAD"); | 817 ASSERT(m_method != "HEAD"); |
| 797 request.setHTTPBody(m_requestEntityBody.release()); | 818 request.setHTTPBody(m_requestEntityBody.release()); |
| 798 } | 819 } |
| 799 | 820 |
| 800 if (m_requestHeaders.size() > 0) | 821 if (m_requestHeaders.size() > 0) |
| 801 request.addHTTPHeaderFields(m_requestHeaders); | 822 request.addHTTPHeaderFields(m_requestHeaders); |
| 802 | 823 |
| 803 ThreadableLoaderOptions options; | 824 ThreadableLoaderOptions options; |
| 804 options.sendLoadCallbacks = SendCallbacks; | 825 options.sendLoadCallbacks = SendCallbacks; |
| 805 options.sniffContent = DoNotSniffContent; | 826 options.sniffContent = DoNotSniffContent; |
| 806 options.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight; | 827 options.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight; |
| 807 options.allowCredentials = (m_sameOriginRequest || m_includeCredentials) ? A
llowStoredCredentials : DoNotAllowStoredCredentials; | 828 options.allowCredentials = (m_sameOriginRequest || m_includeCredentials) ? A
llowStoredCredentials : DoNotAllowStoredCredentials; |
| 808 options.credentialsRequested = m_includeCredentials ? ClientRequestedCredent
ials : ClientDidNotRequestCredentials; | 829 options.credentialsRequested = m_includeCredentials ? ClientRequestedCredent
ials : ClientDidNotRequestCredentials; |
| 809 options.crossOriginRequestPolicy = UseAccessControl; | 830 options.crossOriginRequestPolicy = UseAccessControl; |
| 810 options.securityOrigin = securityOrigin(); | 831 options.securityOrigin = securityOrigin(); |
| 811 options.initiator = FetchInitiatorTypeNames::xmlhttprequest; | 832 options.initiator = FetchInitiatorTypeNames::xmlhttprequest; |
| 812 options.contentSecurityPolicyEnforcement = ContentSecurityPolicy::shouldBypa
ssMainWorld(executionContext()) ? DoNotEnforceContentSecurityPolicy : EnforceCon
nectSrcDirective; | 833 options.contentSecurityPolicyEnforcement = ContentSecurityPolicy::shouldBypa
ssMainWorld(executionContext()) ? DoNotEnforceContentSecurityPolicy : EnforceCon
nectSrcDirective; |
| 813 // TODO(tsepez): Specify TreatAsActiveContent per http://crbug.com/305303. | 834 // TODO(tsepez): Specify TreatAsActiveContent per http://crbug.com/305303. |
| 814 options.mixedContentBlockingTreatment = TreatAsPassiveContent; | 835 options.mixedContentBlockingTreatment = TreatAsPassiveContent; |
| 815 options.timeoutMilliseconds = m_timeoutMilliseconds; | 836 options.timeoutMilliseconds = m_timeoutMilliseconds; |
| 816 | 837 |
| 838 // Since we redirect the downloaded data to a file-handle directly |
| 839 // when "blob" is specified for the responseType attribute, |
| 840 // buffering is not needed. |
| 841 if (responseTypeCode() == ResponseTypeBlob) |
| 842 options.dataBufferingPolicy = DoNotBufferData; |
| 843 |
| 817 m_exceptionCode = 0; | 844 m_exceptionCode = 0; |
| 818 m_error = false; | 845 m_error = false; |
| 819 | 846 |
| 820 if (m_async) { | 847 if (m_async) { |
| 821 if (m_upload) | 848 if (m_upload) |
| 822 request.setReportUploadProgress(true); | 849 request.setReportUploadProgress(true); |
| 823 | 850 |
| 824 // ThreadableLoader::create can return null here, for example if we're n
o longer attached to a page. | 851 // ThreadableLoader::create can return null here, for example if we're n
o longer attached to a page. |
| 825 // This is true while running onunload handlers. | 852 // This is true while running onunload handlers. |
| 826 // FIXME: Maybe we need to be able to send XMLHttpRequests from onunload
, <http://bugs.webkit.org/show_bug.cgi?id=10904>. | 853 // FIXME: Maybe we need to be able to send XMLHttpRequests from onunload
, <http://bugs.webkit.org/show_bug.cgi?id=10904>. |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1280 m_response.setHTTPHeaderField("Content-Type", m_mimeTypeOverride); | 1307 m_response.setHTTPHeaderField("Content-Type", m_mimeTypeOverride); |
| 1281 m_responseEncoding = extractCharsetFromMediaType(m_mimeTypeOverride); | 1308 m_responseEncoding = extractCharsetFromMediaType(m_mimeTypeOverride); |
| 1282 } | 1309 } |
| 1283 | 1310 |
| 1284 if (m_responseEncoding.isEmpty()) | 1311 if (m_responseEncoding.isEmpty()) |
| 1285 m_responseEncoding = response.textEncodingName(); | 1312 m_responseEncoding = response.textEncodingName(); |
| 1286 } | 1313 } |
| 1287 | 1314 |
| 1288 void XMLHttpRequest::didReceiveData(const char* data, int len) | 1315 void XMLHttpRequest::didReceiveData(const char* data, int len) |
| 1289 { | 1316 { |
| 1317 ASSERT(m_responseTypeCode != ResponseTypeBlob); |
| 1318 |
| 1290 if (m_error) | 1319 if (m_error) |
| 1291 return; | 1320 return; |
| 1292 | 1321 |
| 1293 if (m_state < HEADERS_RECEIVED) | 1322 if (m_state < HEADERS_RECEIVED) |
| 1294 changeState(HEADERS_RECEIVED); | 1323 changeState(HEADERS_RECEIVED); |
| 1295 | 1324 |
| 1296 bool useDecoder = m_responseTypeCode == ResponseTypeDefault || m_responseTyp
eCode == ResponseTypeText || m_responseTypeCode == ResponseTypeJSON || m_respons
eTypeCode == ResponseTypeDocument; | 1325 bool useDecoder = m_responseTypeCode == ResponseTypeDefault || m_responseTyp
eCode == ResponseTypeText || m_responseTypeCode == ResponseTypeJSON || m_respons
eTypeCode == ResponseTypeDocument; |
| 1297 | 1326 |
| 1298 if (useDecoder && !m_decoder) { | 1327 if (useDecoder && !m_decoder) { |
| 1299 if (m_responseTypeCode == ResponseTypeJSON) | 1328 if (m_responseTypeCode == ResponseTypeJSON) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1312 } | 1341 } |
| 1313 | 1342 |
| 1314 if (!len) | 1343 if (!len) |
| 1315 return; | 1344 return; |
| 1316 | 1345 |
| 1317 if (len == -1) | 1346 if (len == -1) |
| 1318 len = strlen(data); | 1347 len = strlen(data); |
| 1319 | 1348 |
| 1320 if (useDecoder) { | 1349 if (useDecoder) { |
| 1321 m_responseText = m_responseText.concatenateWith(m_decoder->decode(data,
len)); | 1350 m_responseText = m_responseText.concatenateWith(m_decoder->decode(data,
len)); |
| 1322 } else if (m_responseTypeCode == ResponseTypeArrayBuffer || m_responseTypeCo
de == ResponseTypeBlob) { | 1351 } else if (m_responseTypeCode == ResponseTypeArrayBuffer) { |
| 1323 // Buffer binary data. | 1352 // Buffer binary data. |
| 1324 if (!m_binaryResponseBuilder) | 1353 if (!m_binaryResponseBuilder) |
| 1325 m_binaryResponseBuilder = SharedBuffer::create(); | 1354 m_binaryResponseBuilder = SharedBuffer::create(); |
| 1326 m_binaryResponseBuilder->append(data, len); | 1355 m_binaryResponseBuilder->append(data, len); |
| 1327 } else if (m_responseTypeCode == ResponseTypeStream) { | 1356 } else if (m_responseTypeCode == ResponseTypeStream) { |
| 1328 if (!m_responseStream) | 1357 if (!m_responseStream) |
| 1329 m_responseStream = Stream::create(executionContext(), responseMIMETy
pe()); | 1358 m_responseStream = Stream::create(executionContext(), responseMIMETy
pe()); |
| 1330 m_responseStream->addData(data, len); | 1359 m_responseStream->addData(data, len); |
| 1331 } | 1360 } |
| 1332 | 1361 |
| 1333 if (m_error) | 1362 if (m_error) |
| 1334 return; | 1363 return; |
| 1335 | 1364 |
| 1336 m_receivedLength += len; | 1365 trackProgress(len); |
| 1366 } |
| 1337 | 1367 |
| 1338 if (m_async) | 1368 void XMLHttpRequest::didDownloadData(int dataLength) |
| 1339 dispatchThrottledProgressEventSnapshot(EventTypeNames::progress); | 1369 { |
| 1370 ASSERT(m_responseTypeCode == ResponseTypeBlob); |
| 1340 | 1371 |
| 1341 if (m_state != LOADING) { | 1372 if (m_error) |
| 1342 changeState(LOADING); | 1373 return; |
| 1343 } else { | 1374 |
| 1344 // Firefox calls readyStateChanged every time it receives data. Do | 1375 if (m_state < HEADERS_RECEIVED) |
| 1345 // the same to align with Firefox. | 1376 changeState(HEADERS_RECEIVED); |
| 1346 // | 1377 |
| 1347 // FIXME: Make our implementation and the spec consistent. This | 1378 if (!dataLength) |
| 1348 // behavior was needed when the progress event was not available. | 1379 return; |
| 1349 dispatchReadyStateChangeEvent(); | 1380 |
| 1350 } | 1381 if (m_error) |
| 1382 return; |
| 1383 |
| 1384 m_downloadedBlobLength += dataLength; |
| 1385 trackProgress(dataLength); |
| 1351 } | 1386 } |
| 1352 | 1387 |
| 1353 void XMLHttpRequest::handleDidTimeout() | 1388 void XMLHttpRequest::handleDidTimeout() |
| 1354 { | 1389 { |
| 1355 WTF_LOG(Network, "XMLHttpRequest %p handleDidTimeout()", this); | 1390 WTF_LOG(Network, "XMLHttpRequest %p handleDidTimeout()", this); |
| 1356 | 1391 |
| 1357 // internalAbort() calls dropProtection(), which may release the last refere
nce. | 1392 // internalAbort() calls dropProtection(), which may release the last refere
nce. |
| 1358 RefPtr<XMLHttpRequest> protect(this); | 1393 RefPtr<XMLHttpRequest> protect(this); |
| 1359 | 1394 |
| 1360 // Response is cleared next, save needed progress event data. | 1395 // Response is cleared next, save needed progress event data. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1393 { | 1428 { |
| 1394 return EventTargetNames::XMLHttpRequest; | 1429 return EventTargetNames::XMLHttpRequest; |
| 1395 } | 1430 } |
| 1396 | 1431 |
| 1397 ExecutionContext* XMLHttpRequest::executionContext() const | 1432 ExecutionContext* XMLHttpRequest::executionContext() const |
| 1398 { | 1433 { |
| 1399 return ActiveDOMObject::executionContext(); | 1434 return ActiveDOMObject::executionContext(); |
| 1400 } | 1435 } |
| 1401 | 1436 |
| 1402 } // namespace WebCore | 1437 } // namespace WebCore |
| OLD | NEW |