Title: [280824] trunk
Revision
280824
Author
[email protected]
Date
2021-08-09 20:33:03 -0700 (Mon, 09 Aug 2021)

Log Message

Blob URL changes after loading it
https://bugs.webkit.org/show_bug.cgi?id=228923

Reviewed by Geoff Garen.

Source/WebCore:

Blob URL changes after loading it. This is because we use URLWithBlobURLLifetimeExtension to
extend the lifetime of the Blob URL during the load and URLWithBlobURLLifetimeExtension ends
up creating a new public Blob URL. This is Web-observable so we need a way to extend the
lifetime of a Blob URL without actually generating a new Blob URL.

This patch replaces URLWithBlobURLLifetimeExtension with a new BlobURLHandle class which
extends the lifetime of a Blob URL as long as there are BlobURLHandle objects referring
to it. BlobURLHandle works with both private and public Blob URLs so it replaces
Blob::Handle as well (which I recently introduced via r280547). The Blob URL no longer
changes when we extend its lifetime. Instead, the Blob registry now keeps track of
references to a given Blob and only removes a Blob URL once there are no longer any
references to it.

Test: fast/files/blob-as-frame-url.html

* Headers.cmake:
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneSerializer::serialize):
(WebCore::CloneSerializer::CloneSerializer):
(WebCore::CloneSerializer::dumpIfTerminal):
(WebCore::SerializedScriptValue::SerializedScriptValue):
(WebCore::SerializedScriptValue::create):
* bindings/js/SerializedScriptValue.h:
(WebCore::SerializedScriptValue::blobHandles const):
(WebCore::SerializedScriptValue::SerializedScriptValue):
* fileapi/Blob.cpp:
(WebCore::Blob::Blob):
(WebCore::Blob::slice const):
(WebCore::Blob::size const):
(WebCore::Blob::handle const):
* fileapi/Blob.h:
(WebCore::Blob::url const):
* fileapi/BlobURL.cpp:
(WebCore::BlobURLHandle::BlobURLHandle):
(WebCore::BlobURLHandle::~BlobURLHandle):
(WebCore::BlobURLHandle::registerBlobURLHandleIfNecessary):
(WebCore::BlobURLHandle::unregisterBlobURLHandleIfNecessary):
(WebCore::BlobURLHandle::operator=):
(WebCore::BlobURLHandle::clear):
* fileapi/BlobURL.h:
(WebCore::BlobURLHandle::BlobURLHandle):
(WebCore::BlobURLHandle::url const):
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::registerBlobURLHandle):
(WebCore::ThreadableBlobRegistry::unregisterBlobURLHandle):
* fileapi/ThreadableBlobRegistry.h:
* loader/PolicyChecker.cpp:
(WebCore::FrameLoader::PolicyChecker::extendBlobURLLifetimeIfNecessary const):
(WebCore::FrameLoader::PolicyChecker::checkNavigationPolicy):
(WebCore::FrameLoader::PolicyChecker::checkNewWindowPolicy):
* loader/PolicyChecker.h:
* platform/network/BlobRegistry.h:
* platform/network/BlobRegistryImpl.cpp:
(WebCore::BlobRegistryImpl::registerFileBlobURL):
(WebCore::BlobRegistryImpl::registerBlobURL):
(WebCore::BlobRegistryImpl::registerBlobURLOptionallyFileBacked):
(WebCore::BlobRegistryImpl::registerBlobURLForSlice):
(WebCore::BlobRegistryImpl::unregisterBlobURL):
(WebCore::BlobRegistryImpl::addBlobData):
(WebCore::BlobRegistryImpl::registerBlobURLHandle):
(WebCore::BlobRegistryImpl::unregisterBlobURLHandle):
* platform/network/BlobRegistryImpl.h:
* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::setResponseType):
(WebCore::XMLHttpRequest::open):
(WebCore::XMLHttpRequest::prepareToSend):
(WebCore::XMLHttpRequest::send):
(WebCore::XMLHttpRequest::createRequest):
(WebCore::XMLHttpRequest::clearRequest):
(WebCore::XMLHttpRequest::didFinishLoading):
* xml/XMLHttpRequest.h:

Source/WebKit:

* NetworkProcess/NetworkConnectionToWebProcess.cpp:
(WebKit::NetworkConnectionToWebProcess::registerBlobURLHandle):
(WebKit::NetworkConnectionToWebProcess::unregisterBlobURLHandle):
* NetworkProcess/NetworkConnectionToWebProcess.h:
* NetworkProcess/NetworkConnectionToWebProcess.messages.in:
* NetworkProcess/NetworkProcessPlatformStrategies.cpp:
(WebKit::NetworkProcessPlatformStrategies::createBlobRegistry):
* WebProcess/FileAPI/BlobRegistryProxy.cpp:
(WebKit::BlobRegistryProxy::registerBlobURLHandle):
(WebKit::BlobRegistryProxy::unregisterBlobURLHandle):
* WebProcess/FileAPI/BlobRegistryProxy.h:

Source/WebKitLegacy/mac:

* WebCoreSupport/WebPlatformStrategies.mm:

Source/WebKitLegacy/win:

* WebCoreSupport/WebPlatformStrategies.cpp:

LayoutTests:

Add layout test coverage.

* fast/files/blob-as-frame-url-expected.txt: Added.
* fast/files/blob-as-frame-url.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (280823 => 280824)


--- trunk/LayoutTests/ChangeLog	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/LayoutTests/ChangeLog	2021-08-10 03:33:03 UTC (rev 280824)
@@ -1,3 +1,15 @@
+2021-08-09  Chris Dumez  <[email protected]>
+
+        Blob URL changes after loading it
+        https://bugs.webkit.org/show_bug.cgi?id=228923
+
+        Reviewed by Geoff Garen.
+
+        Add layout test coverage.
+
+        * fast/files/blob-as-frame-url-expected.txt: Added.
+        * fast/files/blob-as-frame-url.html: Added.
+
 2021-08-09  Lauro Moura  <[email protected]>
 
         [GLIB] Garden two getUserMedia timeouts

Modified: trunk/LayoutTests/fast/dom/HTMLAnchorElement/anchor-file-blob-download-then-revoke-expected.txt (280823 => 280824)


--- trunk/LayoutTests/fast/dom/HTMLAnchorElement/anchor-file-blob-download-then-revoke-expected.txt	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/LayoutTests/fast/dom/HTMLAnchorElement/anchor-file-blob-download-then-revoke-expected.txt	2021-08-10 03:33:03 UTC (rev 280824)
@@ -1,4 +1,3 @@
-CONSOLE MESSAGE: PASS: URL was revoked
 Download started.
 Downloading URL with suggested filename "foo.txt"
 Download completed.

Modified: trunk/LayoutTests/fast/dom/HTMLAnchorElement/anchor-file-blob-download-then-revoke.html (280823 => 280824)


--- trunk/LayoutTests/fast/dom/HTMLAnchorElement/anchor-file-blob-download-then-revoke.html	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/LayoutTests/fast/dom/HTMLAnchorElement/anchor-file-blob-download-then-revoke.html	2021-08-10 03:33:03 UTC (rev 280824)
@@ -23,18 +23,6 @@
     link.click();
     // Revoke the URL right away.
     window.URL.revokeObjectURL(link.href);
-
-    // Make sure the URL was revoked.
-    xhr = new XMLHttpRequest();
-    xhr.open("GET", link.href, false);
-    try {
-        xhr.send(null);
-    } catch (e) {
-    }
-    if (xhr.status == 200)
-        console.log("FAIL: URL was not revoked");
-    else
-        console.log("PASS: URL was revoked");
 }
 runTest();
 </script>

Added: trunk/LayoutTests/fast/files/blob-as-frame-url-expected.txt (0 => 280824)


--- trunk/LayoutTests/fast/files/blob-as-frame-url-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/files/blob-as-frame-url-expected.txt	2021-08-10 03:33:03 UTC (rev 280824)
@@ -0,0 +1,12 @@
+Makes sure that using a Blob URL as frame URL works as expected.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS iframe.contentDocument.body.innerText is "FOO"
+PASS iframe.contentWindow.location.href == blobURL is true
+PASS iframe.contentDocument.URL == blobURL is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/files/blob-as-frame-url.html (0 => 280824)


--- trunk/LayoutTests/fast/files/blob-as-frame-url.html	                        (rev 0)
+++ trunk/LayoutTests/fast/files/blob-as-frame-url.html	2021-08-10 03:33:03 UTC (rev 280824)
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script>
+description("Makes sure that using a Blob URL as frame URL works as expected.");
+jsTestIsAsync = true;
+
+let blobContents = `<body>FOO</body>`;
+let iframe = document.createElement("iframe");
+let blob = new Blob([blobContents], { type: "text/html" });
+let blobURL = URL.createObjectURL(blob);
+iframe.src = ""
+iframe._onload_ = () => {
+    shouldBeEqualToString("iframe.contentDocument.body.innerText", "FOO");
+    shouldBeTrue("iframe.contentWindow.location.href == blobURL");
+    shouldBeTrue("iframe.contentDocument.URL == blobURL");
+    finishJSTest();
+};
+document.body.append(iframe);
+blob = null;
+gc();
+setTimeout(gc, 0);
+</script>
+</body>
+</html>

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/FileAPI/url/url-in-tags.window-expected.txt (280823 => 280824)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/FileAPI/url/url-in-tags.window-expected.txt	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/FileAPI/url/url-in-tags.window-expected.txt	2021-08-10 03:33:03 UTC (rev 280824)
@@ -1,7 +1,5 @@
 
-Harness Error (TIMEOUT), message = null
-
 PASS Blob URLs can be used in <script> tags
 PASS Blob URLs can be used in iframes, and are treated same origin
-TIMEOUT Blob URL fragment is implemented. Test timed out
+PASS Blob URL fragment is implemented.
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/FileAPI/url/url-reload.window-expected.txt (280823 => 280824)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/FileAPI/url/url-reload.window-expected.txt	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/FileAPI/url/url-reload.window-expected.txt	2021-08-10 03:33:03 UTC (rev 280824)
@@ -1,6 +1,6 @@
 
 Harness Error (TIMEOUT), message = null
 
-TIMEOUT Reloading a blob URL succeeds. Test timed out
+PASS Reloading a blob URL succeeds.
 TIMEOUT Reloading a blob URL succeeds even if the URL was revoked. Test timed out
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/content-security-policy/inheritance/history.sub-expected.txt (280823 => 280824)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/content-security-policy/inheritance/history.sub-expected.txt	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/content-security-policy/inheritance/history.sub-expected.txt	2021-08-10 03:33:03 UTC (rev 280824)
@@ -1,8 +1,8 @@
 
 PASS History navigation: "about:blank" document is navigated back from history same-origin.
 PASS History navigation: "about:blank" document is navigated back from history cross-origin.
-FAIL History navigation: blob URL document is navigated back from history same-origin. step_wait_func: Wait for the popup to navigate. Timed out waiting on condition
-FAIL History navigation: blob URL document is navigated back from history cross-origin. step_wait_func: Wait for the popup to navigate. Timed out waiting on condition
-FAIL History navigation: blob URL document is navigated back from history (without bfcache on Firefox) same-origin. step_wait_func: Wait for the popup to navigate. Timed out waiting on condition
-FAIL History navigation: blob URL document is navigated back from history (without bfcache on Firefox) cross-origin. step_wait_func: Wait for the popup to navigate. Timed out waiting on condition
+FAIL History navigation: blob URL document is navigated back from history same-origin. assert_equals: Image should be blocked by CSP inherited from navigation initiator. expected "img blocked" but got "img loaded"
+FAIL History navigation: blob URL document is navigated back from history cross-origin. assert_equals: Image should be blocked by CSP inherited from navigation initiator. expected "img blocked" but got "img loaded"
+FAIL History navigation: blob URL document is navigated back from history (without bfcache on Firefox) same-origin. assert_equals: Image should be blocked by CSP inherited from navigation initiator. expected "img blocked" but got "img loaded"
+FAIL History navigation: blob URL document is navigated back from history (without bfcache on Firefox) cross-origin. assert_equals: Image should be blocked by CSP inherited from navigation initiator. expected "img blocked" but got "img loaded"
 

Modified: trunk/Source/WebCore/ChangeLog (280823 => 280824)


--- trunk/Source/WebCore/ChangeLog	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebCore/ChangeLog	2021-08-10 03:33:03 UTC (rev 280824)
@@ -1,3 +1,83 @@
+2021-08-09  Chris Dumez  <[email protected]>
+
+        Blob URL changes after loading it
+        https://bugs.webkit.org/show_bug.cgi?id=228923
+
+        Reviewed by Geoff Garen.
+
+        Blob URL changes after loading it. This is because we use URLWithBlobURLLifetimeExtension to
+        extend the lifetime of the Blob URL during the load and URLWithBlobURLLifetimeExtension ends
+        up creating a new public Blob URL. This is Web-observable so we need a way to extend the
+        lifetime of a Blob URL without actually generating a new Blob URL.
+
+        This patch replaces URLWithBlobURLLifetimeExtension with a new BlobURLHandle class which
+        extends the lifetime of a Blob URL as long as there are BlobURLHandle objects referring
+        to it. BlobURLHandle works with both private and public Blob URLs so it replaces
+        Blob::Handle as well (which I recently introduced via r280547). The Blob URL no longer
+        changes when we extend its lifetime. Instead, the Blob registry now keeps track of
+        references to a given Blob and only removes a Blob URL once there are no longer any
+        references to it.
+
+        Test: fast/files/blob-as-frame-url.html
+
+        * Headers.cmake:
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/SerializedScriptValue.cpp:
+        (WebCore::CloneSerializer::serialize):
+        (WebCore::CloneSerializer::CloneSerializer):
+        (WebCore::CloneSerializer::dumpIfTerminal):
+        (WebCore::SerializedScriptValue::SerializedScriptValue):
+        (WebCore::SerializedScriptValue::create):
+        * bindings/js/SerializedScriptValue.h:
+        (WebCore::SerializedScriptValue::blobHandles const):
+        (WebCore::SerializedScriptValue::SerializedScriptValue):
+        * fileapi/Blob.cpp:
+        (WebCore::Blob::Blob):
+        (WebCore::Blob::slice const):
+        (WebCore::Blob::size const):
+        (WebCore::Blob::handle const):
+        * fileapi/Blob.h:
+        (WebCore::Blob::url const):
+        * fileapi/BlobURL.cpp:
+        (WebCore::BlobURLHandle::BlobURLHandle):
+        (WebCore::BlobURLHandle::~BlobURLHandle):
+        (WebCore::BlobURLHandle::registerBlobURLHandleIfNecessary):
+        (WebCore::BlobURLHandle::unregisterBlobURLHandleIfNecessary):
+        (WebCore::BlobURLHandle::operator=):
+        (WebCore::BlobURLHandle::clear):
+        * fileapi/BlobURL.h:
+        (WebCore::BlobURLHandle::BlobURLHandle):
+        (WebCore::BlobURLHandle::url const):
+        * fileapi/ThreadableBlobRegistry.cpp:
+        (WebCore::ThreadableBlobRegistry::registerBlobURLHandle):
+        (WebCore::ThreadableBlobRegistry::unregisterBlobURLHandle):
+        * fileapi/ThreadableBlobRegistry.h:
+        * loader/PolicyChecker.cpp:
+        (WebCore::FrameLoader::PolicyChecker::extendBlobURLLifetimeIfNecessary const):
+        (WebCore::FrameLoader::PolicyChecker::checkNavigationPolicy):
+        (WebCore::FrameLoader::PolicyChecker::checkNewWindowPolicy):
+        * loader/PolicyChecker.h:
+        * platform/network/BlobRegistry.h:
+        * platform/network/BlobRegistryImpl.cpp:
+        (WebCore::BlobRegistryImpl::registerFileBlobURL):
+        (WebCore::BlobRegistryImpl::registerBlobURL):
+        (WebCore::BlobRegistryImpl::registerBlobURLOptionallyFileBacked):
+        (WebCore::BlobRegistryImpl::registerBlobURLForSlice):
+        (WebCore::BlobRegistryImpl::unregisterBlobURL):
+        (WebCore::BlobRegistryImpl::addBlobData):
+        (WebCore::BlobRegistryImpl::registerBlobURLHandle):
+        (WebCore::BlobRegistryImpl::unregisterBlobURLHandle):
+        * platform/network/BlobRegistryImpl.h:
+        * xml/XMLHttpRequest.cpp:
+        (WebCore::XMLHttpRequest::setResponseType):
+        (WebCore::XMLHttpRequest::open):
+        (WebCore::XMLHttpRequest::prepareToSend):
+        (WebCore::XMLHttpRequest::send):
+        (WebCore::XMLHttpRequest::createRequest):
+        (WebCore::XMLHttpRequest::clearRequest):
+        (WebCore::XMLHttpRequest::didFinishLoading):
+        * xml/XMLHttpRequest.h:
+
 2021-08-09  Simon Fraser  <[email protected]>
 
         Vertical scroll with mouse wheel in horizontal scroller fails to propagate to the document

Modified: trunk/Source/WebCore/Headers.cmake (280823 => 280824)


--- trunk/Source/WebCore/Headers.cmake	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebCore/Headers.cmake	2021-08-10 03:33:03 UTC (rev 280824)
@@ -598,6 +598,7 @@
     fileapi/AsyncFileStream.h
     fileapi/Blob.h
     fileapi/BlobPropertyBag.h
+    fileapi/BlobURL.h
     fileapi/EndingType.h
     fileapi/File.h
     fileapi/FileList.h

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (280823 => 280824)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-08-10 03:33:03 UTC (rev 280824)
@@ -3037,7 +3037,7 @@
 		97627B9814FB5424002CDCA1 /* Supplementable.h in Headers */ = {isa = PBXBuildFile; fileRef = 97627B9714FB5424002CDCA1 /* Supplementable.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		976D6C79122B8A3D001FD1F7 /* Blob.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C5A122B8A3D001FD1F7 /* Blob.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		976D6C7C122B8A3D001FD1F7 /* BlobBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C5D122B8A3D001FD1F7 /* BlobBuilder.h */; };
-		976D6C7F122B8A3D001FD1F7 /* BlobURL.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C60122B8A3D001FD1F7 /* BlobURL.h */; };
+		976D6C7F122B8A3D001FD1F7 /* BlobURL.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C60122B8A3D001FD1F7 /* BlobURL.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		976D6C81122B8A3D001FD1F7 /* File.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C62122B8A3D001FD1F7 /* File.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		976D6C86122B8A3D001FD1F7 /* FileList.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C67122B8A3D001FD1F7 /* FileList.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		976D6C89122B8A3D001FD1F7 /* FileReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C6A122B8A3D001FD1F7 /* FileReader.h */; };

Modified: trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp (280823 => 280824)


--- trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp	2021-08-10 03:33:03 UTC (rev 280824)
@@ -600,7 +600,7 @@
             WasmModuleArray& wasmModules,
             WasmMemoryHandleArray& wasmMemoryHandles,
 #endif
-        Vector<Blob::Handle>& blobHandles, Vector<uint8_t>& out, SerializationContext context, ArrayBufferContentsArray& sharedBuffers)
+        Vector<BlobURLHandle>& blobHandles, Vector<uint8_t>& out, SerializationContext context, ArrayBufferContentsArray& sharedBuffers)
     {
         CloneSerializer serializer(lexicalGlobalObject, messagePorts, arrayBuffers, imageBitmaps,
 #if ENABLE(OFFSCREEN_CANVAS_IN_WORKERS)
@@ -647,7 +647,7 @@
             WasmModuleArray& wasmModules,
             WasmMemoryHandleArray& wasmMemoryHandles,
 #endif
-        Vector<Blob::Handle>& blobHandles, Vector<uint8_t>& out, SerializationContext context, ArrayBufferContentsArray& sharedBuffers)
+        Vector<BlobURLHandle>& blobHandles, Vector<uint8_t>& out, SerializationContext context, ArrayBufferContentsArray& sharedBuffers)
         : CloneBase(lexicalGlobalObject)
         , m_buffer(out)
         , m_blobHandles(blobHandles)
@@ -1297,7 +1297,7 @@
             if (auto* key = JSCryptoKey::toWrapped(vm, obj)) {
                 write(CryptoKeyTag);
                 Vector<uint8_t> serializedKey;
-                Vector<Blob::Handle> dummyBlobHandles;
+                Vector<BlobURLHandle> dummyBlobHandles;
                 Vector<RefPtr<MessagePort>> dummyMessagePorts;
                 Vector<RefPtr<JSC::ArrayBuffer>> dummyArrayBuffers;
 #if ENABLE(WEBASSEMBLY)
@@ -1760,7 +1760,7 @@
     }
 
     Vector<uint8_t>& m_buffer;
-    Vector<Blob::Handle>& m_blobHandles;
+    Vector<BlobURLHandle>& m_blobHandles;
     ObjectPool m_objectPool;
     ObjectPool m_transferredMessagePorts;
     ObjectPool m_transferredArrayBuffers;
@@ -3915,7 +3915,7 @@
     m_memoryCost = computeMemoryCost();
 }
 
-SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>&& buffer, const Vector<Blob::Handle>& blobHandles, std::unique_ptr<ArrayBufferContentsArray> arrayBufferContentsArray, std::unique_ptr<ArrayBufferContentsArray> sharedBufferContentsArray, Vector<std::optional<ImageBitmapBacking>>&& backingStores
+SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>&& buffer, const Vector<BlobURLHandle>& blobHandles, std::unique_ptr<ArrayBufferContentsArray> arrayBufferContentsArray, std::unique_ptr<ArrayBufferContentsArray> sharedBufferContentsArray, Vector<std::optional<ImageBitmapBacking>>&& backingStores
 #if ENABLE(OFFSCREEN_CANVAS_IN_WORKERS)
         , Vector<std::unique_ptr<DetachedOffscreenCanvas>>&& detachedOffscreenCanvases
 #endif
@@ -4065,7 +4065,7 @@
 RefPtr<SerializedScriptValue> SerializedScriptValue::create(JSGlobalObject& lexicalGlobalObject, JSValue value, SerializationErrorMode throwExceptions)
 {
     Vector<uint8_t> buffer;
-    Vector<Blob::Handle> blobHandles;
+    Vector<BlobURLHandle> blobHandles;
     Vector<RefPtr<MessagePort>> dummyMessagePorts;
     Vector<RefPtr<ImageBitmap>> dummyImageBitmaps;
 #if ENABLE(OFFSCREEN_CANVAS_IN_WORKERS)
@@ -4217,7 +4217,7 @@
 #endif
 
     Vector<uint8_t> buffer;
-    Vector<Blob::Handle> blobHandles;
+    Vector<BlobURLHandle> blobHandles;
 #if ENABLE(WEBASSEMBLY)
     WasmModuleArray wasmModules;
     WasmMemoryHandleArray wasmMemoryHandles;

Modified: trunk/Source/WebCore/bindings/js/SerializedScriptValue.h (280823 => 280824)


--- trunk/Source/WebCore/bindings/js/SerializedScriptValue.h	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebCore/bindings/js/SerializedScriptValue.h	2021-08-10 03:33:03 UTC (rev 280824)
@@ -99,7 +99,7 @@
     bool hasBlobURLs() const { return !m_blobHandles.isEmpty(); }
 
     Vector<String> blobURLs() const;
-    const Vector<Blob::Handle>& blobHandles() const { return m_blobHandles; }
+    const Vector<BlobURLHandle>& blobHandles() const { return m_blobHandles; }
     void writeBlobsToDiskForIndexedDB(CompletionHandler<void(IDBValue&&)>&&);
     IDBValue writeBlobsToDiskForIndexedDBSynchronously();
     static Ref<SerializedScriptValue> createFromWireBytes(Vector<uint8_t>&& data)
@@ -123,7 +123,7 @@
 #endif
         );
 
-    SerializedScriptValue(Vector<unsigned char>&&, const Vector<Blob::Handle>& blobHandles, std::unique_ptr<ArrayBufferContentsArray>, std::unique_ptr<ArrayBufferContentsArray> sharedBuffers, Vector<std::optional<ImageBitmapBacking>>&& backingStores
+    SerializedScriptValue(Vector<unsigned char>&&, const Vector<BlobURLHandle>& blobHandles, std::unique_ptr<ArrayBufferContentsArray>, std::unique_ptr<ArrayBufferContentsArray> sharedBuffers, Vector<std::optional<ImageBitmapBacking>>&& backingStores
 #if ENABLE(OFFSCREEN_CANVAS_IN_WORKERS)
         , Vector<std::unique_ptr<DetachedOffscreenCanvas>>&& = { }
 #endif
@@ -152,7 +152,7 @@
     std::unique_ptr<WasmModuleArray> m_wasmModulesArray;
     std::unique_ptr<WasmMemoryHandleArray> m_wasmMemoryHandlesArray;
 #endif
-    Vector<Blob::Handle> m_blobHandles;
+    Vector<BlobURLHandle> m_blobHandles;
     size_t m_memoryCost { 0 };
 };
 

Modified: trunk/Source/WebCore/fileapi/Blob.cpp (280823 => 280824)


--- trunk/Source/WebCore/fileapi/Blob.cpp	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebCore/fileapi/Blob.cpp	2021-08-10 03:33:03 UTC (rev 280824)
@@ -76,67 +76,10 @@
     return instance;
 }
 
-// Unregisters the Blob's internal URL upon destruction. This can be used to extend the lifetime of the Blob data
-// without actually keeping the Blob object alive.
-class BlobInternalURL : public ThreadSafeRefCounted<BlobInternalURL> {
-public:
-    static Ref<BlobInternalURL> create(Vector<BlobPart>&& blobParts, const String& contentType)
-    {
-        return adoptRef(*new BlobInternalURL(WTFMove(blobParts), contentType));
-    }
-
-    static Ref<BlobInternalURL> createForDeserialization(const URL& sourceURL, const String& fileBackedPath, const String& type)
-    {
-        return adoptRef(*new BlobInternalURL(sourceURL, fileBackedPath, type));
-    }
-
-    static Ref<BlobInternalURL> createForSlice(const URL& sourceURL, long long start, long long end, const String& type)
-    {
-        return adoptRef(*new BlobInternalURL(sourceURL, start, end, type));
-    }
-
-    static Ref<BlobInternalURL> adoptInternalURL(const URL& url)
-    {
-        return adoptRef(*new BlobInternalURL(crossThreadCopy(url)));
-    }
-
-    ~BlobInternalURL()
-    {
-        ThreadableBlobRegistry::unregisterBlobURL(m_internalURL);
-    }
-
-    URL url() const { return m_internalURL.isolatedCopy(); }
-
-private:
-    BlobInternalURL(Vector<BlobPart>&& blobParts, const String& contentType)
-        : m_internalURL(BlobURL::createInternalURL())
-    {
-        ThreadableBlobRegistry::registerBlobURL(m_internalURL, WTFMove(blobParts), contentType);
-    }
-    BlobInternalURL(const URL& sourceURL, long long start, long long end, const String& type)
-        : m_internalURL(BlobURL::createInternalURL())
-    {
-        ThreadableBlobRegistry::registerBlobURLForSlice(m_internalURL, sourceURL, start, end, type);
-    }
-    BlobInternalURL(const URL& sourceURL, const String& fileBackedPath, const String& type)
-        : m_internalURL(BlobURL::createInternalURL())
-    {
-        if (fileBackedPath.isEmpty())
-            ThreadableBlobRegistry::registerBlobURL(nullptr, m_internalURL, sourceURL);
-        else
-            ThreadableBlobRegistry::registerBlobURLOptionallyFileBacked(m_internalURL, sourceURL, fileBackedPath, type);
-    }
-    BlobInternalURL(URL&& internalURL)
-        : m_internalURL(WTFMove(internalURL))
-    { }
-
-    URL m_internalURL;
-};
-
 Blob::Blob(UninitializedContructor, ScriptExecutionContext* context, URL&& url, String&& type)
     : ActiveDOMObject(context)
     , m_type(WTFMove(type))
-    , m_internalURL(BlobInternalURL::adoptInternalURL(url))
+    , m_internalURL(WTFMove(url))
 {
 }
 
@@ -143,8 +86,9 @@
 Blob::Blob(ScriptExecutionContext* context)
     : ActiveDOMObject(context)
     , m_size(0)
-    , m_internalURL(BlobInternalURL::create({ }, { }))
+    , m_internalURL(BlobURL::createInternalURL())
 {
+    ThreadableBlobRegistry::registerBlobURL(m_internalURL, { }, { });
 }
 
 static Vector<BlobPart> buildBlobData(Vector<BlobPartVariant>&& blobPartVariants, const BlobPropertyBag& propertyBag)
@@ -163,8 +107,9 @@
 Blob::Blob(ScriptExecutionContext& context, Vector<BlobPartVariant>&& blobPartVariants, const BlobPropertyBag& propertyBag)
     : ActiveDOMObject(&context)
     , m_type(normalizedContentType(propertyBag.type))
-    , m_internalURL(BlobInternalURL::create(buildBlobData(WTFMove(blobPartVariants), propertyBag), m_type))
+    , m_internalURL(BlobURL::createInternalURL())
 {
+    ThreadableBlobRegistry::registerBlobURL(m_internalURL, buildBlobData(WTFMove(blobPartVariants), propertyBag), m_type);
 }
 
 Blob::Blob(ScriptExecutionContext* context, Vector<uint8_t>&& data, const String& contentType)
@@ -171,8 +116,9 @@
     : ActiveDOMObject(context)
     , m_type(contentType)
     , m_size(data.size())
-    , m_internalURL(BlobInternalURL::create({ BlobPart(WTFMove(data)) }, contentType))
+    , m_internalURL(BlobURL::createInternalURL())
 {
+    ThreadableBlobRegistry::registerBlobURL(m_internalURL, { BlobPart(WTFMove(data)) }, contentType);
 }
 
 Blob::Blob(ReferencingExistingBlobConstructor, ScriptExecutionContext* context, const Blob& blob)
@@ -179,8 +125,9 @@
     : ActiveDOMObject(context)
     , m_type(blob.type())
     , m_size(blob.size())
-    , m_internalURL(BlobInternalURL::create({ BlobPart(blob.url()) } , m_type))
+    , m_internalURL(BlobURL::createInternalURL())
 {
+    ThreadableBlobRegistry::registerBlobURL(m_internalURL, { BlobPart(blob.url()) } , m_type);
 }
 
 Blob::Blob(DeserializationContructor, ScriptExecutionContext* context, const URL& srcURL, const String& type, std::optional<unsigned long long> size, const String& fileBackedPath)
@@ -187,16 +134,21 @@
     : ActiveDOMObject(context)
     , m_type(normalizedContentType(type))
     , m_size(size)
-    , m_internalURL(BlobInternalURL::createForDeserialization(srcURL, fileBackedPath, m_type))
+    , m_internalURL(BlobURL::createInternalURL())
 {
+    if (fileBackedPath.isEmpty())
+        ThreadableBlobRegistry::registerBlobURL(nullptr, m_internalURL, srcURL);
+    else
+        ThreadableBlobRegistry::registerBlobURLOptionallyFileBacked(m_internalURL, srcURL, fileBackedPath, m_type);
 }
 
 Blob::Blob(ScriptExecutionContext* context, const URL& srcURL, long long start, long long end, const String& type)
     : ActiveDOMObject(context)
     , m_type(normalizedContentType(type))
-    , m_internalURL(BlobInternalURL::createForSlice(srcURL, start, end, m_type))
+    , m_internalURL(BlobURL::createInternalURL())
     // m_size is not necessarily equal to end - start so we do not initialize it here.
 {
+    ThreadableBlobRegistry::registerBlobURLForSlice(m_internalURL, srcURL, start, end, m_type);
 }
 
 Blob::~Blob()
@@ -205,14 +157,9 @@
         (*m_blobLoaders.begin())->cancel();
 }
 
-URL Blob::url() const
-{
-    return m_internalURL->url();
-}
-
 Ref<Blob> Blob::slice(ScriptExecutionContext& context, long long start, long long end, const String& contentType) const
 {
-    auto blob = adoptRef(*new Blob(&context, m_internalURL->url(), start, end, contentType));
+    auto blob = adoptRef(*new Blob(&context, m_internalURL, start, end, contentType));
     blob->suspendIfNeeded();
     return blob;
 }
@@ -222,7 +169,7 @@
     if (!m_size) {
         // FIXME: _javascript_ cannot represent sizes as large as unsigned long long, we need to
         // come up with an exception to throw if file size is not representable.
-        unsigned long long actualSize = ThreadableBlobRegistry::blobSize(m_internalURL->url());
+        unsigned long long actualSize = ThreadableBlobRegistry::blobSize(m_internalURL);
         m_size = isInBounds<long long>(actualSize) ? actualSize : 0;
     }
 
@@ -395,23 +342,9 @@
     return "Blob";
 }
 
-Blob::Handle Blob::handle() const
+BlobURLHandle Blob::handle() const
 {
-    return Handle { m_internalURL.copyRef() };
+    return BlobURLHandle { m_internalURL };
 }
 
-Blob::Handle::Handle(Ref<BlobInternalURL>&& internalURL)
-    : m_internalURL(WTFMove(internalURL))
-{ }
-
-Blob::Handle::~Handle() = default;
-
-Blob::Handle::Handle(Handle&&) = default;
-Blob::Handle::Handle(const Handle&) = default;
-
-URL Blob::Handle::url() const
-{
-    return m_internalURL->url();
-}
-
 } // namespace WebCore

Modified: trunk/Source/WebCore/fileapi/Blob.h (280823 => 280824)


--- trunk/Source/WebCore/fileapi/Blob.h	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebCore/fileapi/Blob.h	2021-08-10 03:33:03 UTC (rev 280824)
@@ -32,6 +32,7 @@
 #pragma once
 
 #include "BlobPropertyBag.h"
+#include "BlobURL.h"
 #include "FileReaderLoader.h"
 #include "ScriptExecutionContext.h"
 #include "ScriptWrappable.h"
@@ -57,7 +58,6 @@
 template<typename> class ExceptionOr;
 
 using BlobPartVariant = Variant<RefPtr<JSC::ArrayBufferView>, RefPtr<JSC::ArrayBuffer>, RefPtr<Blob>, String>;
-class BlobInternalURL;
 
 class Blob : public ScriptWrappable, public URLRegistrable, public RefCounted<Blob>, public ActiveDOMObject {
     WTF_MAKE_ISO_ALLOCATED_EXPORT(Blob, WEBCORE_EXPORT);
@@ -93,7 +93,7 @@
 
     virtual ~Blob();
 
-    WEBCORE_EXPORT URL url() const;
+    URL url() const { return m_internalURL; }
     const String& type() const { return m_type; }
 
     WEBCORE_EXPORT unsigned long long size() const;
@@ -117,19 +117,8 @@
     void arrayBuffer(ScriptExecutionContext&, Ref<DeferredPromise>&&);
     ExceptionOr<Ref<ReadableStream>> stream(ScriptExecutionContext&);
 
-    class Handle {
-    public:
-        explicit Handle(Ref<BlobInternalURL>&&);
-        ~Handle();
-        Handle(Handle&&);
-        Handle(const Handle&);
-        URL url() const;
-    private:
-        Ref<BlobInternalURL> m_internalURL;
-    };
-
     // Keeping the handle alive will keep the Blob data alive (but not the Blob object).
-    Handle handle() const;
+    BlobURLHandle handle() const;
 
 protected:
     WEBCORE_EXPORT explicit Blob(ScriptExecutionContext*);
@@ -160,7 +149,7 @@
     // This is an internal URL referring to the blob data associated with this object. It serves
     // as an identifier for this blob. The internal URL is never used to source the blob's content
     // into an HTML or for FileRead'ing, public blob URLs must be used for those purposes.
-    Ref<BlobInternalURL> m_internalURL;
+    URL m_internalURL;
 
     HashSet<std::unique_ptr<BlobLoader>> m_blobLoaders;
 };

Modified: trunk/Source/WebCore/fileapi/BlobURL.cpp (280823 => 280824)


--- trunk/Source/WebCore/fileapi/BlobURL.cpp	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebCore/fileapi/BlobURL.cpp	2021-08-10 03:33:03 UTC (rev 280824)
@@ -96,45 +96,67 @@
     return URL({ }, urlString);
 }
 
-URLWithBlobURLLifetimeExtension::URLWithBlobURLLifetimeExtension(const URL& url)
-    : m_url(url)
+BlobURLHandle::BlobURLHandle(const BlobURLHandle& other)
+    : m_url(other.m_url.isolatedCopy())
 {
-    extendBlobURLLifetimeIfNecessary();
+    registerBlobURLHandleIfNecessary();
 }
 
-URLWithBlobURLLifetimeExtension::~URLWithBlobURLLifetimeExtension()
+BlobURLHandle::BlobURLHandle(const URL& url)
+    : m_url(url.isolatedCopy())
 {
-    unregisterCurrentURLIfNecessary();
+    ASSERT(m_url.protocolIsBlob());
+    registerBlobURLHandleIfNecessary();
 }
 
-void URLWithBlobURLLifetimeExtension::extendBlobURLLifetimeIfNecessary()
+BlobURLHandle::~BlobURLHandle()
 {
-    if (m_url.protocolIsBlob()) {
-        auto origin = SecurityOrigin::create(BlobURL::getOriginURL(m_url));
-        URL temporaryBlobURL = BlobURL::createPublicURL(origin.ptr());
-        ThreadableBlobRegistry::registerBlobURL(origin.ptr(), temporaryBlobURL, m_url);
-        m_url = WTFMove(temporaryBlobURL);
-    }
+    unregisterBlobURLHandleIfNecessary();
 }
 
-void URLWithBlobURLLifetimeExtension::unregisterCurrentURLIfNecessary()
+void BlobURLHandle::registerBlobURLHandleIfNecessary()
 {
     if (m_url.protocolIsBlob())
-        ThreadableBlobRegistry::unregisterBlobURL(m_url);
+        ThreadableBlobRegistry::registerBlobURLHandle(m_url);
 }
 
-URLWithBlobURLLifetimeExtension& URLWithBlobURLLifetimeExtension::operator=(URLWithBlobURLLifetimeExtension&& other)
+void BlobURLHandle::unregisterBlobURLHandleIfNecessary()
 {
-    unregisterCurrentURLIfNecessary();
+    if (m_url.protocolIsBlob())
+        ThreadableBlobRegistry::unregisterBlobURLHandle(m_url);
+}
+
+BlobURLHandle& BlobURLHandle::operator=(const BlobURLHandle& other)
+{
+    if (this == &other)
+        return *this;
+
+    unregisterBlobURLHandleIfNecessary();
+    m_url = other.m_url.isolatedCopy();
+    registerBlobURLHandleIfNecessary();
+
+    return *this;
+}
+
+void BlobURLHandle::clear()
+{
+    unregisterBlobURLHandleIfNecessary();
+    m_url = { };
+}
+
+BlobURLHandle& BlobURLHandle::operator=(BlobURLHandle&& other)
+{
+    unregisterBlobURLHandleIfNecessary();
     m_url = std::exchange(other.m_url, { });
     return *this;
 }
 
-URLWithBlobURLLifetimeExtension& URLWithBlobURLLifetimeExtension::operator=(URL&& url)
+BlobURLHandle& BlobURLHandle::operator=(const URL& url)
 {
-    unregisterCurrentURLIfNecessary();
-    m_url = WTFMove(url);
-    extendBlobURLLifetimeIfNecessary();
+    ASSERT(url.protocolIsBlob());
+    unregisterBlobURLHandleIfNecessary();
+    m_url = url.isolatedCopy();
+    registerBlobURLHandleIfNecessary();
     return *this;
 }
 

Modified: trunk/Source/WebCore/fileapi/BlobURL.h (280823 => 280824)


--- trunk/Source/WebCore/fileapi/BlobURL.h	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebCore/fileapi/BlobURL.h	2021-08-10 03:33:03 UTC (rev 280824)
@@ -58,27 +58,31 @@
     BlobURL() { }
 };
 
-class URLWithBlobURLLifetimeExtension {
+// Extends the lifetime of the Blob URL. This means that the blob URL will remain valid after
+// revokeObjectURL() has been called, as long as BlobURLHandle objects refer to the blob URL.
+class BlobURLHandle {
     WTF_MAKE_FAST_ALLOCATED;
-    WTF_MAKE_NONCOPYABLE(URLWithBlobURLLifetimeExtension);
 public:
-    URLWithBlobURLLifetimeExtension() = default;
-    explicit URLWithBlobURLLifetimeExtension(const URL&);
-    ~URLWithBlobURLLifetimeExtension();
+    BlobURLHandle() = default;
+    explicit BlobURLHandle(const URL&);
+    ~BlobURLHandle();
 
-    URLWithBlobURLLifetimeExtension(URLWithBlobURLLifetimeExtension&& other)
+    BlobURLHandle(const BlobURLHandle&);
+    BlobURLHandle(BlobURLHandle&& other)
         : m_url(std::exchange(other.m_url, { }))
     { }
 
-    URLWithBlobURLLifetimeExtension& operator=(URLWithBlobURLLifetimeExtension&&);
-    URLWithBlobURLLifetimeExtension& operator=(URL&&);
+    BlobURLHandle& operator=(const BlobURLHandle&);
+    BlobURLHandle& operator=(BlobURLHandle&&);
+    BlobURLHandle& operator=(const URL&);
 
-    operator const URL&() const { return m_url; }
-    const URL& url() const { return m_url; }
+    URL url() const { return m_url.isolatedCopy(); }
 
+    void clear();
+
 private:
-    void unregisterCurrentURLIfNecessary();
-    void extendBlobURLLifetimeIfNecessary();
+    void unregisterBlobURLHandleIfNecessary();
+    void registerBlobURLHandleIfNecessary();
 
     URL m_url;
 };

Modified: trunk/Source/WebCore/fileapi/ThreadableBlobRegistry.cpp (280823 => 280824)


--- trunk/Source/WebCore/fileapi/ThreadableBlobRegistry.cpp	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebCore/fileapi/ThreadableBlobRegistry.cpp	2021-08-10 03:33:03 UTC (rev 280824)
@@ -155,15 +155,25 @@
     if (isBlobURLContainsNullOrigin(url))
         originMap()->remove(url.string());
 
-    if (isMainThread()) {
+    ensureOnMainThread([url = "" {
         blobRegistry().unregisterBlobURL(url);
-        return;
-    }
-    callOnMainThread([url = "" {
-        blobRegistry().unregisterBlobURL(url);
     });
 }
 
+void ThreadableBlobRegistry::registerBlobURLHandle(const URL& url)
+{
+    ensureOnMainThread([url = "" {
+        blobRegistry().registerBlobURLHandle(url);
+    });
+}
+
+void ThreadableBlobRegistry::unregisterBlobURLHandle(const URL& url)
+{
+    ensureOnMainThread([url = "" {
+        blobRegistry().unregisterBlobURLHandle(url);
+    });
+}
+
 RefPtr<SecurityOrigin> ThreadableBlobRegistry::getCachedOrigin(const URL& url)
 {
     if (auto cachedOrigin = originMap()->get(url.string()))

Modified: trunk/Source/WebCore/fileapi/ThreadableBlobRegistry.h (280823 => 280824)


--- trunk/Source/WebCore/fileapi/ThreadableBlobRegistry.h	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebCore/fileapi/ThreadableBlobRegistry.h	2021-08-10 03:33:03 UTC (rev 280824)
@@ -47,6 +47,9 @@
     static void registerBlobURLForSlice(const URL& newURL, const URL& srcURL, long long start, long long end, const String& contentType);
     static void unregisterBlobURL(const URL&);
 
+    static void registerBlobURLHandle(const URL&);
+    static void unregisterBlobURLHandle(const URL&);
+
     static unsigned long long blobSize(const URL&);
 
     // Returns the origin for the given blob URL. This is because we are not able to embed the unique security origin or the origin of file URL

Modified: trunk/Source/WebCore/loader/PolicyChecker.cpp (280823 => 280824)


--- trunk/Source/WebCore/loader/PolicyChecker.cpp	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebCore/loader/PolicyChecker.cpp	2021-08-10 03:33:03 UTC (rev 280824)
@@ -104,17 +104,12 @@
     checkNavigationPolicy(WTFMove(newRequest), redirectResponse, m_frame.loader().activeDocumentLoader(), { }, WTFMove(function));
 }
 
-URLWithBlobURLLifetimeExtension FrameLoader::PolicyChecker::extendBlobURLLifetimeIfNecessary(ResourceRequest& request, DocumentLoader* loader, PolicyDecisionMode mode) const
+BlobURLHandle FrameLoader::PolicyChecker::extendBlobURLLifetimeIfNecessary(const ResourceRequest& request, PolicyDecisionMode mode) const
 {
     if (mode != PolicyDecisionMode::Asynchronous || !request.url().protocolIsBlob())
         return { };
 
-    URLWithBlobURLLifetimeExtension urlWithLifetimeExtension(request.url());
-    request.setURL(urlWithLifetimeExtension);
-    if (loader)
-        loader->request().setURL(urlWithLifetimeExtension);
-
-    return urlWithLifetimeExtension;
+    return BlobURLHandle { request.url() };
 }
 
 void FrameLoader::PolicyChecker::checkNavigationPolicy(ResourceRequest&& request, const ResourceResponse& redirectResponse, DocumentLoader* loader, RefPtr<FormState>&& formState, NavigationPolicyDecisionFunction&& function, PolicyDecisionMode policyDecisionMode)
@@ -197,7 +192,7 @@
 
     m_frame.loader().clearProvisionalLoadForPolicyCheck();
 
-    auto blobURLLifetimeExtension = extendBlobURLLifetimeIfNecessary(request, loader, policyDecisionMode);
+    auto blobURLLifetimeExtension = extendBlobURLLifetimeIfNecessary(request, policyDecisionMode);
 
     bool isInitialEmptyDocumentLoad = !m_frame.loader().stateMachine().committedFirstRealDocumentLoad() && request.url().protocolIsAbout() && !substituteData.isValid();
     auto requestIdentifier = PolicyCheckIdentifier::create();
@@ -255,7 +250,7 @@
     if (!DOMWindow::allowPopUp(m_frame))
         return function({ }, nullptr, { }, { }, ShouldContinuePolicyCheck::No);
 
-    auto blobURLLifetimeExtension = extendBlobURLLifetimeIfNecessary(request, nullptr);
+    auto blobURLLifetimeExtension = extendBlobURLLifetimeIfNecessary(request);
 
     auto requestIdentifier = PolicyCheckIdentifier::create();
     m_frame.loader().client().dispatchDecidePolicyForNewWindowAction(navigationAction, request, formState.get(), frameName, requestIdentifier, [frame = makeRef(m_frame), request,

Modified: trunk/Source/WebCore/loader/PolicyChecker.h (280823 => 280824)


--- trunk/Source/WebCore/loader/PolicyChecker.h	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebCore/loader/PolicyChecker.h	2021-08-10 03:33:03 UTC (rev 280824)
@@ -51,7 +51,7 @@
 class NavigationAction;
 class ResourceError;
 class ResourceResponse;
-class URLWithBlobURLLifetimeExtension;
+class BlobURLHandle;
 
 enum class NavigationPolicyDecision : uint8_t {
     ContinueLoad,
@@ -90,7 +90,7 @@
 
 private:
     void handleUnimplementablePolicy(const ResourceError&);
-    URLWithBlobURLLifetimeExtension extendBlobURLLifetimeIfNecessary(ResourceRequest&, DocumentLoader*, PolicyDecisionMode = PolicyDecisionMode::Asynchronous) const;
+    BlobURLHandle extendBlobURLLifetimeIfNecessary(const ResourceRequest&, PolicyDecisionMode = PolicyDecisionMode::Asynchronous) const;
 
     Frame& m_frame;
 

Modified: trunk/Source/WebCore/platform/network/BlobRegistry.h (280823 => 280824)


--- trunk/Source/WebCore/platform/network/BlobRegistry.h	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebCore/platform/network/BlobRegistry.h	2021-08-10 03:33:03 UTC (rev 280824)
@@ -63,6 +63,9 @@
 
     virtual void unregisterBlobURL(const URL&) = 0;
 
+    virtual void registerBlobURLHandle(const URL&) = 0;
+    virtual void unregisterBlobURLHandle(const URL&) = 0;
+
     virtual unsigned long long blobSize(const URL&) = 0;
 
     virtual void writeBlobsToTemporaryFiles(const Vector<String>& blobURLs, CompletionHandler<void(Vector<String>&& filePaths)>&&) = 0;

Modified: trunk/Source/WebCore/platform/network/BlobRegistryImpl.cpp (280823 => 280824)


--- trunk/Source/WebCore/platform/network/BlobRegistryImpl.cpp	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebCore/platform/network/BlobRegistryImpl.cpp	2021-08-10 03:33:03 UTC (rev 280824)
@@ -115,7 +115,7 @@
 
     auto blobData = BlobData::create(contentType);
     blobData->appendFile(WTFMove(file));
-    m_blobs.set(url.string(), WTFMove(blobData));
+    addBlobData(url.string(), WTFMove(blobData));
 }
 
 void BlobRegistryImpl::registerBlobURL(const URL& url, Vector<BlobPart>&& blobParts, const String& contentType)
@@ -149,7 +149,7 @@
         }
     }
 
-    m_blobs.set(url.string(), WTFMove(blobData));
+    addBlobData(url.string(), WTFMove(blobData));
 }
 
 void BlobRegistryImpl::registerBlobURL(const URL& url, const URL& srcURL)
@@ -164,7 +164,7 @@
 
     BlobData* src = ""
     if (src) {
-        m_blobs.set(url.string(), src);
+        addBlobData(url.string(), src);
         return;
     }
 
@@ -174,7 +174,7 @@
     auto backingFile = BlobData::create(contentType);
     backingFile->appendFile(file.releaseNonNull());
 
-    m_blobs.set(url.string(), WTFMove(backingFile));
+    addBlobData(url.string(), WTFMove(backingFile));
 }
 
 void BlobRegistryImpl::registerBlobURLForSlice(const URL& url, const URL& srcURL, long long start, long long end, const String& contentType)
@@ -210,13 +210,14 @@
 
     appendStorageItems(newData.ptr(), originalData->items(), start, newLength);
 
-    m_blobs.set(url.string(), WTFMove(newData));
+    addBlobData(url.string(), WTFMove(newData));
 }
 
 void BlobRegistryImpl::unregisterBlobURL(const URL& url)
 {
     ASSERT(isMainThread());
-    m_blobs.remove(url.string());
+    if (m_blobReferences.remove(url.string()))
+        m_blobs.remove(url.string());
 }
 
 BlobData* BlobRegistryImpl::getBlobDataFromURL(const URL& url) const
@@ -359,4 +360,23 @@
     return result;
 }
 
+void BlobRegistryImpl::addBlobData(const String& url, RefPtr<BlobData>&& blobData)
+{
+    auto addResult = m_blobs.set(url, WTFMove(blobData));
+    if (addResult.isNewEntry)
+        m_blobReferences.add(url);
+}
+
+void BlobRegistryImpl::registerBlobURLHandle(const URL& url)
+{
+    if (m_blobs.contains(url.string()))
+        m_blobReferences.add(url.string());
+}
+
+void BlobRegistryImpl::unregisterBlobURLHandle(const URL& url)
+{
+    if (m_blobReferences.remove(url.string()))
+        m_blobs.remove(url.string());
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/network/BlobRegistryImpl.h (280823 => 280824)


--- trunk/Source/WebCore/platform/network/BlobRegistryImpl.h	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebCore/platform/network/BlobRegistryImpl.h	2021-08-10 03:33:03 UTC (rev 280824)
@@ -33,6 +33,7 @@
 
 #include "BlobData.h"
 #include "BlobRegistry.h"
+#include <wtf/HashCountedSet.h>
 #include <wtf/HashMap.h>
 #include <wtf/URLHash.h>
 #include <wtf/text/StringHash.h>
@@ -65,6 +66,9 @@
     void registerBlobURLForSlice(const URL&, const URL& srcURL, long long start, long long end, const String& contentType);
     void unregisterBlobURL(const URL&);
 
+    void registerBlobURLHandle(const URL&);
+    void unregisterBlobURLHandle(const URL&);
+
     unsigned long long blobSize(const URL&);
 
     void writeBlobsToTemporaryFiles(const Vector<String>& blobURLs, CompletionHandler<void(Vector<String>&& filePaths)>&&);
@@ -78,6 +82,9 @@
     Vector<RefPtr<BlobDataFileReference>> filesInBlob(const URL&) const;
 
 private:
+    void addBlobData(const String& url, RefPtr<BlobData>&&);
+
+    HashCountedSet<String> m_blobReferences;
     HashMap<String, RefPtr<BlobData>> m_blobs;
 };
 

Modified: trunk/Source/WebCore/xml/XMLHttpRequest.cpp (280823 => 280824)


--- trunk/Source/WebCore/xml/XMLHttpRequest.cpp	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.cpp	2021-08-10 03:33:03 UTC (rev 280824)
@@ -251,7 +251,7 @@
     // attempt to discourage synchronous XHR use. responseType is one such piece of functionality.
     // We'll only disable this functionality for HTTP(S) requests since sync requests for local protocols
     // such as file: and data: still make sense to allow.
-    if (!m_async && scriptExecutionContext()->isDocument() && m_url.url().protocolIsInHTTPFamily()) {
+    if (!m_async && scriptExecutionContext()->isDocument() && m_url.protocolIsInHTTPFamily()) {
         logConsoleError(scriptExecutionContext(), "XMLHttpRequest.responseType cannot be changed for synchronous HTTP(S) requests made from the window context.");
         return Exception { InvalidAccessError };
     }
@@ -382,9 +382,10 @@
     clearResponse();
     clearRequest();
 
-    auto upgradedURL = url;
-    context->contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(upgradedURL, ContentSecurityPolicy::InsecureRequestType::Load);
-    m_url = WTFMove(upgradedURL);
+    m_url = url;
+    context->contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(m_url, ContentSecurityPolicy::InsecureRequestType::Load);
+    if (m_url.protocolIsBlob())
+        m_blobURLLifetimeExtension = m_url;
 
     m_async = async;
 
@@ -417,7 +418,7 @@
     auto& context = *scriptExecutionContext();
 
     if (is<Document>(context) && downcast<Document>(context).shouldIgnoreSyncXHRs()) {
-        logConsoleError(scriptExecutionContext(), makeString("Ignoring XMLHttpRequest.send() call for '", m_url.url().string(), "' because the maximum number of synchronous failures was reached."));
+        logConsoleError(scriptExecutionContext(), makeString("Ignoring XMLHttpRequest.send() call for '", m_url.string(), "' because the maximum number of synchronous failures was reached."));
         return ExceptionOr<void> { };
     }
 
@@ -521,7 +522,7 @@
         return WTFMove(result.value());
 
     if (m_method != "GET" && m_method != "HEAD") {
-        if (!m_url.url().protocolIsInHTTPFamily()) {
+        if (!m_url.protocolIsInHTTPFamily()) {
             // FIXME: We would like to support posting Blobs to non-http URLs (e.g. custom URL schemes)
             // but because of the architecture of blob-handling that will require a fair amount of work.
             
@@ -594,8 +595,10 @@
 ExceptionOr<void> XMLHttpRequest::createRequest()
 {
     // Only GET request is supported for blob URL.
-    if (!m_async && m_url.url().protocolIsBlob() && m_method != "GET")
+    if (!m_async && m_url.protocolIsBlob() && m_method != "GET") {
+        m_blobURLLifetimeExtension.clear();
         return Exception { NetworkError };
+    }
 
     if (m_async && m_upload && m_upload->hasEventListeners())
         m_uploadListenerFlag = true;
@@ -747,6 +750,7 @@
     m_requestHeaders.clear();
     m_requestEntityBody = nullptr;
     m_url = URL { };
+    m_blobURLLifetimeExtension.clear();
 }
 
 void XMLHttpRequest::genericError()
@@ -939,6 +943,7 @@
 
     m_loadingActivity = std::nullopt;
     m_url = URL { };
+    m_blobURLLifetimeExtension.clear();
 
     m_sendFlag = false;
     changeState(DONE);

Modified: trunk/Source/WebCore/xml/XMLHttpRequest.h (280823 => 280824)


--- trunk/Source/WebCore/xml/XMLHttpRequest.h	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.h	2021-08-10 03:33:03 UTC (rev 280824)
@@ -216,7 +216,8 @@
 
     std::unique_ptr<XMLHttpRequestUpload> m_upload;
 
-    URLWithBlobURLLifetimeExtension m_url;
+    URL m_url;
+    BlobURLHandle m_blobURLLifetimeExtension;
     String m_method;
     HTTPHeaderMap m_requestHeaders;
     RefPtr<FormData> m_requestEntityBody;

Modified: trunk/Source/WebKit/ChangeLog (280823 => 280824)


--- trunk/Source/WebKit/ChangeLog	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebKit/ChangeLog	2021-08-10 03:33:03 UTC (rev 280824)
@@ -1,3 +1,22 @@
+2021-08-09  Chris Dumez  <[email protected]>
+
+        Blob URL changes after loading it
+        https://bugs.webkit.org/show_bug.cgi?id=228923
+
+        Reviewed by Geoff Garen.
+
+        * NetworkProcess/NetworkConnectionToWebProcess.cpp:
+        (WebKit::NetworkConnectionToWebProcess::registerBlobURLHandle):
+        (WebKit::NetworkConnectionToWebProcess::unregisterBlobURLHandle):
+        * NetworkProcess/NetworkConnectionToWebProcess.h:
+        * NetworkProcess/NetworkConnectionToWebProcess.messages.in:
+        * NetworkProcess/NetworkProcessPlatformStrategies.cpp:
+        (WebKit::NetworkProcessPlatformStrategies::createBlobRegistry):
+        * WebProcess/FileAPI/BlobRegistryProxy.cpp:
+        (WebKit::BlobRegistryProxy::registerBlobURLHandle):
+        (WebKit::BlobRegistryProxy::unregisterBlobURLHandle):
+        * WebProcess/FileAPI/BlobRegistryProxy.h:
+
 2021-08-09  Myles C. Maxfield  <[email protected]>
 
         Create a Language log channel

Modified: trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp (280823 => 280824)


--- trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp	2021-08-10 03:33:03 UTC (rev 280824)
@@ -866,6 +866,24 @@
     session->blobRegistry().unregisterBlobURL(url);
 }
 
+void NetworkConnectionToWebProcess::registerBlobURLHandle(const URL& url)
+{
+    auto* session = networkSession();
+    if (!session)
+        return;
+
+    session->blobRegistry().registerBlobURLHandle(url);
+}
+
+void NetworkConnectionToWebProcess::unregisterBlobURLHandle(const URL& url)
+{
+    auto* session = networkSession();
+    if (!session)
+        return;
+
+    session->blobRegistry().unregisterBlobURLHandle(url);
+}
+
 void NetworkConnectionToWebProcess::blobSize(const URL& url, CompletionHandler<void(uint64_t)>&& completionHandler)
 {
     auto* session = networkSession();

Modified: trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h (280823 => 280824)


--- trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h	2021-08-10 03:33:03 UTC (rev 280824)
@@ -236,6 +236,9 @@
     void unregisterBlobURL(const URL&);
     void writeBlobsToTemporaryFiles(const Vector<String>& blobURLs, CompletionHandler<void(Vector<String>&&)>&&);
 
+    void registerBlobURLHandle(const URL&);
+    void unregisterBlobURLHandle(const URL&);
+
     void setCaptureExtraNetworkLoadMetricsEnabled(bool);
 
     void createSocketStream(URL&&, String cachePartition, WebCore::WebSocketIdentifier);

Modified: trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in (280823 => 280824)


--- trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.messages.in	2021-08-10 03:33:03 UTC (rev 280824)
@@ -56,6 +56,8 @@
     UnregisterBlobURL(URL url)
     BlobSize(URL url) -> (uint64_t resultSize) Synchronous
     WriteBlobsToTemporaryFiles(Vector<String> blobURLs) -> (Vector<String> fileNames) Async
+    RegisterBlobURLHandle(URL url);
+    UnregisterBlobURLHandle(URL url);
 
     SetCaptureExtraNetworkLoadMetricsEnabled(bool enabled)
 

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcessPlatformStrategies.cpp (280823 => 280824)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcessPlatformStrategies.cpp	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcessPlatformStrategies.cpp	2021-08-10 03:33:03 UTC (rev 280824)
@@ -65,6 +65,8 @@
         void unregisterBlobURL(const URL&) final { ASSERT_NOT_REACHED(); }
         unsigned long long blobSize(const URL&) final { ASSERT_NOT_REACHED(); return 0; }
         void writeBlobsToTemporaryFiles(const Vector<String>& blobURLs, CompletionHandler<void(Vector<String>&& filePaths)>&&) final { ASSERT_NOT_REACHED(); }
+        void registerBlobURLHandle(const URL&) final { ASSERT_NOT_REACHED(); }
+        void unregisterBlobURLHandle(const URL&) final { ASSERT_NOT_REACHED(); }
     };
     static NeverDestroyed<EmptyBlobRegistry> blobRegistry;
     return &blobRegistry.get();

Modified: trunk/Source/WebKit/WebProcess/FileAPI/BlobRegistryProxy.cpp (280823 => 280824)


--- trunk/Source/WebKit/WebProcess/FileAPI/BlobRegistryProxy.cpp	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebKit/WebProcess/FileAPI/BlobRegistryProxy.cpp	2021-08-10 03:33:03 UTC (rev 280824)
@@ -74,6 +74,16 @@
     WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::RegisterBlobURLForSlice(url, srcURL, start, end, contentType), 0);
 }
 
+void BlobRegistryProxy::registerBlobURLHandle(const URL& url)
+{
+    WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::RegisterBlobURLHandle(url), 0);
+}
+
+void BlobRegistryProxy::unregisterBlobURLHandle(const URL& url)
+{
+    WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::UnregisterBlobURLHandle(url), 0);
+}
+
 unsigned long long BlobRegistryProxy::blobSize(const URL& url)
 {
     uint64_t resultSize;

Modified: trunk/Source/WebKit/WebProcess/FileAPI/BlobRegistryProxy.h (280823 => 280824)


--- trunk/Source/WebKit/WebProcess/FileAPI/BlobRegistryProxy.h	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebKit/WebProcess/FileAPI/BlobRegistryProxy.h	2021-08-10 03:33:03 UTC (rev 280824)
@@ -39,6 +39,8 @@
     void registerBlobURLForSlice(const URL&, const URL& srcURL, long long start, long long end, const String& contentType) final;
     unsigned long long blobSize(const URL&) final;
     void writeBlobsToTemporaryFiles(const Vector<String>& blobURLs, CompletionHandler<void(Vector<String>&& filePaths)>&&) final;
+    void registerBlobURLHandle(const URL&) final;
+    void unregisterBlobURLHandle(const URL&) final;
 };
 
 }

Modified: trunk/Source/WebKitLegacy/mac/ChangeLog (280823 => 280824)


--- trunk/Source/WebKitLegacy/mac/ChangeLog	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog	2021-08-10 03:33:03 UTC (rev 280824)
@@ -1,3 +1,12 @@
+2021-08-09  Chris Dumez  <[email protected]>
+
+        Blob URL changes after loading it
+        https://bugs.webkit.org/show_bug.cgi?id=228923
+
+        Reviewed by Geoff Garen.
+
+        * WebCoreSupport/WebPlatformStrategies.mm:
+
 2021-08-09  Myles C. Maxfield  <[email protected]>
 
         Support WTF logging channels

Modified: trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.mm (280823 => 280824)


--- trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.mm	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebPlatformStrategies.mm	2021-08-10 03:33:03 UTC (rev 280824)
@@ -91,6 +91,8 @@
     void unregisterBlobURL(const URL& url) final { m_blobRegistry.unregisterBlobURL(url); }
     unsigned long long blobSize(const URL& url) final { return m_blobRegistry.blobSize(url); }
     void writeBlobsToTemporaryFiles(const Vector<String>& blobURLs, CompletionHandler<void(Vector<String>&& filePaths)>&& completionHandler) final { m_blobRegistry.writeBlobsToTemporaryFiles(blobURLs, WTFMove(completionHandler)); }
+    void registerBlobURLHandle(const URL& url) final { m_blobRegistry.registerBlobURLHandle(url); }
+    void unregisterBlobURLHandle(const URL& url) final { m_blobRegistry.unregisterBlobURLHandle(url); }
 
     BlobRegistryImpl* blobRegistryImpl() final { return &m_blobRegistry; }
 

Modified: trunk/Source/WebKitLegacy/win/ChangeLog (280823 => 280824)


--- trunk/Source/WebKitLegacy/win/ChangeLog	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebKitLegacy/win/ChangeLog	2021-08-10 03:33:03 UTC (rev 280824)
@@ -1,3 +1,12 @@
+2021-08-09  Chris Dumez  <[email protected]>
+
+        Blob URL changes after loading it
+        https://bugs.webkit.org/show_bug.cgi?id=228923
+
+        Reviewed by Geoff Garen.
+
+        * WebCoreSupport/WebPlatformStrategies.cpp:
+
 2021-08-09  Stephan Szabo  <[email protected]>
 
         [WinCairo][Debug] Build fix after r280756

Modified: trunk/Source/WebKitLegacy/win/WebCoreSupport/WebPlatformStrategies.cpp (280823 => 280824)


--- trunk/Source/WebKitLegacy/win/WebCoreSupport/WebPlatformStrategies.cpp	2021-08-10 03:11:48 UTC (rev 280823)
+++ trunk/Source/WebKitLegacy/win/WebCoreSupport/WebPlatformStrategies.cpp	2021-08-10 03:33:03 UTC (rev 280824)
@@ -87,6 +87,8 @@
     void unregisterBlobURL(const URL& url) final { m_blobRegistry.unregisterBlobURL(url); }
     unsigned long long blobSize(const URL& url) final { return m_blobRegistry.blobSize(url); }
     void writeBlobsToTemporaryFiles(const Vector<String>& blobURLs, CompletionHandler<void(Vector<String>&& filePaths)>&& completionHandler) final { m_blobRegistry.writeBlobsToTemporaryFiles(blobURLs, WTFMove(completionHandler)); }
+    void registerBlobURLHandle(const URL& url) final { m_blobRegistry.registerBlobURLHandle(url); }
+    void unregisterBlobURLHandle(const URL& url) final { m_blobRegistry.unregisterBlobURLHandle(url); }
 
     BlobRegistryImpl* blobRegistryImpl() final { return &m_blobRegistry; }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to