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

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

Issue 24304004: [XHR] Abort method execution when m_loader->cancel() in internalAbort() caused reentry (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 7 years, 3 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 463 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 && !name.startsWith(staticData->m_secHeaderPrefix, false); 474 && !name.startsWith(staticData->m_secHeaderPrefix, false);
475 } 475 }
476 476
477 void XMLHttpRequest::open(const String& method, const KURL& url, ExceptionState& es) 477 void XMLHttpRequest::open(const String& method, const KURL& url, ExceptionState& es)
478 { 478 {
479 open(method, url, true, es); 479 open(method, url, true, es);
480 } 480 }
481 481
482 void XMLHttpRequest::open(const String& method, const KURL& url, bool async, Exc eptionState& es) 482 void XMLHttpRequest::open(const String& method, const KURL& url, bool async, Exc eptionState& es)
483 { 483 {
484 internalAbort(); 484 if (!internalAbort())
485 return;
486
485 State previousState = m_state; 487 State previousState = m_state;
486 m_state = UNSENT; 488 m_state = UNSENT;
487 m_error = false; 489 m_error = false;
488 m_uploadComplete = false; 490 m_uploadComplete = false;
489 491
490 // clear stuff from possible previous load 492 // clear stuff from possible previous load
491 clearResponse(); 493 clearResponse();
492 clearRequest(); 494 clearRequest();
493 495
494 ASSERT(m_state == UNSENT); 496 ASSERT(m_state == UNSENT);
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
785 // ThreadableLoader::create can return null here, for example if we're n o longer attached to a page. 787 // 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. 788 // 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>. 789 // FIXME: Maybe we need to be able to send XMLHttpRequests from onunload , <http://bugs.webkit.org/show_bug.cgi?id=10904>.
788 // FIXME: Maybe create() can return null for other reasons too? 790 // FIXME: Maybe create() can return null for other reasons too?
789 ASSERT(!m_loader); 791 ASSERT(!m_loader);
790 m_loader = ThreadableLoader::create(scriptExecutionContext(), this, requ est, options); 792 m_loader = ThreadableLoader::create(scriptExecutionContext(), this, requ est, options);
791 if (m_loader) { 793 if (m_loader) {
792 // Neither this object nor the JavaScript wrapper should be deleted while 794 // Neither this object nor the JavaScript wrapper should be deleted while
793 // a request is in progress because we need to keep the listeners al ive, 795 // a request is in progress because we need to keep the listeners al ive,
794 // and they are referenced by the JavaScript wrapper. 796 // and they are referenced by the JavaScript wrapper.
795
796 // m_loader was null, so there should be no pending activity at this point.
797 ASSERT(!hasPendingActivity());
798 setPendingActivity(this); 797 setPendingActivity(this);
799 } 798 }
800 } else { 799 } else {
801 ThreadableLoader::loadResourceSynchronously(scriptExecutionContext(), re quest, *this, options); 800 ThreadableLoader::loadResourceSynchronously(scriptExecutionContext(), re quest, *this, options);
802 } 801 }
803 802
804 if (!m_exceptionCode && m_error) 803 if (!m_exceptionCode && m_error)
805 m_exceptionCode = NetworkError; 804 m_exceptionCode = NetworkError;
806 if (m_exceptionCode) 805 if (m_exceptionCode)
807 es.throwDOMException(m_exceptionCode); 806 es.throwDOMException(m_exceptionCode);
808 } 807 }
809 808
810 void XMLHttpRequest::abort() 809 void XMLHttpRequest::abort()
811 { 810 {
812 // internalAbort() calls dropProtection(), which may release the last refere nce. 811 // internalAbort() calls dropProtection(), which may release the last refere nce.
813 RefPtr<XMLHttpRequest> protect(this); 812 RefPtr<XMLHttpRequest> protect(this);
814 813
815 bool sendFlag = m_loader; 814 bool sendFlag = m_loader;
816 815
817 internalAbort(); 816 if (!internalAbort())
817 return;
818 818
819 clearResponseBuffers(); 819 clearResponseBuffers();
820 820
821 // Clear headers as required by the spec 821 // Clear headers as required by the spec
822 m_requestHeaders.clear(); 822 m_requestHeaders.clear();
823 823
824 if ((m_state <= OPENED && !sendFlag) || m_state == DONE) 824 if ((m_state <= OPENED && !sendFlag) || m_state == DONE)
825 m_state = UNSENT; 825 m_state = UNSENT;
826 else { 826 else {
827 ASSERT(!m_loader); 827 ASSERT(!m_loader);
828 changeState(DONE); 828 changeState(DONE);
829 m_state = UNSENT; 829 m_state = UNSENT;
830 } 830 }
831 831
832 m_progressEventThrottle.dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent: :create(eventNames().abortEvent)); 832 m_progressEventThrottle.dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent: :create(eventNames().abortEvent));
833 if (!m_uploadComplete) { 833 if (!m_uploadComplete) {
834 m_uploadComplete = true; 834 m_uploadComplete = true;
835 if (m_upload && m_uploadEventsAllowed) 835 if (m_upload && m_uploadEventsAllowed)
836 m_upload->dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::creat e(eventNames().abortEvent)); 836 m_upload->dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::creat e(eventNames().abortEvent));
837 } 837 }
838 } 838 }
839 839
840 void XMLHttpRequest::internalAbort(DropProtection async) 840 bool XMLHttpRequest::internalAbort(DropProtection async)
841 { 841 {
842 m_error = true; 842 m_error = true;
843 843
844 // FIXME: when we add the support for multi-part XHR, we will have to think be careful with this initialization. 844 // FIXME: when we add the support for multi-part XHR, we will have to think be careful with this initialization.
845 m_receivedLength = 0; 845 m_receivedLength = 0;
846 m_decoder = 0; 846 m_decoder = 0;
847 847
848 InspectorInstrumentation::didFailXHRLoading(scriptExecutionContext(), this); 848 InspectorInstrumentation::didFailXHRLoading(scriptExecutionContext(), this);
849 849
850 if (m_responseStream && m_state != DONE) 850 if (m_responseStream && m_state != DONE)
851 m_responseStream->abort(); 851 m_responseStream->abort();
852 852
853 if (!m_loader) 853 if (!m_loader)
854 return; 854 return true;
855 855
856 m_loader->cancel(); 856 // Cancelling the ThreadableLoader m_loader may result in calling
857 m_loader = 0; 857 // window.onload synchronously. If such an onload handler contains open()
858 // call on the same XMLHttpRequest object, reentry happens. If m_loader
859 // is left to be non 0, internalAbort() call for the inner open() makes
860 // an extra dropProtection() call (when we're back to the outer open(),
861 // we'll call dropProtection()). To avoid that, clears m_loader before
862 // calling cancel.
863 //
864 // If, window.onload contains open() and send(), m_loader will be set to
865 // non 0 value. So, we cannot continue the outer open(). In such case,
866 // just abort the outer open() by returning false.
867 RefPtr<ThreadableLoader> loader = m_loader.release();
868 loader->cancel();
869
870 // Save to a local variable since we're going to drop protection.
871 bool newLoadStarted = m_loader;
858 872
859 if (async == DropProtectionAsync) 873 if (async == DropProtectionAsync)
860 dropProtectionSoon(); 874 dropProtectionSoon();
861 else 875 else
862 dropProtection(); 876 dropProtection();
877
878 return !newLoadStarted;
863 } 879 }
864 880
865 void XMLHttpRequest::clearResponse() 881 void XMLHttpRequest::clearResponse()
866 { 882 {
867 m_response = ResourceResponse(); 883 m_response = ResourceResponse();
868 clearResponseBuffers(); 884 clearResponseBuffers();
869 } 885 }
870 886
871 void XMLHttpRequest::clearResponseBuffers() 887 void XMLHttpRequest::clearResponseBuffers()
872 { 888 {
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after
1244 else 1260 else
1245 // Firefox calls readyStateChanged every time it receives data, 4449 442 1261 // Firefox calls readyStateChanged every time it receives data, 4449 442
1246 callReadyStateChangeListener(); 1262 callReadyStateChangeListener();
1247 } 1263 }
1248 } 1264 }
1249 1265
1250 void XMLHttpRequest::handleDidTimeout() 1266 void XMLHttpRequest::handleDidTimeout()
1251 { 1267 {
1252 // internalAbort() calls dropProtection(), which may release the last refere nce. 1268 // internalAbort() calls dropProtection(), which may release the last refere nce.
1253 RefPtr<XMLHttpRequest> protect(this); 1269 RefPtr<XMLHttpRequest> protect(this);
1254 internalAbort(); 1270
1271 if (!internalAbort())
1272 return;
1255 1273
1256 m_exceptionCode = TimeoutError; 1274 m_exceptionCode = TimeoutError;
1257 1275
1258 handleDidFailGeneric(); 1276 handleDidFailGeneric();
1259 1277
1260 if (!m_async) { 1278 if (!m_async) {
1261 m_state = DONE; 1279 m_state = DONE;
1262 return; 1280 return;
1263 } 1281 }
1264 changeState(DONE); 1282 changeState(DONE);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1296 { 1314 {
1297 return eventNames().interfaceForXMLHttpRequest; 1315 return eventNames().interfaceForXMLHttpRequest;
1298 } 1316 }
1299 1317
1300 ScriptExecutionContext* XMLHttpRequest::scriptExecutionContext() const 1318 ScriptExecutionContext* XMLHttpRequest::scriptExecutionContext() const
1301 { 1319 {
1302 return ActiveDOMObject::scriptExecutionContext(); 1320 return ActiveDOMObject::scriptExecutionContext();
1303 } 1321 }
1304 1322
1305 } // namespace WebCore 1323 } // 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