| Index: Source/core/xml/XMLHttpRequest.cpp
|
| diff --git a/Source/core/xml/XMLHttpRequest.cpp b/Source/core/xml/XMLHttpRequest.cpp
|
| index 886d51490bf07df9c14c9cf04eda81181ba9c236..051a5e026038dba4c546dba07fba96f5f96cdf37 100644
|
| --- a/Source/core/xml/XMLHttpRequest.cpp
|
| +++ b/Source/core/xml/XMLHttpRequest.cpp
|
| @@ -481,7 +481,9 @@ void XMLHttpRequest::open(const String& method, const KURL& url, ExceptionState&
|
|
|
| void XMLHttpRequest::open(const String& method, const KURL& url, bool async, ExceptionState& es)
|
| {
|
| - internalAbort();
|
| + if (!internalAbort())
|
| + return;
|
| +
|
| State previousState = m_state;
|
| m_state = UNSENT;
|
| m_error = false;
|
| @@ -792,9 +794,6 @@ void XMLHttpRequest::createRequest(ExceptionState& es)
|
| // Neither this object nor the JavaScript wrapper should be deleted while
|
| // a request is in progress because we need to keep the listeners alive,
|
| // and they are referenced by the JavaScript wrapper.
|
| -
|
| - // m_loader was null, so there should be no pending activity at this point.
|
| - ASSERT(!hasPendingActivity());
|
| setPendingActivity(this);
|
| }
|
| } else {
|
| @@ -814,7 +813,8 @@ void XMLHttpRequest::abort()
|
|
|
| bool sendFlag = m_loader;
|
|
|
| - internalAbort();
|
| + if (!internalAbort())
|
| + return;
|
|
|
| clearResponseBuffers();
|
|
|
| @@ -837,7 +837,7 @@ void XMLHttpRequest::abort()
|
| }
|
| }
|
|
|
| -void XMLHttpRequest::internalAbort(DropProtection async)
|
| +bool XMLHttpRequest::internalAbort(DropProtection async)
|
| {
|
| m_error = true;
|
|
|
| @@ -851,15 +851,31 @@ void XMLHttpRequest::internalAbort(DropProtection async)
|
| m_responseStream->abort();
|
|
|
| if (!m_loader)
|
| - return;
|
| -
|
| - m_loader->cancel();
|
| - m_loader = 0;
|
| + return true;
|
| +
|
| + // Cancelling the ThreadableLoader m_loader may result in calling
|
| + // window.onload synchronously. If such an onload handler contains open()
|
| + // call on the same XMLHttpRequest object, reentry happens. If m_loader
|
| + // is left to be non 0, internalAbort() call for the inner open() makes
|
| + // an extra dropProtection() call (when we're back to the outer open(),
|
| + // we'll call dropProtection()). To avoid that, clears m_loader before
|
| + // calling cancel.
|
| + //
|
| + // If, window.onload contains open() and send(), m_loader will be set to
|
| + // non 0 value. So, we cannot continue the outer open(). In such case,
|
| + // just abort the outer open() by returning false.
|
| + RefPtr<ThreadableLoader> loader = m_loader.release();
|
| + loader->cancel();
|
| +
|
| + // Save to a local variable since we're going to drop protection.
|
| + bool newLoadStarted = m_loader;
|
|
|
| if (async == DropProtectionAsync)
|
| dropProtectionSoon();
|
| else
|
| dropProtection();
|
| +
|
| + return !newLoadStarted;
|
| }
|
|
|
| void XMLHttpRequest::clearResponse()
|
| @@ -1251,7 +1267,9 @@ void XMLHttpRequest::handleDidTimeout()
|
| {
|
| // internalAbort() calls dropProtection(), which may release the last reference.
|
| RefPtr<XMLHttpRequest> protect(this);
|
| - internalAbort();
|
| +
|
| + if (!internalAbort())
|
| + return;
|
|
|
| m_exceptionCode = TimeoutError;
|
|
|
|
|