Diff
Modified: trunk/LayoutTests/ChangeLog (251494 => 251495)
--- trunk/LayoutTests/ChangeLog 2019-10-23 20:16:00 UTC (rev 251494)
+++ trunk/LayoutTests/ChangeLog 2019-10-23 20:38:22 UTC (rev 251495)
@@ -1,3 +1,21 @@
+2019-10-23 Chris Dumez <cdu...@apple.com>
+
+ FetchRequest should not prevent entering the back/forward cache
+ https://bugs.webkit.org/show_bug.cgi?id=203091
+ <rdar://problem/56525333>
+
+ Reviewed by Youenn Fablet.
+
+ Add layout test coverage.
+
+ * TestExpectations:
+ * fast/history/page-cache-active-fetch-request-blobReadAsBlob-expected.txt: Added.
+ * fast/history/page-cache-active-fetch-request-blobReadAsBlob.html: Added.
+ * fast/history/page-cache-active-fetch-request-blobReadAsReadableStream-expected.txt: Added.
+ * fast/history/page-cache-active-fetch-request-blobReadAsReadableStream.html: Added.
+ * fast/history/page-cache-active-fetch-request-blobReadAsText-expected.txt: Added.
+ * fast/history/page-cache-active-fetch-request-blobReadAsText.html: Added.
+
2019-10-23 Yury Semikhatsky <yu...@chromium.org>
Web Inspector: notify inspector when provisional page is created, committed and destroyed
Modified: trunk/LayoutTests/TestExpectations (251494 => 251495)
--- trunk/LayoutTests/TestExpectations 2019-10-23 20:16:00 UTC (rev 251494)
+++ trunk/LayoutTests/TestExpectations 2019-10-23 20:38:22 UTC (rev 251495)
@@ -266,6 +266,9 @@
fast/files/file-reader-back-forward-cache.html [ DumpJSConsoleLogInStdErr ]
fast/history/page-cache-createImageBitmap.html [ DumpJSConsoleLogInStdErr ]
http/tests/navigation/page-cache-xhr-in-loading-iframe.html [ DumpJSConsoleLogInStdErr ]
+fast/history/page-cache-active-fetch-request-blobReadAsBlob.html [ DumpJSConsoleLogInStdErr ]
+fast/history/page-cache-active-fetch-request-blobReadAsText.html [ DumpJSConsoleLogInStdErr ]
+fast/history/page-cache-active-fetch-request-blobReadAsReadableStream.html [ DumpJSConsoleLogInStdErr ]
webkit.org/b/202495 imported/w3c/web-platform-tests/shadow-dom/directionality-002.tentative.html [ ImageOnlyFailure ]
Added: trunk/LayoutTests/fast/history/page-cache-active-fetch-request-blobReadAsBlob-expected.txt (0 => 251495)
--- trunk/LayoutTests/fast/history/page-cache-active-fetch-request-blobReadAsBlob-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/history/page-cache-active-fetch-request-blobReadAsBlob-expected.txt 2019-10-23 20:38:22 UTC (rev 251495)
@@ -0,0 +1,14 @@
+Tests that a page with an active fetch request is able to enter the back/forward 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 back/forward cache
+PASS Promise resolved after restoring from the back/forward cache.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/history/page-cache-active-fetch-request-blobReadAsBlob.html (0 => 251495)
--- trunk/LayoutTests/fast/history/page-cache-active-fetch-request-blobReadAsBlob.html (rev 0)
+++ trunk/LayoutTests/fast/history/page-cache-active-fetch-request-blobReadAsBlob.html 2019-10-23 20:38:22 UTC (rev 251495)
@@ -0,0 +1,55 @@
+<!-- webkit-test-runner [ enableBackForwardCache=true ] -->
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+description('Tests that a page with an active fetch request is able to enter the back/forward cache.');
+window.jsTestIsAsync = true;
+let restoredFromCache = false;
+
+window.addEventListener("pageshow", function(event) {
+ debug("pageshow - " + (event.persisted ? "" : "not ") + "from cache");
+
+ if (event.persisted) {
+ testPassed("Page did enter and was restored from the back/forward cache");
+ restoredFromCache = true;
+ }
+}, false);
+
+window.addEventListener("pagehide", function(event) {
+ debug("pagehide - " + (event.persisted ? "" : "not ") + "entering cache");
+ if (!event.persisted) {
+ testFailed("Page did not enter the back/forward cache.");
+ finishJSTest();
+ }
+}, false);
+
+var textData = JSON.stringify("This is the body");
+
+function tryGetRequestBlob()
+{
+ blob = new Blob([textData], { "type" : "text/plain" });
+ request = new Request("", {"method": "POST", "body": blob });
+ request.blob().then(() => {
+ if (restoredFromCache) {
+ testPassed("Promise resolved after restoring from the back/forward cache.");
+ finishJSTest();
+ return;
+ }
+ setTimeout(tryGetRequestBlob, 0);
+ }, (e) => {
+ setTimeout(tryGetRequestBlob, 0);
+ });
+}
+
+window.addEventListener('load', function() {
+ setTimeout(() => {
+ tryGetRequestBlob();
+ window.location.href = ""
+ }, 0);
+}, false);
+
+</script>
+</body>
+</html>
Added: trunk/LayoutTests/fast/history/page-cache-active-fetch-request-blobReadAsReadableStream-expected.txt (0 => 251495)
--- trunk/LayoutTests/fast/history/page-cache-active-fetch-request-blobReadAsReadableStream-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/history/page-cache-active-fetch-request-blobReadAsReadableStream-expected.txt 2019-10-23 20:38:22 UTC (rev 251495)
@@ -0,0 +1,13 @@
+Tests that a page with an active fetch request is able to enter the back/forward 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 back/forward cache
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/history/page-cache-active-fetch-request-blobReadAsReadableStream.html (0 => 251495)
--- trunk/LayoutTests/fast/history/page-cache-active-fetch-request-blobReadAsReadableStream.html (rev 0)
+++ trunk/LayoutTests/fast/history/page-cache-active-fetch-request-blobReadAsReadableStream.html 2019-10-23 20:38:22 UTC (rev 251495)
@@ -0,0 +1,55 @@
+<!-- webkit-test-runner [ enableBackForwardCache=true ] -->
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+description('Tests that a page with an active fetch request is able to enter the back/forward cache.');
+window.jsTestIsAsync = true;
+let restoredFromCache = false;
+
+window.addEventListener("pageshow", function(event) {
+ debug("pageshow - " + (event.persisted ? "" : "not ") + "from cache");
+
+ if (event.persisted) {
+ testPassed("Page did enter and was restored from the back/forward cache");
+ restoredFromCache = true;
+ finishJSTest();
+ }
+}, false);
+
+window.addEventListener("pagehide", function(event) {
+ debug("pagehide - " + (event.persisted ? "" : "not ") + "entering cache");
+ if (!event.persisted) {
+ testFailed("Page did not enter the back/forward cache.");
+ finishJSTest();
+ }
+}, false);
+
+var textData = JSON.stringify("This is the body");
+
+function tryGetRequestBlob()
+{
+ blob = new Blob([textData], { "type" : "text/plain" });
+ request = new Request("", {"method": "POST", "body": blob });
+ readableStream = request.body;
+ readableStream.getReader().read().then(() => {
+ if (restoredFromCache) {
+ return;
+ }
+ setTimeout(tryGetRequestBlob, 0);
+ }, (e) => {
+ setTimeout(tryGetRequestBlob, 0);
+ });
+}
+
+window.addEventListener('load', function() {
+ setTimeout(() => {
+ tryGetRequestBlob();
+ window.location.href = ""
+ }, 0);
+}, false);
+
+</script>
+</body>
+</html>
Added: trunk/LayoutTests/fast/history/page-cache-active-fetch-request-blobReadAsText-expected.txt (0 => 251495)
--- trunk/LayoutTests/fast/history/page-cache-active-fetch-request-blobReadAsText-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/history/page-cache-active-fetch-request-blobReadAsText-expected.txt 2019-10-23 20:38:22 UTC (rev 251495)
@@ -0,0 +1,15 @@
+Tests that a page with an active fetch request is able to enter the back/forward 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 back/forward cache
+PASS Promise resolved after restoring from the back/forward cache.
+PASS text is "\"This is the body\""
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/history/page-cache-active-fetch-request-blobReadAsText.html (0 => 251495)
--- trunk/LayoutTests/fast/history/page-cache-active-fetch-request-blobReadAsText.html (rev 0)
+++ trunk/LayoutTests/fast/history/page-cache-active-fetch-request-blobReadAsText.html 2019-10-23 20:38:22 UTC (rev 251495)
@@ -0,0 +1,57 @@
+<!-- webkit-test-runner [ enableBackForwardCache=true ] -->
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+description('Tests that a page with an active fetch request is able to enter the back/forward cache.');
+window.jsTestIsAsync = true;
+let restoredFromCache = false;
+
+window.addEventListener("pageshow", function(event) {
+ debug("pageshow - " + (event.persisted ? "" : "not ") + "from cache");
+
+ if (event.persisted) {
+ testPassed("Page did enter and was restored from the back/forward cache");
+ restoredFromCache = true;
+ }
+}, false);
+
+window.addEventListener("pagehide", function(event) {
+ debug("pagehide - " + (event.persisted ? "" : "not ") + "entering cache");
+ if (!event.persisted) {
+ testFailed("Page did not enter the back/forward cache.");
+ finishJSTest();
+ }
+}, false);
+
+var textData = JSON.stringify("This is the body");
+
+function tryGetRequestBlob()
+{
+ blob = new Blob([textData], { "type" : "text/plain" });
+ request = new Request("", {"method": "POST", "body": blob });
+ request.text().then((_text) => {
+ if (restoredFromCache) {
+ testPassed("Promise resolved after restoring from the back/forward cache.");
+ text = _text;
+ shouldBeEqualToString("text", "" + textData);
+ finishJSTest();
+ return;
+ }
+ setTimeout(tryGetRequestBlob, 0);
+ }, (e) => {
+ setTimeout(tryGetRequestBlob, 0);
+ });
+}
+
+window.addEventListener('load', function() {
+ setTimeout(() => {
+ tryGetRequestBlob();
+ window.location.href = ""
+ }, 0);
+}, false);
+
+</script>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (251494 => 251495)
--- trunk/Source/WebCore/ChangeLog 2019-10-23 20:16:00 UTC (rev 251494)
+++ trunk/Source/WebCore/ChangeLog 2019-10-23 20:38:22 UTC (rev 251495)
@@ -1,3 +1,32 @@
+2019-10-23 Chris Dumez <cdu...@apple.com>
+
+ FetchRequest should not prevent entering the back/forward cache
+ https://bugs.webkit.org/show_bug.cgi?id=203091
+ <rdar://problem/56525333>
+
+ Reviewed by Youenn Fablet.
+
+ FetchRequest used to prevent the page from entering the back/forward cache while it had a blob
+ load in progress. We no longer prevent suspension in such case. Instead, if the document is
+ suspended when the blob load finishes, we post a task to the Window event loop to do the work
+ and resolve / reject the promise. The Window event loop makes sure not to delays tasks that
+ are associated with a document that is suspended.
+
+ Tests: fast/history/page-cache-active-fetch-request-blobReadAsBlob.html
+ fast/history/page-cache-active-fetch-request-blobReadAsReadableStream.html
+ fast/history/page-cache-active-fetch-request-blobReadAsText.html
+
+ * Modules/fetch/FetchBodyOwner.cpp:
+ (WebCore::FetchBodyOwner::runNetworkTaskWhenPossible):
+ (WebCore::FetchBodyOwner::blobLoadingSucceeded):
+ (WebCore::FetchBodyOwner::blobLoadingFailed):
+ (WebCore::FetchBodyOwner::blobChunk):
+ (WebCore::FetchBodyOwner::postSuspendableNetworkTask): Deleted.
+ * Modules/fetch/FetchBodyOwner.h:
+ * Modules/fetch/FetchRequest.cpp:
+ * Modules/fetch/FetchRequest.h:
+ * dom/AbstractEventLoop.h:
+
2019-10-23 Yury Semikhatsky <yu...@chromium.org>
Web Inspector: notify inspector when provisional page is created, committed and destroyed
Modified: trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp (251494 => 251495)
--- trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp 2019-10-23 20:16:00 UTC (rev 251494)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp 2019-10-23 20:38:22 UTC (rev 251495)
@@ -34,9 +34,27 @@
#include "JSBlob.h"
#include "ResourceError.h"
#include "ResourceResponse.h"
+#include "WindowEventLoop.h"
namespace WebCore {
+void FetchBodyOwner::runNetworkTaskWhenPossible(Function<void()>&& task)
+{
+ auto* context = scriptExecutionContext();
+ if (!context || !scriptExecutionContext()->activeDOMObjectsAreSuspended())
+ return task();
+
+ if (is<Document>(*context)) {
+ downcast<Document>(*context).eventLoop().queueTask(TaskSource::Networking, *context, [pendingActivity = makePendingActivity(*this), task = WTFMove(task)] {
+ task();
+ });
+ } else {
+ context->postTask([pendingActivity = makePendingActivity(*this), task = WTFMove(task)](ScriptExecutionContext&) {
+ task();
+ });
+ }
+}
+
FetchBodyOwner::FetchBodyOwner(ScriptExecutionContext& context, Optional<FetchBody>&& body, Ref<FetchHeaders>&& headers)
: ActiveDOMObject(&context)
, m_body(WTFMove(body))
@@ -268,13 +286,15 @@
void FetchBodyOwner::blobLoadingSucceeded()
{
ASSERT(!isBodyNull());
+ runNetworkTaskWhenPossible([this]() mutable {
#if ENABLE(STREAMS_API)
- if (m_readableStreamSource) {
- m_readableStreamSource->close();
- m_readableStreamSource = nullptr;
- }
+ if (m_readableStreamSource) {
+ m_readableStreamSource->close();
+ m_readableStreamSource = nullptr;
+ }
#endif
- m_body->loadingSucceeded();
+ m_body->loadingSucceeded();
+ });
finishBlobLoading();
}
@@ -281,15 +301,16 @@
void FetchBodyOwner::blobLoadingFailed()
{
ASSERT(!isBodyNull());
+ runNetworkTaskWhenPossible([this]() mutable {
#if ENABLE(STREAMS_API)
- if (m_readableStreamSource) {
- if (!m_readableStreamSource->isCancelling())
- m_readableStreamSource->error(Exception { TypeError, "Blob loading failed"_s});
- m_readableStreamSource = nullptr;
- } else
+ if (m_readableStreamSource) {
+ if (!m_readableStreamSource->isCancelling())
+ m_readableStreamSource->error(Exception { TypeError, "Blob loading failed"_s});
+ m_readableStreamSource = nullptr;
+ } else
#endif
- m_body->loadingFailed(Exception { TypeError, "Blob loading failed"_s});
-
+ m_body->loadingFailed(Exception { TypeError, "Blob loading failed"_s});
+ });
finishBlobLoading();
}
@@ -298,8 +319,10 @@
ASSERT(data);
#if ENABLE(STREAMS_API)
ASSERT(m_readableStreamSource);
- if (!m_readableStreamSource->enqueue(ArrayBuffer::tryCreate(data, size)))
- stop();
+ runNetworkTaskWhenPossible([this, arrayBuffer = ArrayBuffer::tryCreate(data, size)]() mutable {
+ if (!m_readableStreamSource->enqueue(WTFMove(arrayBuffer)))
+ stop();
+ });
#else
UNUSED_PARAM(data);
UNUSED_PARAM(size);
Modified: trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h (251494 => 251495)
--- trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h 2019-10-23 20:16:00 UTC (rev 251494)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h 2019-10-23 20:38:22 UTC (rev 251495)
@@ -125,6 +125,8 @@
Ref<FetchHeaders> m_headers;
private:
+ void runNetworkTaskWhenPossible(Function<void()>&&);
+
Optional<BlobLoader> m_blobLoader;
bool m_isBodyOpaque { false };
Modified: trunk/Source/WebCore/Modules/fetch/FetchRequest.cpp (251494 => 251495)
--- trunk/Source/WebCore/Modules/fetch/FetchRequest.cpp 2019-10-23 20:16:00 UTC (rev 251494)
+++ trunk/Source/WebCore/Modules/fetch/FetchRequest.cpp 2019-10-23 20:38:22 UTC (rev 251495)
@@ -329,11 +329,5 @@
return "Request";
}
-bool FetchRequest::shouldPreventEnteringBackForwardCache_DEPRECATED() const
-{
- // FIXME: This should never prevent entering the back/forward cache.
- return isActive();
-}
-
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/fetch/FetchRequest.h (251494 => 251495)
--- trunk/Source/WebCore/Modules/fetch/FetchRequest.h 2019-10-23 20:16:00 UTC (rev 251494)
+++ trunk/Source/WebCore/Modules/fetch/FetchRequest.h 2019-10-23 20:38:22 UTC (rev 251495)
@@ -92,7 +92,6 @@
ExceptionOr<void> setBody(FetchRequest&);
const char* activeDOMObjectName() const final;
- bool shouldPreventEnteringBackForwardCache_DEPRECATED() const final;
ResourceRequest m_request;
FetchOptions m_options;
Modified: trunk/Source/WebCore/dom/AbstractEventLoop.h (251494 => 251495)
--- trunk/Source/WebCore/dom/AbstractEventLoop.h 2019-10-23 20:16:00 UTC (rev 251494)
+++ trunk/Source/WebCore/dom/AbstractEventLoop.h 2019-10-23 20:38:22 UTC (rev 251495)
@@ -34,6 +34,7 @@
enum class TaskSource : uint8_t {
IdleTask,
+ Networking,
};
// https://html.spec.whatwg.org/multipage/webappapis.html#event-loop