Title: [181480] trunk
Revision
181480
Author
[email protected]
Date
2015-03-13 10:58:50 -0700 (Fri, 13 Mar 2015)

Log Message

XMLHttpRequests should not prevent a page from entering PageCache
https://bugs.webkit.org/show_bug.cgi?id=142612
<rdar://problem/19923085>

Reviewed by Alexey Proskuryakov.

Source/WebCore:

Make XMLHttpRequest ActiveDOMObjects suspendable in most cases to
drastically improve the likelihood of pages using them to enter
PageCache. XMLHttpRequest used to be only suspendable when not
loading. After this patch, if the XMLHttpRequest is loading when
navigating away from the page, it will be aborted and the page
will enter the PageCache. Upon restoring the page from PageCache,
the XMLHttpRequests' error handlers will be executed to give them
a chance to reload if they want to.

Test: http/tests/navigation/page-cache-xhr.html

* history/PageCache.cpp:
(WebCore::logCanCacheFrameDecision):
(WebCore::PageCache::canCachePageContainingThisFrame):
Do not prevent a page to enter the page cache ff the main document has
an error that is a cancellation and all remaining subresource loaders
are for XHR. We extend the pre-existing mechanism used on iOS, which
allowed PageCaching if the remaining resource loads are for images.

* loader/DocumentLoader.cpp:
(WebCore::areAllLoadersPageCacheAcceptable):
Mark XHR loaders as PageCache acceptable.

* loader/DocumentThreadableLoader.cpp:
(WebCore::DocumentThreadableLoader::isXMLHttpRequest):
* loader/DocumentThreadableLoader.h:
* loader/ThreadableLoader.h:
* loader/cache/CachedResource.cpp:
(WebCore::CachedResource::areAllClientsXMLHttpRequests):
* loader/cache/CachedResource.h:
* loader/cache/CachedResourceClient.h:
(WebCore::CachedResourceClient::isXMLHttpRequest):
* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::XMLHttpRequest):
(WebCore::XMLHttpRequest::createRequest):
(WebCore::XMLHttpRequest::canSuspend):
Report that we can suspend XMLHttpRequests as long as the window load
event has already fired. If the window load event has not fired yet,
it would be unsafe to cancel the load in suspend() as it would
potentially cause arbitrary JS execution while suspending.

(WebCore::XMLHttpRequest::suspend):
If suspending for PageCache and the request is currently loading, abort
the load and mark that we should fire the error event upon restoring
from PageCache.

(WebCore::XMLHttpRequest::resume):
(WebCore::XMLHttpRequest::resumeTimerFired):
Upon resuming, fire the error event in a timer if the load was aborted
for suspending. We need to do this in a timer because we are not allowed
to execute arbitrary JS inside resume().

(WebCore::XMLHttpRequest::stop):
Add a assertion to make sure we are not firing event inside stop() as
this would potentially cause arbitrary JS execution and it would be
unsafe. It seems to me that our code is currently unsafe but the
assertion does not seem to be hit by our current layout tests. I am
adding the assertion as it would make it clear we have a bug and we
need to fix it.

* xml/XMLHttpRequest.h:

LayoutTests:

Add a tests to make sure that loading XMLHttpRequests do not prevent a
page from entering PageCache.

* http/tests/navigation/page-cache-xhr-expected.txt: Added.
* http/tests/navigation/page-cache-xhr.html: Added.
* http/tests/navigation/resources/page-cache-helper.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (181479 => 181480)


--- trunk/LayoutTests/ChangeLog	2015-03-13 16:00:03 UTC (rev 181479)
+++ trunk/LayoutTests/ChangeLog	2015-03-13 17:58:50 UTC (rev 181480)
@@ -1,3 +1,18 @@
+2015-03-13  Chris Dumez  <[email protected]>
+
+        XMLHttpRequests should not prevent a page from entering PageCache
+        https://bugs.webkit.org/show_bug.cgi?id=142612
+        <rdar://problem/19923085>
+
+        Reviewed by Alexey Proskuryakov.
+
+        Add a tests to make sure that loading XMLHttpRequests do not prevent a
+        page from entering PageCache.
+
+        * http/tests/navigation/page-cache-xhr-expected.txt: Added.
+        * http/tests/navigation/page-cache-xhr.html: Added.
+        * http/tests/navigation/resources/page-cache-helper.html: Added.
+
 2015-03-13  Marcos Chavarría Teijeiro  <[email protected]>
 
         Unreviewed Gardening 13th March.

Added: trunk/LayoutTests/http/tests/navigation/page-cache-xhr-expected.txt (0 => 181480)


--- trunk/LayoutTests/http/tests/navigation/page-cache-xhr-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/navigation/page-cache-xhr-expected.txt	2015-03-13 17:58:50 UTC (rev 181480)
@@ -0,0 +1,15 @@
+Tests that a page with a loading XMLHttpRequest goes into the page cache.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+pageshow - not from cache
+pagehide - entering cache
+pageshow - from cache
+PASS Page did enter and was restored from the page cache
+PASS Executed the XHR error handler after restoring from page cache
+PASS xhr.status is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/http/tests/navigation/page-cache-xhr.html (0 => 181480)


--- trunk/LayoutTests/http/tests/navigation/page-cache-xhr.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/navigation/page-cache-xhr.html	2015-03-13 17:58:50 UTC (rev 181480)
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+description('Tests that a page with a loading XMLHttpRequest goes into the page cache.');
+window.jsTestIsAsync = true;
+
+var restoredFromPageCache = false;
+
+if (window.testRunner)
+    testRunner.overridePreference("WebKitUsesPageCachePreferenceKey", 1);
+
+window.addEventListener("pageshow", function(event) {
+    debug("pageshow - " + (event.persisted ? "" : "not ") + "from cache");
+
+    if (event.persisted) {
+        testPassed("Page did enter and was restored from the page cache");
+        restoredFromPageCache = true;
+    }
+}, false);
+
+window.addEventListener("pagehide", function(event) {
+    debug("pagehide - " + (event.persisted ? "" : "not ") + "entering cache");
+    if (!event.persisted) {
+        testFailed("Page did not enter the page cache.");
+        finishJSTest();
+    }
+}, false);
+
+function xhrLoaded()
+{
+    testFailed("The XMLHttpRequest should not haved loaded");
+    finishJSTest();
+}
+
+function xhrError() {
+    if (restoredFromPageCache)
+        testPassed("Executed the XHR error handler after restoring from page cache");
+    else
+        testFailed("Executed the XHR error handler before restoring from page cache");
+
+    shouldBe("xhr.status", "0");
+    finishJSTest();
+}
+
+window.addEventListener('load', function() {
+    xhr = new XMLHttpRequest();
+    xhr._onload_ = xhrLoaded;
+    xhr._onerror_ = xhrError;
+    // Slow loading XHR (3-second stall).
+    xhr.open("GET", "/resources/load-and-stall.cgi?name=../../../http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout.js&stallFor=3&stallAt=0&mimeType=text/plain", true);
+    xhr.send();
+
+    // This needs to happen in a setTimeout because a navigation inside the onload handler would
+    // not create a history entry.
+    setTimeout(function() {
+      // Force a back navigation back to this page.
+      window.location.href = ""
+    }, 0);
+}, false);
+
+</script>
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/http/tests/navigation/resources/page-cache-helper.html (0 => 181480)


--- trunk/LayoutTests/http/tests/navigation/resources/page-cache-helper.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/navigation/resources/page-cache-helper.html	2015-03-13 17:58:50 UTC (rev 181480)
@@ -0,0 +1,9 @@
+This page should go back. If a test outputs the contents of this
+page, then the test page failed to enter the page cache.
+<script>
+  window.addEventListener("load", function() {
+    setTimeout(function() {
+      history.back();
+    }, 0);
+  }, false);
+</script>

Modified: trunk/Source/WebCore/ChangeLog (181479 => 181480)


--- trunk/Source/WebCore/ChangeLog	2015-03-13 16:00:03 UTC (rev 181479)
+++ trunk/Source/WebCore/ChangeLog	2015-03-13 17:58:50 UTC (rev 181480)
@@ -1,3 +1,73 @@
+2015-03-13  Chris Dumez  <[email protected]>
+
+        XMLHttpRequests should not prevent a page from entering PageCache
+        https://bugs.webkit.org/show_bug.cgi?id=142612
+        <rdar://problem/19923085>
+
+        Reviewed by Alexey Proskuryakov.
+
+        Make XMLHttpRequest ActiveDOMObjects suspendable in most cases to
+        drastically improve the likelihood of pages using them to enter
+        PageCache. XMLHttpRequest used to be only suspendable when not
+        loading. After this patch, if the XMLHttpRequest is loading when
+        navigating away from the page, it will be aborted and the page
+        will enter the PageCache. Upon restoring the page from PageCache,
+        the XMLHttpRequests' error handlers will be executed to give them
+        a chance to reload if they want to.
+
+        Test: http/tests/navigation/page-cache-xhr.html
+
+        * history/PageCache.cpp:
+        (WebCore::logCanCacheFrameDecision):
+        (WebCore::PageCache::canCachePageContainingThisFrame):
+        Do not prevent a page to enter the page cache ff the main document has
+        an error that is a cancellation and all remaining subresource loaders
+        are for XHR. We extend the pre-existing mechanism used on iOS, which
+        allowed PageCaching if the remaining resource loads are for images.
+
+        * loader/DocumentLoader.cpp:
+        (WebCore::areAllLoadersPageCacheAcceptable):
+        Mark XHR loaders as PageCache acceptable.
+
+        * loader/DocumentThreadableLoader.cpp:
+        (WebCore::DocumentThreadableLoader::isXMLHttpRequest):
+        * loader/DocumentThreadableLoader.h:
+        * loader/ThreadableLoader.h:
+        * loader/cache/CachedResource.cpp:
+        (WebCore::CachedResource::areAllClientsXMLHttpRequests):
+        * loader/cache/CachedResource.h:
+        * loader/cache/CachedResourceClient.h:
+        (WebCore::CachedResourceClient::isXMLHttpRequest):
+        * xml/XMLHttpRequest.cpp:
+        (WebCore::XMLHttpRequest::XMLHttpRequest):
+        (WebCore::XMLHttpRequest::createRequest):
+        (WebCore::XMLHttpRequest::canSuspend):
+        Report that we can suspend XMLHttpRequests as long as the window load
+        event has already fired. If the window load event has not fired yet,
+        it would be unsafe to cancel the load in suspend() as it would
+        potentially cause arbitrary JS execution while suspending.
+
+        (WebCore::XMLHttpRequest::suspend):
+        If suspending for PageCache and the request is currently loading, abort
+        the load and mark that we should fire the error event upon restoring
+        from PageCache.
+
+        (WebCore::XMLHttpRequest::resume):
+        (WebCore::XMLHttpRequest::resumeTimerFired):
+        Upon resuming, fire the error event in a timer if the load was aborted
+        for suspending. We need to do this in a timer because we are not allowed
+        to execute arbitrary JS inside resume().
+
+        (WebCore::XMLHttpRequest::stop):
+        Add a assertion to make sure we are not firing event inside stop() as
+        this would potentially cause arbitrary JS execution and it would be
+        unsafe. It seems to me that our code is currently unsafe but the
+        assertion does not seem to be hit by our current layout tests. I am
+        adding the assertion as it would make it clear we have a bug and we
+        need to fix it.
+
+        * xml/XMLHttpRequest.h:
+
 2015-03-13  Joonghun Park  <[email protected]>
 
         Fix Debug build error 'comparison is always true due to limited range of data type [-Werror=type-limits]'

Modified: trunk/Source/WebCore/history/PageCache.cpp (181479 => 181480)


--- trunk/Source/WebCore/history/PageCache.cpp	2015-03-13 16:00:03 UTC (rev 181479)
+++ trunk/Source/WebCore/history/PageCache.cpp	2015-03-13 17:58:50 UTC (rev 181480)
@@ -128,14 +128,11 @@
     if (!frame.loader().documentLoader()->mainDocumentError().isNull()) {
         PCLOG("   -Main document has an error");
         logPageCacheFailureDiagnosticMessage(diagnosticLoggingClient, DiagnosticLoggingKeys::mainDocumentErrorKey());
-#if !PLATFORM(IOS)
-        rejectReasons |= 1 << MainDocumentError;
-#else
+
         if (frame.loader().documentLoader()->mainDocumentError().isCancellation() && frame.loader().documentLoader()->subresourceLoadersArePageCacheAcceptable())
-            PCLOG("    -But, it was a cancellation and all loaders during the cancel were loading images.");
+            PCLOG("    -But, it was a cancellation and all loaders during the cancelation were loading images or XHR.");
         else
             rejectReasons |= 1 << MainDocumentError;
-#endif
     }
     if (frame.loader().documentLoader()->substituteData().isValid() && frame.loader().documentLoader()->substituteData().failingURL().isEmpty()) {
         PCLOG("   -Frame is an error page");
@@ -304,11 +301,7 @@
     Document* document = frame.document();
     
     return documentLoader
-#if !PLATFORM(IOS)
-        && documentLoader->mainDocumentError().isNull()
-#else
         && (documentLoader->mainDocumentError().isNull() || (documentLoader->mainDocumentError().isCancellation() && documentLoader->subresourceLoadersArePageCacheAcceptable()))
-#endif
         // Do not cache error pages (these can be recognized as pages with substitute data or unreachable URLs).
         && !(documentLoader->substituteData().isValid() && !documentLoader->substituteData().failingURL().isEmpty())
         && (!frameLoader.subframeLoader().containsPlugins() || frame.page()->settings().pageCacheSupportsPlugins())

Modified: trunk/Source/WebCore/loader/DocumentLoader.cpp (181479 => 181480)


--- trunk/Source/WebCore/loader/DocumentLoader.cpp	2015-03-13 16:00:03 UTC (rev 181479)
+++ trunk/Source/WebCore/loader/DocumentLoader.cpp	2015-03-13 17:58:50 UTC (rev 181480)
@@ -99,19 +99,16 @@
     Vector<RefPtr<ResourceLoader>> loadersCopy;
     copyValuesToVector(loaders, loadersCopy);
     for (auto& loader : loadersCopy) {
-        ResourceHandle* handle = loader->handle();
-        if (!handle)
-            return false;
-
         if (!loader->frameLoader())
             return false;
 
-        CachedResource* cachedResource = MemoryCache::singleton().resourceForURL(handle->firstRequest().url(), loader->frameLoader()->frame().page()->sessionID());
+        CachedResource* cachedResource = MemoryCache::singleton().resourceForURL(loader->request().url(), loader->frameLoader()->frame().page()->sessionID());
         if (!cachedResource)
             return false;
 
+        // Only image and XHR loads do prevent the page from entering the PageCache.
         // All non-image loads will prevent the page from entering the PageCache.
-        if (!cachedResource->isImage())
+        if (!cachedResource->isImage() && !cachedResource->areAllClientsXMLHttpRequests())
             return false;
     }
     return true;

Modified: trunk/Source/WebCore/loader/DocumentThreadableLoader.cpp (181479 => 181480)


--- trunk/Source/WebCore/loader/DocumentThreadableLoader.cpp	2015-03-13 16:00:03 UTC (rev 181479)
+++ trunk/Source/WebCore/loader/DocumentThreadableLoader.cpp	2015-03-13 17:58:50 UTC (rev 181480)
@@ -34,6 +34,7 @@
 #include "CachedRawResource.h"
 #include "CachedResourceLoader.h"
 #include "CachedResourceRequest.h"
+#include "CachedResourceRequestInitiators.h"
 #include "CrossOriginAccessControl.h"
 #include "CrossOriginPreflightResultCache.h"
 #include "Document.h"
@@ -418,6 +419,11 @@
     return m_sameOriginRequest && securityOrigin()->canRequest(url);
 }
 
+bool DocumentThreadableLoader::isXMLHttpRequest() const
+{
+    return m_options.initiator == cachedResourceRequestInitiators().xmlhttprequest;
+}
+
 SecurityOrigin* DocumentThreadableLoader::securityOrigin() const
 {
     return m_options.securityOrigin ? m_options.securityOrigin.get() : m_document.securityOrigin();

Modified: trunk/Source/WebCore/loader/DocumentThreadableLoader.h (181479 => 181480)


--- trunk/Source/WebCore/loader/DocumentThreadableLoader.h	2015-03-13 16:00:03 UTC (rev 181479)
+++ trunk/Source/WebCore/loader/DocumentThreadableLoader.h	2015-03-13 17:58:50 UTC (rev 181480)
@@ -96,6 +96,8 @@
         void loadRequest(const ResourceRequest&, SecurityCheckPolicy);
         bool isAllowedRedirect(const URL&);
 
+        bool isXMLHttpRequest() const override final;
+
         SecurityOrigin* securityOrigin() const;
 
         CachedResourceHandle<CachedRawResource> m_resource;

Modified: trunk/Source/WebCore/loader/ThreadableLoader.h (181479 => 181480)


--- trunk/Source/WebCore/loader/ThreadableLoader.h	2015-03-13 16:00:03 UTC (rev 181479)
+++ trunk/Source/WebCore/loader/ThreadableLoader.h	2015-03-13 17:58:50 UTC (rev 181480)
@@ -36,10 +36,7 @@
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefPtr.h>
 #include <wtf/Vector.h>
-
-#if ENABLE(RESOURCE_TIMING)
 #include <wtf/text/AtomicString.h>
-#endif
 
 namespace WebCore {
 
@@ -69,9 +66,7 @@
         PreflightPolicy preflightPolicy; // If AccessControl is used, how to determine if a preflight is needed.
         CrossOriginRequestPolicy crossOriginRequestPolicy;
         RefPtr<SecurityOrigin> securityOrigin;
-#if ENABLE(RESOURCE_TIMING)
         AtomicString initiator;
-#endif
     };
 
     // Useful for doing loader operations from any thread (not threadsafe, 

Modified: trunk/Source/WebCore/loader/cache/CachedResource.cpp (181479 => 181480)


--- trunk/Source/WebCore/loader/cache/CachedResource.cpp	2015-03-13 16:00:03 UTC (rev 181479)
+++ trunk/Source/WebCore/loader/cache/CachedResource.cpp	2015-03-13 17:58:50 UTC (rev 181480)
@@ -735,6 +735,18 @@
     return sizeof(CachedResource) + m_response.memoryUsage() + kAverageClientsHashMapSize + m_resourceRequest.url().string().length() * 2;
 }
 
+bool CachedResource::areAllClientsXMLHttpRequests() const
+{
+    if (type() != RawResource)
+        return false;
+
+    for (auto& client : m_clients) {
+        if (!client.key->isXMLHttpRequest())
+            return false;
+    }
+    return true;
+}
+
 void CachedResource::setLoadPriority(const Optional<ResourceLoadPriority>& loadPriority)
 {
     if (loadPriority)

Modified: trunk/Source/WebCore/loader/cache/CachedResource.h (181479 => 181480)


--- trunk/Source/WebCore/loader/cache/CachedResource.h	2015-03-13 16:00:03 UTC (rev 181479)
+++ trunk/Source/WebCore/loader/cache/CachedResource.h	2015-03-13 17:58:50 UTC (rev 181480)
@@ -158,6 +158,8 @@
 
     SubresourceLoader* loader() { return m_loader.get(); }
 
+    bool areAllClientsXMLHttpRequests() const;
+
     bool isImage() const { return type() == ImageResource; }
     // FIXME: CachedRawResource could be either a main resource or a raw XHR resource.
     bool isMainOrRawResource() const { return type() == MainResource || type() == RawResource; }

Modified: trunk/Source/WebCore/loader/cache/CachedResourceClient.h (181479 => 181480)


--- trunk/Source/WebCore/loader/cache/CachedResourceClient.h	2015-03-13 16:00:03 UTC (rev 181479)
+++ trunk/Source/WebCore/loader/cache/CachedResourceClient.h	2015-03-13 17:58:50 UTC (rev 181480)
@@ -43,6 +43,7 @@
     virtual ~CachedResourceClient() { }
     virtual void notifyFinished(CachedResource*) { }
     virtual void deprecatedDidReceiveCachedResource(CachedResource*) { }
+    virtual bool isXMLHttpRequest() const { return false; }
 
     static CachedResourceClientType expectedType() { return BaseResourceType; }
     virtual CachedResourceClientType resourceClientType() const { return expectedType(); }

Modified: trunk/Source/WebCore/xml/XMLHttpRequest.cpp (181479 => 181480)


--- trunk/Source/WebCore/xml/XMLHttpRequest.cpp	2015-03-13 16:00:03 UTC (rev 181479)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.cpp	2015-03-13 17:58:50 UTC (rev 181480)
@@ -24,6 +24,7 @@
 #include "XMLHttpRequest.h"
 
 #include "Blob.h"
+#include "CachedResourceRequestInitiators.h"
 #include "ContentSecurityPolicy.h"
 #include "CrossOriginAccessControl.h"
 #include "DOMFormData.h"
@@ -64,10 +65,6 @@
 #include <wtf/StdLibExtras.h>
 #include <wtf/text/CString.h>
 
-#if ENABLE(RESOURCE_TIMING)
-#include "CachedResourceRequestInitiators.h"
-#endif
-
 namespace WebCore {
 
 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, xmlHttpRequestCounter, ("XMLHttpRequest"));
@@ -139,6 +136,8 @@
     , m_progressEventThrottle(this)
     , m_responseTypeCode(ResponseTypeDefault)
     , m_responseCacheIsValid(false)
+    , m_resumeTimer(*this, &XMLHttpRequest::resumeTimerFired)
+    , m_dispatchErrorOnResuming(false)
 {
 #ifndef NDEBUG
     xmlHttpRequestCounter.increment();
@@ -764,9 +763,7 @@
     options.setAllowCredentials((m_sameOriginRequest || m_includeCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials);
     options.crossOriginRequestPolicy = UseAccessControl;
     options.securityOrigin = securityOrigin();
-#if ENABLE(RESOURCE_TIMING)
     options.initiator = cachedResourceRequestInitiators().xmlhttprequest;
-#endif
 
 #if ENABLE(XHR_TIMEOUT)
     if (m_timeoutMilliseconds)
@@ -1255,7 +1252,10 @@
 
 bool XMLHttpRequest::canSuspend() const
 {
-    return !m_loader;
+    // If the load event has not fired yet, cancelling the load in suspend() may cause
+    // the load event to be fired and arbitrary JS execution, which would be unsafe.
+    // Therefore, we prevent suspending in this case.
+    return document()->loadEventFinished();
 }
 
 const char* XMLHttpRequest::activeDOMObjectName() const
@@ -1263,18 +1263,50 @@
     return "XMLHttpRequest";
 }
 
-void XMLHttpRequest::suspend(ReasonForSuspension)
+void XMLHttpRequest::suspend(ReasonForSuspension reason)
 {
+    NoEventDispatchAssertion assertNoEventDispatch;
+
     m_progressEventThrottle.suspend();
+
+    if (m_resumeTimer.isActive()) {
+        m_resumeTimer.stop();
+        m_dispatchErrorOnResuming = true;
+    }
+
+    if (reason == ActiveDOMObject::DocumentWillBecomeInactive && m_loader) {
+        // Going into PageCache, abort the request and dispatch a network error on resuming.
+        genericError();
+        m_dispatchErrorOnResuming = true;
+        bool aborted = internalAbort();
+        // It should not be possible to restart the load when aborting in suspend() because
+        // we are not allowed to execute in JS in suspend().
+        ASSERT_UNUSED(aborted, aborted);
+    }
 }
 
 void XMLHttpRequest::resume()
 {
+    NoEventDispatchAssertion assertNoEventDispatch;
+
     m_progressEventThrottle.resume();
+
+    // We are not allowed to execute arbitrary JS in resume() so dispatch
+    // the error event in a timer.
+    if (m_dispatchErrorOnResuming && !m_resumeTimer.isActive())
+        m_resumeTimer.startOneShot(0);
 }
 
+void XMLHttpRequest::resumeTimerFired()
+{
+    ASSERT(m_dispatchErrorOnResuming);
+    m_dispatchErrorOnResuming = false;
+    dispatchErrorEvents(eventNames().errorEvent);
+}
+
 void XMLHttpRequest::stop()
 {
+    NoEventDispatchAssertion assertNoEventDispatch;
     internalAbort();
 }
 

Modified: trunk/Source/WebCore/xml/XMLHttpRequest.h (181479 => 181480)


--- trunk/Source/WebCore/xml/XMLHttpRequest.h	2015-03-13 16:00:03 UTC (rev 181479)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.h	2015-03-13 17:58:50 UTC (rev 181480)
@@ -205,6 +205,8 @@
 
     void dispatchErrorEvents(const AtomicString&);
 
+    void resumeTimerFired();
+
     std::unique_ptr<XMLHttpRequestUpload> m_upload;
 
     URL m_url;
@@ -254,6 +256,9 @@
     // An enum corresponding to the allowed string values for the responseType attribute.
     ResponseTypeCode m_responseTypeCode;
     bool m_responseCacheIsValid;
+
+    Timer m_resumeTimer;
+    bool m_dispatchErrorOnResuming;
 };
 
 } // namespace WebCore
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to