XMLHttpRequests should not prevent a page from entering PageCache
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Mar 2015 17:58:50 +0000 (17:58 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Mar 2015 17:58:50 +0000 (17:58 +0000)
commit617d74084087c979551b514af3e10a71b1982529
tree5f582d0729342f9fc50ca571314742aabb6e5d2b
parent34c195300dc5e80a51861cc7d4322023f5706c62
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.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@181480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
15 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/navigation/page-cache-xhr-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/navigation/page-cache-xhr.html [new file with mode: 0644]
LayoutTests/http/tests/navigation/resources/page-cache-helper.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/history/PageCache.cpp
Source/WebCore/loader/DocumentLoader.cpp
Source/WebCore/loader/DocumentThreadableLoader.cpp
Source/WebCore/loader/DocumentThreadableLoader.h
Source/WebCore/loader/ThreadableLoader.h
Source/WebCore/loader/cache/CachedResource.cpp
Source/WebCore/loader/cache/CachedResource.h
Source/WebCore/loader/cache/CachedResourceClient.h
Source/WebCore/xml/XMLHttpRequest.cpp
Source/WebCore/xml/XMLHttpRequest.h