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 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 , m_downloadedBlobLength(0) | 171 , m_downloadedBlobLength(0) |
172 , m_error(false) | 172 , m_error(false) |
173 , m_uploadEventsAllowed(true) | 173 , m_uploadEventsAllowed(true) |
174 , m_uploadComplete(false) | 174 , m_uploadComplete(false) |
175 , m_sameOriginRequest(true) | 175 , m_sameOriginRequest(true) |
176 , m_receivedLength(0) | 176 , m_receivedLength(0) |
177 , m_lastSendLineNumber(0) | 177 , m_lastSendLineNumber(0) |
178 , m_exceptionCode(0) | 178 , m_exceptionCode(0) |
179 , m_progressEventThrottle(this) | 179 , m_progressEventThrottle(this) |
180 , m_responseTypeCode(ResponseTypeDefault) | 180 , m_responseTypeCode(ResponseTypeDefault) |
181 , m_dropProtectionRunner(this, &XMLHttpRequest::dropProtection) | |
182 , m_securityOrigin(securityOrigin) | 181 , m_securityOrigin(securityOrigin) |
183 { | 182 { |
184 initializeXMLHttpRequestStaticData(); | 183 initializeXMLHttpRequestStaticData(); |
185 #ifndef NDEBUG | 184 #ifndef NDEBUG |
186 xmlHttpRequestCounter.increment(); | 185 xmlHttpRequestCounter.increment(); |
187 #endif | 186 #endif |
188 ScriptWrappable::init(this); | 187 ScriptWrappable::init(this); |
189 } | 188 } |
190 | 189 |
191 XMLHttpRequest::~XMLHttpRequest() | 190 XMLHttpRequest::~XMLHttpRequest() |
(...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
842 if (m_async) { | 841 if (m_async) { |
843 if (m_upload) | 842 if (m_upload) |
844 request.setReportUploadProgress(true); | 843 request.setReportUploadProgress(true); |
845 | 844 |
846 // ThreadableLoader::create can return null here, for example if we're n
o longer attached to a page. | 845 // ThreadableLoader::create can return null here, for example if we're n
o longer attached to a page. |
847 // This is true while running onunload handlers. | 846 // This is true while running onunload handlers. |
848 // FIXME: Maybe we need to be able to send XMLHttpRequests from onunload
, <http://bugs.webkit.org/show_bug.cgi?id=10904>. | 847 // FIXME: Maybe we need to be able to send XMLHttpRequests from onunload
, <http://bugs.webkit.org/show_bug.cgi?id=10904>. |
849 // FIXME: Maybe create() can return null for other reasons too? | 848 // FIXME: Maybe create() can return null for other reasons too? |
850 ASSERT(!m_loader); | 849 ASSERT(!m_loader); |
851 m_loader = ThreadableLoader::create(executionContext(), this, request, o
ptions); | 850 m_loader = ThreadableLoader::create(executionContext(), this, request, o
ptions); |
852 if (m_loader) { | |
853 // Neither this object nor the JavaScript wrapper should be deleted
while | |
854 // a request is in progress because we need to keep the listeners al
ive, | |
855 // and they are referenced by the JavaScript wrapper. | |
856 setPendingActivity(this); | |
857 } | |
858 } else { | 851 } else { |
859 ThreadableLoader::loadResourceSynchronously(executionContext(), request,
*this, options); | 852 ThreadableLoader::loadResourceSynchronously(executionContext(), request,
*this, options); |
860 } | 853 } |
861 | 854 |
862 if (!m_exceptionCode && m_error) | 855 if (!m_exceptionCode && m_error) |
863 m_exceptionCode = NetworkError; | 856 m_exceptionCode = NetworkError; |
864 if (m_exceptionCode) | 857 if (m_exceptionCode) |
865 exceptionState.throwUninformativeAndGenericDOMException(m_exceptionCode)
; | 858 exceptionState.throwUninformativeAndGenericDOMException(m_exceptionCode)
; |
866 } | 859 } |
867 | 860 |
868 void XMLHttpRequest::abort() | 861 void XMLHttpRequest::abort() |
869 { | 862 { |
870 WTF_LOG(Network, "XMLHttpRequest %p abort()", this); | 863 WTF_LOG(Network, "XMLHttpRequest %p abort()", this); |
871 | 864 |
872 // internalAbort() calls dropProtection(), which may release the last refere
nce. | |
873 RefPtr<XMLHttpRequest> protect(this); | |
874 | |
875 bool sendFlag = m_loader; | 865 bool sendFlag = m_loader; |
876 | 866 |
877 // Response is cleared next, save needed progress event data. | 867 // Response is cleared next, save needed progress event data. |
878 long long expectedLength = m_response.expectedContentLength(); | 868 long long expectedLength = m_response.expectedContentLength(); |
879 long long receivedLength = m_receivedLength; | 869 long long receivedLength = m_receivedLength; |
880 | 870 |
| 871 // internalAbort() clears m_loader. hasPendingActivity() returns false when |
| 872 // m_loader is 0. So, if window.onload is dispatched (see comments in |
| 873 // internalAbort()), it's possible that the wrapper gets GC-ed during |
| 874 // execution of the event. So, we need to keep this object alive to |
| 875 // continue the rest of this method. |
| 876 RefPtr<XMLHttpRequest> protect(this); |
| 877 |
881 if (!internalAbort()) | 878 if (!internalAbort()) |
882 return; | 879 return; |
883 | 880 |
884 clearResponse(); | 881 clearResponse(); |
885 | 882 |
886 // Clear headers as required by the spec | 883 // Clear headers as required by the spec |
887 m_requestHeaders.clear(); | 884 m_requestHeaders.clear(); |
888 | 885 |
889 if (!((m_state <= OPENED && !sendFlag) || m_state == DONE)) { | 886 if (!((m_state <= OPENED && !sendFlag) || m_state == DONE)) { |
890 ASSERT(!m_loader); | 887 ASSERT(!m_loader); |
891 handleRequestError(0, EventTypeNames::abort, receivedLength, expectedLen
gth); | 888 handleRequestError(0, EventTypeNames::abort, receivedLength, expectedLen
gth); |
892 } | 889 } |
893 m_state = UNSENT; | 890 m_state = UNSENT; |
894 } | 891 } |
895 | 892 |
896 void XMLHttpRequest::clearVariablesForLoading() | 893 void XMLHttpRequest::clearVariablesForLoading() |
897 { | 894 { |
898 m_decoder.clear(); | 895 m_decoder.clear(); |
899 | 896 |
900 m_responseEncoding = String(); | 897 m_responseEncoding = String(); |
901 } | 898 } |
902 | 899 |
903 bool XMLHttpRequest::internalAbort(DropProtection async) | 900 bool XMLHttpRequest::internalAbort() |
904 { | 901 { |
905 m_error = true; | 902 m_error = true; |
906 | 903 |
907 clearVariablesForLoading(); | 904 clearVariablesForLoading(); |
908 | 905 |
909 InspectorInstrumentation::didFailXHRLoading(executionContext(), this, this); | 906 InspectorInstrumentation::didFailXHRLoading(executionContext(), this, this); |
910 | 907 |
911 if (m_responseStream && m_state != DONE) | 908 if (m_responseStream && m_state != DONE) |
912 m_responseStream->abort(); | 909 m_responseStream->abort(); |
913 | 910 |
914 if (!m_loader) | 911 if (!m_loader) |
915 return true; | 912 return true; |
916 | 913 |
917 // Cancelling the ThreadableLoader m_loader may result in calling | 914 // Cancelling the ThreadableLoader m_loader may result in calling |
918 // window.onload synchronously. If such an onload handler contains open() | 915 // window.onload synchronously. If such an onload handler contains open() |
919 // call on the same XMLHttpRequest object, reentry happens. If m_loader | 916 // call on the same XMLHttpRequest object, reentry happens. If m_loader |
920 // is left to be non 0, internalAbort() call for the inner open() makes | 917 // is left to be non 0, internalAbort() for the inner open() repeats the |
921 // an extra dropProtection() call (when we're back to the outer open(), | 918 // the same work. To avoid that, clears m_loader before calling cancel(). |
922 // we'll call dropProtection()). To avoid that, clears m_loader before | 919 RefPtr<ThreadableLoader> loader = m_loader.release(); |
923 // calling cancel. | 920 loader->cancel(); |
924 // | 921 |
925 // If, window.onload contains open() and send(), m_loader will be set to | 922 // If, window.onload contains open() and send(), m_loader will be set to |
926 // non 0 value. So, we cannot continue the outer open(). In such case, | 923 // non 0 value. So, we cannot continue the outer open(). In such case, |
927 // just abort the outer open() by returning false. | 924 // just abort the outer open() by returning false. |
928 RefPtr<ThreadableLoader> loader = m_loader.release(); | 925 if (m_loader) |
929 loader->cancel(); | 926 return false; |
930 | |
931 // Save to a local variable since we're going to drop protection. | |
932 bool newLoadStarted = m_loader; | |
933 | 927 |
934 // If abort() called internalAbort() and a nested open() ended up | 928 // If abort() called internalAbort() and a nested open() ended up |
935 // clearing the error flag, but didn't send(), make sure the error | 929 // clearing the error flag, but didn't send(), make sure the error |
936 // flag is still set. | 930 // flag is still set. |
937 if (!newLoadStarted) | 931 m_error = true; |
938 m_error = true; | |
939 | 932 |
940 if (async == DropProtectionAsync) | 933 return true; |
941 dropProtectionSoon(); | |
942 else | |
943 dropProtection(); | |
944 | |
945 return !newLoadStarted; | |
946 } | 934 } |
947 | 935 |
948 void XMLHttpRequest::clearResponse() | 936 void XMLHttpRequest::clearResponse() |
949 { | 937 { |
950 // FIXME: when we add the support for multi-part XHR, we will have to | 938 // FIXME: when we add the support for multi-part XHR, we will have to |
951 // be careful with this initialization. | 939 // be careful with this initialization. |
952 m_receivedLength = 0; | 940 m_receivedLength = 0; |
953 | 941 |
954 m_response = ResourceResponse(); | 942 m_response = ResourceResponse(); |
955 | 943 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1054 if (!m_uploadComplete) { | 1042 if (!m_uploadComplete) { |
1055 m_uploadComplete = true; | 1043 m_uploadComplete = true; |
1056 if (m_upload && m_uploadEventsAllowed) | 1044 if (m_upload && m_uploadEventsAllowed) |
1057 m_upload->handleRequestError(type); | 1045 m_upload->handleRequestError(type); |
1058 } | 1046 } |
1059 | 1047 |
1060 dispatchThrottledProgressEvent(EventTypeNames::progress, receivedLength, exp
ectedLength); | 1048 dispatchThrottledProgressEvent(EventTypeNames::progress, receivedLength, exp
ectedLength); |
1061 dispatchEventAndLoadEnd(type, receivedLength, expectedLength); | 1049 dispatchEventAndLoadEnd(type, receivedLength, expectedLength); |
1062 } | 1050 } |
1063 | 1051 |
1064 void XMLHttpRequest::dropProtectionSoon() | |
1065 { | |
1066 m_dropProtectionRunner.runAsync(); | |
1067 } | |
1068 | |
1069 void XMLHttpRequest::dropProtection() | |
1070 { | |
1071 unsetPendingActivity(this); | |
1072 } | |
1073 | |
1074 void XMLHttpRequest::overrideMimeType(const AtomicString& override) | 1052 void XMLHttpRequest::overrideMimeType(const AtomicString& override) |
1075 { | 1053 { |
1076 m_mimeTypeOverride = override; | 1054 m_mimeTypeOverride = override; |
1077 } | 1055 } |
1078 | 1056 |
1079 void XMLHttpRequest::setRequestHeader(const AtomicString& name, const AtomicStri
ng& value, ExceptionState& exceptionState) | 1057 void XMLHttpRequest::setRequestHeader(const AtomicString& name, const AtomicStri
ng& value, ExceptionState& exceptionState) |
1080 { | 1058 { |
1081 if (m_state != OPENED || m_loader) { | 1059 if (m_state != OPENED || m_loader) { |
1082 exceptionState.throwDOMException(InvalidStateError, "The object's state
must be OPENED."); | 1060 exceptionState.throwDOMException(InvalidStateError, "The object's state
must be OPENED."); |
1083 return; | 1061 return; |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1256 if (m_decoder) | 1234 if (m_decoder) |
1257 m_responseText = m_responseText.concatenateWith(m_decoder->flush()); | 1235 m_responseText = m_responseText.concatenateWith(m_decoder->flush()); |
1258 | 1236 |
1259 if (m_responseStream) | 1237 if (m_responseStream) |
1260 m_responseStream->finalize(); | 1238 m_responseStream->finalize(); |
1261 | 1239 |
1262 clearVariablesForLoading(); | 1240 clearVariablesForLoading(); |
1263 | 1241 |
1264 InspectorInstrumentation::didFinishXHRLoading(executionContext(), this, this
, identifier, m_responseText, m_method, m_url, m_lastSendURL, m_lastSendLineNumb
er); | 1242 InspectorInstrumentation::didFinishXHRLoading(executionContext(), this, this
, identifier, m_responseText, m_method, m_url, m_lastSendURL, m_lastSendLineNumb
er); |
1265 | 1243 |
1266 // Prevent dropProtection releasing the last reference, and retain |this| un
til the end of this method. | 1244 // hasPendingActivity() returns false when m_loader is 0. So, it's possible |
| 1245 // that the wrapper gets GC-ed during execution of the event. So, we need |
| 1246 // to keep this object alive to continue the rest of this method. |
1267 RefPtr<XMLHttpRequest> protect(this); | 1247 RefPtr<XMLHttpRequest> protect(this); |
1268 | 1248 |
1269 if (m_loader) { | 1249 if (m_loader) |
1270 m_loader = 0; | 1250 m_loader = 0; |
1271 dropProtection(); | |
1272 } | |
1273 | 1251 |
1274 changeState(DONE); | 1252 changeState(DONE); |
1275 } | 1253 } |
1276 | 1254 |
1277 void XMLHttpRequest::didSendData(unsigned long long bytesSent, unsigned long lon
g totalBytesToBeSent) | 1255 void XMLHttpRequest::didSendData(unsigned long long bytesSent, unsigned long lon
g totalBytesToBeSent) |
1278 { | 1256 { |
1279 WTF_LOG(Network, "XMLHttpRequest %p didSendData(%llu, %llu)", this, bytesSen
t, totalBytesToBeSent); | 1257 WTF_LOG(Network, "XMLHttpRequest %p didSendData(%llu, %llu)", this, bytesSen
t, totalBytesToBeSent); |
1280 | 1258 |
1281 if (!m_upload) | 1259 if (!m_upload) |
1282 return; | 1260 return; |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1375 return; | 1353 return; |
1376 | 1354 |
1377 m_downloadedBlobLength += dataLength; | 1355 m_downloadedBlobLength += dataLength; |
1378 trackProgress(dataLength); | 1356 trackProgress(dataLength); |
1379 } | 1357 } |
1380 | 1358 |
1381 void XMLHttpRequest::handleDidTimeout() | 1359 void XMLHttpRequest::handleDidTimeout() |
1382 { | 1360 { |
1383 WTF_LOG(Network, "XMLHttpRequest %p handleDidTimeout()", this); | 1361 WTF_LOG(Network, "XMLHttpRequest %p handleDidTimeout()", this); |
1384 | 1362 |
1385 // internalAbort() calls dropProtection(), which may release the last refere
nce. | |
1386 RefPtr<XMLHttpRequest> protect(this); | |
1387 | |
1388 // Response is cleared next, save needed progress event data. | 1363 // Response is cleared next, save needed progress event data. |
1389 long long expectedLength = m_response.expectedContentLength(); | 1364 long long expectedLength = m_response.expectedContentLength(); |
1390 long long receivedLength = m_receivedLength; | 1365 long long receivedLength = m_receivedLength; |
1391 | 1366 |
1392 if (!internalAbort()) | 1367 if (!internalAbort()) |
1393 return; | 1368 return; |
1394 | 1369 |
1395 handleDidFailGeneric(); | 1370 handleDidFailGeneric(); |
1396 handleRequestError(TimeoutError, EventTypeNames::timeout, receivedLength, ex
pectedLength); | 1371 handleRequestError(TimeoutError, EventTypeNames::timeout, receivedLength, ex
pectedLength); |
1397 } | 1372 } |
1398 | 1373 |
1399 void XMLHttpRequest::suspend() | 1374 void XMLHttpRequest::suspend() |
1400 { | 1375 { |
1401 m_progressEventThrottle.suspend(); | 1376 m_progressEventThrottle.suspend(); |
1402 } | 1377 } |
1403 | 1378 |
1404 void XMLHttpRequest::resume() | 1379 void XMLHttpRequest::resume() |
1405 { | 1380 { |
1406 m_progressEventThrottle.resume(); | 1381 m_progressEventThrottle.resume(); |
1407 } | 1382 } |
1408 | 1383 |
1409 void XMLHttpRequest::stop() | 1384 void XMLHttpRequest::stop() |
1410 { | 1385 { |
1411 internalAbort(DropProtectionAsync); | 1386 internalAbort(); |
| 1387 } |
| 1388 |
| 1389 bool XMLHttpRequest::hasPendingActivity() const |
| 1390 { |
| 1391 return m_loader; |
1412 } | 1392 } |
1413 | 1393 |
1414 void XMLHttpRequest::contextDestroyed() | 1394 void XMLHttpRequest::contextDestroyed() |
1415 { | 1395 { |
1416 ASSERT(!m_loader); | 1396 ASSERT(!m_loader); |
1417 ActiveDOMObject::contextDestroyed(); | 1397 ActiveDOMObject::contextDestroyed(); |
1418 } | 1398 } |
1419 | 1399 |
1420 const AtomicString& XMLHttpRequest::interfaceName() const | 1400 const AtomicString& XMLHttpRequest::interfaceName() const |
1421 { | 1401 { |
1422 return EventTargetNames::XMLHttpRequest; | 1402 return EventTargetNames::XMLHttpRequest; |
1423 } | 1403 } |
1424 | 1404 |
1425 ExecutionContext* XMLHttpRequest::executionContext() const | 1405 ExecutionContext* XMLHttpRequest::executionContext() const |
1426 { | 1406 { |
1427 return ActiveDOMObject::executionContext(); | 1407 return ActiveDOMObject::executionContext(); |
1428 } | 1408 } |
1429 | 1409 |
1430 } // namespace WebCore | 1410 } // namespace WebCore |
OLD | NEW |