Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(463)

Side by Side Diff: Source/core/xml/XMLHttpRequest.cpp

Issue 104363002: [XHR] Use hasPendingActivity() to manage XHR's life time. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Rebase Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/core/xml/XMLHttpRequest.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « Source/core/xml/XMLHttpRequest.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698