⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 280547 in webkit


Ignore:
Timestamp:
Aug 2, 2021, 11:46:51 AM (5 years ago)
Author:
Chris Dumez
Message:

imported/w3c/web-platform-tests/webmessaging/broadcastchannel/blobs.html is a flaky failure since implementing BlobChannel
https://bugs.webkit.org/show_bug.cgi?id=228168
<rdar://problem/80922502>

Reviewed by Alex Christensen.

Source/WebCore:

The test was flaky because it is trying to send a Blob via BroadcastChannel.postMessage()
without keeping the blob alive. When GC triggers, the Blob would go away and trying to
decode the Blob upon receiving would fail.

To address the issue, I introduced a Blob::Handle class that wraps the Blob's internal URL
and keeps the Blob data alive as long as as someone is holding such handle. Previously,
the Blob destructor would unregister the internal URL and the Blob data would go away.

I then updated SerializedScriptValue to hold on to Blob::Handle objects instead of Blob
URLs. This guarantees that when using postMessage() to send a message to a worker, the
Blob data will stay alive until we dispatch the message event on the worker side and try
and deserialized the SerializedScriptValue.

For BroadcastChannel.postMessage() though, we end up going via the network process and
the SerializedScriptValue ends up getting serialized/deserialized over IPC. I added a
CompletionHandler to BroadcastChannelRegistry::postMessage() which only gets called
once the message event has successfully been dispatched. I use this completion handler
to make sure the SerializedScriptValue's Blob URLs stay valid until the the message has
been dispatched by holding on to the Blob::Handles.

No new tests, unskipped existing test.

  • Modules/indexeddb/IDBValue.cpp:

(WebCore::IDBValue::IDBValue):

  • bindings/js/SerializedScriptValue.cpp:

(WebCore::CloneSerializer::serialize):
(WebCore::CloneSerializer::CloneSerializer):
(WebCore::CloneSerializer::dumpIfTerminal):
(WebCore::CloneSerializer::write):
(WebCore::SerializedScriptValue::SerializedScriptValue):
(WebCore::SerializedScriptValue::computeMemoryCost const):
(WebCore::SerializedScriptValue::create):
(WebCore::SerializedScriptValue::blobURLs const):
(WebCore::SerializedScriptValue::writeBlobsToDiskForIndexedDB):

  • bindings/js/SerializedScriptValue.h:

(WebCore::SerializedScriptValue::hasBlobURLs const):
(WebCore::SerializedScriptValue::blobHandles const):
(WebCore::SerializedScriptValue::SerializedScriptValue):

  • dom/BroadcastChannel.cpp:

(WebCore::BroadcastChannel::postMessage):
(WebCore::BroadcastChannel::dispatchMessageTo):

  • dom/BroadcastChannel.h:
  • dom/BroadcastChannelRegistry.h:
  • fileapi/Blob.cpp:

(WebCore::BlobInternalURL::create):
(WebCore::BlobInternalURL::~BlobInternalURL):
(WebCore::BlobInternalURL::url const):
(WebCore::BlobInternalURL::BlobInternalURL):
(WebCore::Blob::Blob):
(WebCore::Blob::~Blob):
(WebCore::Blob::url const):
(WebCore::Blob::slice const):
(WebCore::Blob::size const):
(WebCore::Blob::handle const):
(WebCore::Blob::Handle::Handle):
(WebCore::Blob::Handle::url const):

  • fileapi/Blob.h:
  • loader/EmptyClients.cpp:

Source/WebKit:

  • NetworkProcess/NetworkBroadcastChannelRegistry.cpp:

(WebKit::NetworkBroadcastChannelRegistry::postMessage):

  • NetworkProcess/NetworkBroadcastChannelRegistry.h:
  • NetworkProcess/NetworkBroadcastChannelRegistry.messages.in:
  • Platform/IPC/HandleMessage.h:

(IPC::handleMessageAsyncWantsConnection):
handleMessageAsyncWantsConnection() had gotten out of sync with handleMessageAsync(). This was causing IPC decoding
failures when using both "Async" and "WantsConnection" for the IPC message.

  • WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.cpp:

(WebKit::WebBroadcastChannelRegistry::postMessage):
(WebKit::WebBroadcastChannelRegistry::postMessageToRemote):

  • WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.h:
  • WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.messages.in:

Source/WebKitLegacy:

  • WebCoreSupport/WebBroadcastChannelRegistry.cpp:

(WebBroadcastChannelRegistry::postMessage):

  • WebCoreSupport/WebBroadcastChannelRegistry.h:

LayoutTests:

Unskip test that is no longer flaky.

  • platform/ios-wk2/TestExpectations:
  • platform/mac/TestExpectations:
Location:
trunk
Files:
24 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r280543 r280547  
     12021-08-02  Chris Dumez  <cdumez@apple.com>
     2
     3        imported/w3c/web-platform-tests/webmessaging/broadcastchannel/blobs.html is a flaky failure since implementing BlobChannel
     4        https://bugs.webkit.org/show_bug.cgi?id=228168
     5        <rdar://problem/80922502>
     6
     7        Reviewed by Alex Christensen.
     8
     9        Unskip test that is no longer flaky.
     10
     11        * platform/ios-wk2/TestExpectations:
     12        * platform/mac/TestExpectations:
     13
    1142021-08-02  Wenson Hsieh  <wenson_hsieh@apple.com>
    215
  • trunk/LayoutTests/platform/ios-wk2/TestExpectations

    r280532 r280547  
    19951995webkit.org/b/228114 imported/w3c/web-platform-tests/fetch/content-type/script.window.html [ Pass Failure ]
    19961996
    1997 webkit.org/b/228168 imported/w3c/web-platform-tests/webmessaging/broadcastchannel/blobs.html [ Pass Failure ]
    1998 
    19991997webkit.org/b/227998 imported/w3c/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-network-error.sub.html [ Pass Failure ]
    20001998
  • trunk/LayoutTests/platform/mac/TestExpectations

    r280504 r280547  
    22972297webkit.org/b/214574 svg/animations/smil-leak-list-property-instances.svg [ Pass Failure ]
    22982298
    2299 webkit.org/b/228168 imported/w3c/web-platform-tests/webmessaging/broadcastchannel/blobs.html [ Pass Failure ]
    2300 
    23012299webkit.org/b/222385 imported/w3c/web-platform-tests/xhr/event-upload-progress-crossorigin.any.worker.html [ Pass Failure ]
    23022300
  • trunk/Source/WebCore/ChangeLog

    r280543 r280547  
     12021-08-02  Chris Dumez  <cdumez@apple.com>
     2
     3        imported/w3c/web-platform-tests/webmessaging/broadcastchannel/blobs.html is a flaky failure since implementing BlobChannel
     4        https://bugs.webkit.org/show_bug.cgi?id=228168
     5        <rdar://problem/80922502>
     6
     7        Reviewed by Alex Christensen.
     8
     9        The test was flaky because it is trying to send a Blob via BroadcastChannel.postMessage()
     10        without keeping the blob alive. When GC triggers, the Blob would go away and trying to
     11        decode the Blob upon receiving would fail.
     12
     13        To address the issue, I introduced a Blob::Handle class that wraps the Blob's internal URL
     14        and keeps the Blob data alive as long as as someone is holding such handle. Previously,
     15        the Blob destructor would unregister the internal URL and the Blob data would go away.
     16
     17        I then updated SerializedScriptValue to hold on to Blob::Handle objects instead of Blob
     18        URLs. This guarantees that when using postMessage() to send a message to a worker, the
     19        Blob data will stay alive until we dispatch the message event on the worker side and try
     20        and deserialized the SerializedScriptValue.
     21
     22        For BroadcastChannel.postMessage() though, we end up going via the network process and
     23        the SerializedScriptValue ends up getting serialized/deserialized over IPC. I added a
     24        CompletionHandler to BroadcastChannelRegistry::postMessage() which only gets called
     25        once the message event has successfully been dispatched. I use this completion handler
     26        to make sure the SerializedScriptValue's Blob URLs stay valid until the the message has
     27        been dispatched by holding on to the Blob::Handles.
     28
     29        No new tests, unskipped existing test.
     30
     31        * Modules/indexeddb/IDBValue.cpp:
     32        (WebCore::IDBValue::IDBValue):
     33        * bindings/js/SerializedScriptValue.cpp:
     34        (WebCore::CloneSerializer::serialize):
     35        (WebCore::CloneSerializer::CloneSerializer):
     36        (WebCore::CloneSerializer::dumpIfTerminal):
     37        (WebCore::CloneSerializer::write):
     38        (WebCore::SerializedScriptValue::SerializedScriptValue):
     39        (WebCore::SerializedScriptValue::computeMemoryCost const):
     40        (WebCore::SerializedScriptValue::create):
     41        (WebCore::SerializedScriptValue::blobURLs const):
     42        (WebCore::SerializedScriptValue::writeBlobsToDiskForIndexedDB):
     43        * bindings/js/SerializedScriptValue.h:
     44        (WebCore::SerializedScriptValue::hasBlobURLs const):
     45        (WebCore::SerializedScriptValue::blobHandles const):
     46        (WebCore::SerializedScriptValue::SerializedScriptValue):
     47        * dom/BroadcastChannel.cpp:
     48        (WebCore::BroadcastChannel::postMessage):
     49        (WebCore::BroadcastChannel::dispatchMessageTo):
     50        * dom/BroadcastChannel.h:
     51        * dom/BroadcastChannelRegistry.h:
     52        * fileapi/Blob.cpp:
     53        (WebCore::BlobInternalURL::create):
     54        (WebCore::BlobInternalURL::~BlobInternalURL):
     55        (WebCore::BlobInternalURL::url const):
     56        (WebCore::BlobInternalURL::BlobInternalURL):
     57        (WebCore::Blob::Blob):
     58        (WebCore::Blob::~Blob):
     59        (WebCore::Blob::url const):
     60        (WebCore::Blob::slice const):
     61        (WebCore::Blob::size const):
     62        (WebCore::Blob::handle const):
     63        (WebCore::Blob::Handle::Handle):
     64        (WebCore::Blob::Handle::url const):
     65        * fileapi/Blob.h:
     66        * loader/EmptyClients.cpp:
     67
    1682021-08-02  Wenson Hsieh  <wenson_hsieh@apple.com>
    269
  • trunk/Source/WebCore/Modules/indexeddb/IDBValue.cpp

    r275151 r280547  
    3838IDBValue::IDBValue(const SerializedScriptValue& scriptValue)
    3939    : m_data(ThreadSafeDataBuffer::copyVector(scriptValue.data()))
    40     , m_blobURLs(scriptValue.blobURLsIsolatedCopy())
     40    , m_blobURLs(scriptValue.blobURLs())
    4141{
    4242}
  • trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp

    r280476 r280547  
    601601            WasmMemoryHandleArray& wasmMemoryHandles,
    602602#endif
    603         Vector<String>& blobURLs, Vector<uint8_t>& out, SerializationContext context, ArrayBufferContentsArray& sharedBuffers)
     603        Vector<Blob::Handle>& blobHandles, Vector<uint8_t>& out, SerializationContext context, ArrayBufferContentsArray& sharedBuffers)
    604604    {
    605605        CloneSerializer serializer(lexicalGlobalObject, messagePorts, arrayBuffers, imageBitmaps,
     
    614614            wasmMemoryHandles,
    615615#endif
    616             blobURLs, out, context, sharedBuffers);
     616            blobHandles, out, context, sharedBuffers);
    617617        return serializer.serialize(value);
    618618    }
     
    648648            WasmMemoryHandleArray& wasmMemoryHandles,
    649649#endif
    650         Vector<String>& blobURLs, Vector<uint8_t>& out, SerializationContext context, ArrayBufferContentsArray& sharedBuffers)
     650        Vector<Blob::Handle>& blobHandles, Vector<uint8_t>& out, SerializationContext context, ArrayBufferContentsArray& sharedBuffers)
    651651        : CloneBase(lexicalGlobalObject)
    652652        , m_buffer(out)
    653         , m_blobURLs(blobURLs)
     653        , m_blobHandles(blobHandles)
    654654        , m_emptyIdentifier(Identifier::fromString(lexicalGlobalObject->vm(), emptyString()))
    655655        , m_context(context)
     
    12251225            if (auto* blob = JSBlob::toWrapped(vm, obj)) {
    12261226                write(BlobTag);
    1227                 m_blobURLs.append(blob->url().string());
     1227                m_blobHandles.append(blob->handle());
    12281228                write(blob->url().string());
    12291229                write(blob->type());
     
    12981298                write(CryptoKeyTag);
    12991299                Vector<uint8_t> serializedKey;
    1300                 Vector<String> dummyBlobURLs;
     1300                Vector<Blob::Handle> dummyBlobHandles;
    13011301                Vector<RefPtr<MessagePort>> dummyMessagePorts;
    13021302                Vector<RefPtr<JSC::ArrayBuffer>> dummyArrayBuffers;
     
    13171317                    dummyMemoryHandles,
    13181318#endif
    1319                     dummyBlobURLs, serializedKey, SerializationContext::Default, dummySharedBuffers);
     1319                    dummyBlobHandles, serializedKey, SerializationContext::Default, dummySharedBuffers);
    13201320                rawKeySerializer.write(key);
    13211321                Vector<uint8_t> wrappedKey;
     
    15511551    void write(const File& file)
    15521552    {
    1553         m_blobURLs.append(file.url().string());
     1553        m_blobHandles.append(file.handle());
    15541554        write(file.path());
    15551555        write(file.url().string());
     
    17611761
    17621762    Vector<uint8_t>& m_buffer;
    1763     Vector<String>& m_blobURLs;
     1763    Vector<Blob::Handle>& m_blobHandles;
    17641764    ObjectPool m_objectPool;
    17651765    ObjectPool m_transferredMessagePorts;
     
    39163916}
    39173917
    3918 SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>&& buffer, const Vector<String>& blobURLs, std::unique_ptr<ArrayBufferContentsArray> arrayBufferContentsArray, std::unique_ptr<ArrayBufferContentsArray> sharedBufferContentsArray, Vector<std::optional<ImageBitmapBacking>>&& backingStores
     3918SerializedScriptValue::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
    39193919#if ENABLE(OFFSCREEN_CANVAS_IN_WORKERS)
    39203920        , Vector<std::unique_ptr<DetachedOffscreenCanvas>>&& detachedOffscreenCanvases
     
    39423942    , m_wasmMemoryHandlesArray(WTFMove(wasmMemoryHandlesArray))
    39433943#endif
     3944    , m_blobHandles(blobHandles)
    39443945{
    3945     // Since this SerializedScriptValue is meant to be passed between threads, its String data members
    3946     // need to be isolatedCopies so we don't run into thread safety issues for the StringImpls.
    3947     m_blobURLs.reserveInitialCapacity(blobURLs.size());
    3948     for (auto& url : blobURLs)
    3949         m_blobURLs.uncheckedAppend(url.isolatedCopy());
    39503946    m_memoryCost = computeMemoryCost();
    39513947}
     
    39913987#endif
    39923988
    3993     for (auto& urls : m_blobURLs)
    3994         cost += urls.sizeInBytes();
     3989    for (auto& handle : m_blobHandles)
     3990        cost += handle.url().string().sizeInBytes();
    39953991
    39963992    return cost;
     
    40704066{
    40714067    Vector<uint8_t> buffer;
    4072     Vector<String> blobURLs;
     4068    Vector<Blob::Handle> blobHandles;
    40734069    Vector<RefPtr<MessagePort>> dummyMessagePorts;
    40744070    Vector<RefPtr<ImageBitmap>> dummyImageBitmaps;
     
    40964092        dummyMemoryHandles,
    40974093#endif
    4098         blobURLs, buffer, SerializationContext::Default, dummySharedBuffers);
     4094        blobHandles, buffer, SerializationContext::Default, dummySharedBuffers);
    40994095
    41004096#if ENABLE(WEBASSEMBLY)
     
    41094105        return nullptr;
    41104106
    4111     return adoptRef(*new SerializedScriptValue(WTFMove(buffer), blobURLs, nullptr, nullptr, { }));
     4107    return adoptRef(*new SerializedScriptValue(WTFMove(buffer), blobHandles, nullptr, nullptr, { }));
    41124108}
    41134109
     
    42224218
    42234219    Vector<uint8_t> buffer;
    4224     Vector<String> blobURLs;
     4220    Vector<Blob::Handle> blobHandles;
    42254221#if ENABLE(WEBASSEMBLY)
    42264222    WasmModuleArray wasmModules;
     
    42394235        wasmMemoryHandles,
    42404236#endif
    4241         blobURLs, buffer, context, *sharedBuffers);
     4237        blobHandles, buffer, context, *sharedBuffers);
    42424238
    42434239    if (code != SerializationReturnCode::SuccessfullyCompleted)
     
    42614257#endif
    42624258
    4263     return adoptRef(*new SerializedScriptValue(WTFMove(buffer), blobURLs, arrayBufferContentsArray.releaseReturnValue(), context == SerializationContext::WorkerPostMessage ? WTFMove(sharedBuffers) : nullptr, WTFMove(backingStores)
     4259    return adoptRef(*new SerializedScriptValue(WTFMove(buffer), blobHandles, arrayBufferContentsArray.releaseReturnValue(), context == SerializationContext::WorkerPostMessage ? WTFMove(sharedBuffers) : nullptr, WTFMove(backingStores)
    42644260#if ENABLE(OFFSCREEN_CANVAS_IN_WORKERS)
    42654261                , WTFMove(detachedCanvases)
     
    43674363}
    43684364
    4369 Vector<String> SerializedScriptValue::blobURLsIsolatedCopy() const
     4365Vector<String> SerializedScriptValue::blobURLs() const
    43704366{
    43714367    Vector<String> result;
    4372     result.reserveInitialCapacity(m_blobURLs.size());
    4373     for (auto& url : m_blobURLs)
    4374         result.uncheckedAppend(url.isolatedCopy());
     4368    result.reserveInitialCapacity(m_blobHandles.size());
     4369    for (auto& handle : m_blobHandles)
     4370        result.uncheckedAppend(handle.url().string());
    43754371
    43764372    return result;
     
    43824378    ASSERT(hasBlobURLs());
    43834379
    4384     blobRegistry().writeBlobsToTemporaryFiles(m_blobURLs, [completionHandler = WTFMove(completionHandler), this, protectedThis = makeRef(*this)] (auto&& blobFilePaths) mutable {
     4380    blobRegistry().writeBlobsToTemporaryFiles(blobURLs(), [completionHandler = WTFMove(completionHandler), this, protectedThis = makeRef(*this)] (auto&& blobFilePaths) mutable {
    43854381        ASSERT(isMainThread());
    43864382
     
    43924388        }
    43934389
    4394         ASSERT(m_blobURLs.size() == blobFilePaths.size());
    4395 
    4396         completionHandler({ *this, m_blobURLs, blobFilePaths });
     4390        ASSERT(m_blobHandles.size() == blobFilePaths.size());
     4391
     4392        completionHandler({ *this, blobURLs(), blobFilePaths });
    43974393    });
    43984394}
  • trunk/Source/WebCore/bindings/js/SerializedScriptValue.h

    r278253 r280547  
    2727#pragma once
    2828
     29#include "Blob.h"
    2930#include "DetachedRTCDataChannel.h"
    3031#include "ExceptionOr.h"
     
    9697
    9798    const Vector<uint8_t>& data() const { return m_data; }
    98     bool hasBlobURLs() const { return !m_blobURLs.isEmpty(); }
    99 
    100     Vector<String> blobURLsIsolatedCopy() const;
     99    bool hasBlobURLs() const { return !m_blobHandles.isEmpty(); }
     100
     101    Vector<String> blobURLs() const;
     102    const Vector<Blob::Handle>& blobHandles() const { return m_blobHandles; }
    101103    void writeBlobsToDiskForIndexedDB(CompletionHandler<void(IDBValue&&)>&&);
    102104    IDBValue writeBlobsToDiskForIndexedDBSynchronously();
     
    122124        );
    123125
    124     SerializedScriptValue(Vector<unsigned char>&&, const Vector<String>& blobURLs, std::unique_ptr<ArrayBufferContentsArray>, std::unique_ptr<ArrayBufferContentsArray> sharedBuffers, Vector<std::optional<ImageBitmapBacking>>&& backingStores
     126    SerializedScriptValue(Vector<unsigned char>&&, const Vector<Blob::Handle>& blobHandles, std::unique_ptr<ArrayBufferContentsArray>, std::unique_ptr<ArrayBufferContentsArray> sharedBuffers, Vector<std::optional<ImageBitmapBacking>>&& backingStores
    125127#if ENABLE(OFFSCREEN_CANVAS_IN_WORKERS)
    126128        , Vector<std::unique_ptr<DetachedOffscreenCanvas>>&& = { }
     
    151153    std::unique_ptr<WasmMemoryHandleArray> m_wasmMemoryHandlesArray;
    152154#endif
    153     Vector<String> m_blobURLs;
     155    Vector<Blob::Handle> m_blobHandles;
    154156    size_t m_memoryCost { 0 };
    155157};
  • trunk/Source/WebCore/dom/BroadcastChannel.cpp

    r279971 r280547  
    3535#include "WorkerGlobalScope.h"
    3636#include "WorkerLoaderProxy.h"
     37#include <wtf/CallbackAggregator.h>
    3738#include <wtf/HashMap.h>
    3839#include <wtf/IsoMallocInlines.h>
     
    9697
    9798    ensureOnMainThread([origin = crossThreadCopy(m_origin), name = crossThreadCopy(m_name), identifier = m_identifier, messageData = messageData.releaseReturnValue()](auto& document) mutable {
    98         if (auto* page = document.page())
    99             page->broadcastChannelRegistry().postMessage(origin, name, identifier, WTFMove(messageData));
     99        auto* page = document.page();
     100        if (!page)
     101            return;
     102
     103        auto blobHandles = messageData->blobHandles();
     104        page->broadcastChannelRegistry().postMessage(origin, name, identifier, WTFMove(messageData), [blobHandles = WTFMove(blobHandles)] {
     105            // Keeps Blob data inside messageData alive until the message has been delivered.
     106        });
    100107    });
    101108
     
    116123}
    117124
    118 void BroadcastChannel::dispatchMessageTo(BroadcastChannelIdentifier channelIdentifier, Ref<SerializedScriptValue>&& message)
     125void BroadcastChannel::dispatchMessageTo(BroadcastChannelIdentifier channelIdentifier, Ref<SerializedScriptValue>&& message, CompletionHandler<void()>&& completionHandler)
    119126{
    120127    ASSERT(isMainThread());
    121128    auto contextIdentifier = channelToContextIdentifier().get(channelIdentifier);
    122129    if (!contextIdentifier)
    123         return;
     130        return completionHandler();
    124131
    125     ScriptExecutionContext::postTaskTo(contextIdentifier, [channelIdentifier, message = WTFMove(message)](auto&) mutable {
     132    auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
     133    ScriptExecutionContext::postTaskTo(contextIdentifier, [channelIdentifier, message = WTFMove(message), callbackAggregator = WTFMove(callbackAggregator)](auto&) mutable {
    126134        RefPtr<BroadcastChannel> channel;
    127135        {
     
    131139        if (channel)
    132140            channel->dispatchMessage(WTFMove(message));
     141
     142        callOnMainThread([callbackAggregator = WTFMove(callbackAggregator)] { });
    133143    });
    134144}
  • trunk/Source/WebCore/dom/BroadcastChannel.h

    r279971 r280547  
    6363    void close();
    6464
    65     WEBCORE_EXPORT static void dispatchMessageTo(BroadcastChannelIdentifier, Ref<SerializedScriptValue>&&);
     65    WEBCORE_EXPORT static void dispatchMessageTo(BroadcastChannelIdentifier, Ref<SerializedScriptValue>&&, CompletionHandler<void()>&&);
    6666
    6767private:
  • trunk/Source/WebCore/dom/BroadcastChannelRegistry.h

    r279971 r280547  
    2727
    2828#include "BroadcastChannelIdentifier.h"
     29#include <wtf/Forward.h>
    2930#include <wtf/RefCounted.h>
    3031
     
    3940    virtual void registerChannel(const SecurityOriginData&, const String& name, BroadcastChannelIdentifier) = 0;
    4041    virtual void unregisterChannel(const SecurityOriginData&, const String& name, BroadcastChannelIdentifier) = 0;
    41     virtual void postMessage(const SecurityOriginData&, const String& name, BroadcastChannelIdentifier source, Ref<SerializedScriptValue>&&) = 0;
     42    virtual void postMessage(const SecurityOriginData&, const String& name, BroadcastChannelIdentifier source, Ref<SerializedScriptValue>&&, CompletionHandler<void()>&&) = 0;
    4243};
    4344
  • trunk/Source/WebCore/fileapi/Blob.cpp

    r278702 r280547  
    4545#include <wtf/IsoMallocInlines.h>
    4646#include <wtf/NeverDestroyed.h>
     47#include <wtf/ThreadSafeRefCounted.h>
    4748#include <wtf/text/CString.h>
    4849
     
    5960};
    6061
    61 
    6262void BlobURLRegistry::registerURL(ScriptExecutionContext& context, const URL& publicURL, URLRegistrable& blob)
    6363{
     
    7777}
    7878
     79// Unregisters the Blob's internal URL upon destruction. This can be used to extend the lifetime of the Blob data
     80// without actually keeping the Blob object alive.
     81class BlobInternalURL : public ThreadSafeRefCounted<BlobInternalURL> {
     82public:
     83    static Ref<BlobInternalURL> create(Vector<BlobPart>&& blobParts, const String& contentType)
     84    {
     85        return adoptRef(*new BlobInternalURL(WTFMove(blobParts), contentType));
     86    }
     87
     88    static Ref<BlobInternalURL> createForDeserialization(const URL& sourceURL, const String& fileBackedPath, const String& type)
     89    {
     90        return adoptRef(*new BlobInternalURL(sourceURL, fileBackedPath, type));
     91    }
     92
     93    static Ref<BlobInternalURL> createForSlice(const URL& sourceURL, long long start, long long end, const String& type)
     94    {
     95        return adoptRef(*new BlobInternalURL(sourceURL, start, end, type));
     96    }
     97
     98    static Ref<BlobInternalURL> adoptInternalURL(const URL& url)
     99    {
     100        return adoptRef(*new BlobInternalURL(crossThreadCopy(url)));
     101    }
     102
     103    ~BlobInternalURL()
     104    {
     105        ThreadableBlobRegistry::unregisterBlobURL(m_internalURL);
     106    }
     107
     108    URL url() const { return m_internalURL.isolatedCopy(); }
     109
     110private:
     111    BlobInternalURL(Vector<BlobPart>&& blobParts, const String& contentType)
     112        : m_internalURL(BlobURL::createInternalURL())
     113    {
     114        ThreadableBlobRegistry::registerBlobURL(m_internalURL, WTFMove(blobParts), contentType);
     115    }
     116    BlobInternalURL(const URL& sourceURL, long long start, long long end, const String& type)
     117        : m_internalURL(BlobURL::createInternalURL())
     118    {
     119        ThreadableBlobRegistry::registerBlobURLForSlice(m_internalURL, sourceURL, start, end, type);
     120    }
     121    BlobInternalURL(const URL& sourceURL, const String& fileBackedPath, const String& type)
     122        : m_internalURL(BlobURL::createInternalURL())
     123    {
     124        if (fileBackedPath.isEmpty())
     125            ThreadableBlobRegistry::registerBlobURL(nullptr, m_internalURL, sourceURL);
     126        else
     127            ThreadableBlobRegistry::registerBlobURLOptionallyFileBacked(m_internalURL, sourceURL, fileBackedPath, type);
     128    }
     129    BlobInternalURL(URL&& internalURL)
     130        : m_internalURL(WTFMove(internalURL))
     131    { }
     132
     133    URL m_internalURL;
     134};
     135
    79136Blob::Blob(UninitializedContructor, ScriptExecutionContext* context, URL&& url, String&& type)
    80137    : ActiveDOMObject(context)
    81     , m_internalURL(WTFMove(url))
    82138    , m_type(WTFMove(type))
     139    , m_internalURL(BlobInternalURL::adoptInternalURL(url))
    83140{
    84141}
     
    87144    : ActiveDOMObject(context)
    88145    , m_size(0)
    89 {
    90     m_internalURL = BlobURL::createInternalURL();
    91     ThreadableBlobRegistry::registerBlobURL(m_internalURL, { },  { });
    92 }
    93 
    94 Blob::Blob(ScriptExecutionContext& context, Vector<BlobPartVariant>&& blobPartVariants, const BlobPropertyBag& propertyBag)
    95     : ActiveDOMObject(&context)
    96     , m_internalURL(BlobURL::createInternalURL())
    97     , m_type(normalizedContentType(propertyBag.type))
     146    , m_internalURL(BlobInternalURL::create({ }, { }))
     147{
     148}
     149
     150static Vector<BlobPart> buildBlobData(Vector<BlobPartVariant>&& blobPartVariants, const BlobPropertyBag& propertyBag)
    98151{
    99152    BlobBuilder builder(propertyBag.endings);
     
    105158        );
    106159    }
    107 
    108     ThreadableBlobRegistry::registerBlobURL(m_internalURL, builder.finalize(), m_type);
     160    return builder.finalize();
     161}
     162
     163Blob::Blob(ScriptExecutionContext& context, Vector<BlobPartVariant>&& blobPartVariants, const BlobPropertyBag& propertyBag)
     164    : ActiveDOMObject(&context)
     165    , m_type(normalizedContentType(propertyBag.type))
     166    , m_internalURL(BlobInternalURL::create(buildBlobData(WTFMove(blobPartVariants), propertyBag), m_type))
     167{
    109168}
    110169
     
    113172    , m_type(contentType)
    114173    , m_size(data.size())
    115 {
    116     Vector<BlobPart> blobParts;
    117     blobParts.append(BlobPart(WTFMove(data)));
    118     m_internalURL = BlobURL::createInternalURL();
    119     ThreadableBlobRegistry::registerBlobURL(m_internalURL, WTFMove(blobParts), contentType);
     174    , m_internalURL(BlobInternalURL::create({ BlobPart(WTFMove(data)) }, contentType))
     175{
    120176}
    121177
    122178Blob::Blob(ReferencingExistingBlobConstructor, ScriptExecutionContext* context, const Blob& blob)
    123179    : ActiveDOMObject(context)
    124     , m_internalURL(BlobURL::createInternalURL())
    125180    , m_type(blob.type())
    126181    , m_size(blob.size())
    127 {
    128     ThreadableBlobRegistry::registerBlobURL(m_internalURL, { BlobPart(blob.url()) } , m_type);
     182    , m_internalURL(BlobInternalURL::create({ BlobPart(blob.url()) } , m_type))
     183{
    129184}
    130185
     
    133188    , m_type(normalizedContentType(type))
    134189    , m_size(size)
    135 {
    136     m_internalURL = BlobURL::createInternalURL();
    137     if (fileBackedPath.isEmpty())
    138         ThreadableBlobRegistry::registerBlobURL(nullptr, m_internalURL, srcURL);
    139     else
    140         ThreadableBlobRegistry::registerBlobURLOptionallyFileBacked(m_internalURL, srcURL, fileBackedPath, m_type);
     190    , m_internalURL(BlobInternalURL::createForDeserialization(srcURL, fileBackedPath, m_type))
     191{
    141192}
    142193
     
    144195    : ActiveDOMObject(context)
    145196    , m_type(normalizedContentType(type))
     197    , m_internalURL(BlobInternalURL::createForSlice(srcURL, start, end, m_type))
    146198    // m_size is not necessarily equal to end - start so we do not initialize it here.
    147199{
    148     m_internalURL = BlobURL::createInternalURL();
    149     ThreadableBlobRegistry::registerBlobURLForSlice(m_internalURL, srcURL, start, end, m_type);
    150200}
    151201
     
    154204    while (!m_blobLoaders.isEmpty())
    155205        (*m_blobLoaders.begin())->cancel();
    156 
    157     ThreadableBlobRegistry::unregisterBlobURL(m_internalURL);
     206}
     207
     208URL Blob::url() const
     209{
     210    return m_internalURL->url();
     211}
     212
     213Ref<Blob> Blob::slice(ScriptExecutionContext& context, long long start, long long end, const String& contentType) const
     214{
     215    auto blob = adoptRef(*new Blob(&context, m_internalURL->url(), start, end, contentType));
     216    blob->suspendIfNeeded();
     217    return blob;
    158218}
    159219
     
    163223        // FIXME: JavaScript cannot represent sizes as large as unsigned long long, we need to
    164224        // come up with an exception to throw if file size is not representable.
    165         unsigned long long actualSize = ThreadableBlobRegistry::blobSize(m_internalURL);
     225        unsigned long long actualSize = ThreadableBlobRegistry::blobSize(m_internalURL->url());
    166226        m_size = isInBounds<long long>(actualSize) ? actualSize : 0;
    167227    }
     
    336396}
    337397
     398Blob::Handle Blob::handle() const
     399{
     400    return Handle { m_internalURL.copyRef() };
     401}
     402
     403Blob::Handle::Handle(Ref<BlobInternalURL>&& internalURL)
     404    : m_internalURL(WTFMove(internalURL))
     405{ }
     406
     407Blob::Handle::~Handle() = default;
     408
     409Blob::Handle::Handle(Handle&&) = default;
     410Blob::Handle::Handle(const Handle&) = default;
     411
     412URL Blob::Handle::url() const
     413{
     414    return m_internalURL->url();
     415}
    338416
    339417} // namespace WebCore
  • trunk/Source/WebCore/fileapi/Blob.h

    r278702 r280547  
    5858
    5959using BlobPartVariant = Variant<RefPtr<JSC::ArrayBufferView>, RefPtr<JSC::ArrayBuffer>, RefPtr<Blob>, String>;
     60class BlobInternalURL;
    6061
    6162class Blob : public ScriptWrappable, public URLRegistrable, public RefCounted<Blob>, public ActiveDOMObject {
     
    9394    virtual ~Blob();
    9495
    95     const URL& url() const { return m_internalURL; }
     96    WEBCORE_EXPORT URL url() const;
    9697    const String& type() const { return m_type; }
    9798
     
    111112    URLRegistry& registry() const override;
    112113
    113     Ref<Blob> slice(ScriptExecutionContext& context, long long start, long long end, const String& contentType) const
    114     {
    115         auto blob = adoptRef(*new Blob(&context, m_internalURL, start, end, contentType));
    116         blob->suspendIfNeeded();
    117         return blob;
    118     }
     114    Ref<Blob> slice(ScriptExecutionContext&, long long start, long long end, const String& contentType) const;
    119115
    120116    void text(ScriptExecutionContext&, Ref<DeferredPromise>&&);
    121117    void arrayBuffer(ScriptExecutionContext&, Ref<DeferredPromise>&&);
    122118    ExceptionOr<Ref<ReadableStream>> stream(ScriptExecutionContext&);
     119
     120    class Handle {
     121    public:
     122        explicit Handle(Ref<BlobInternalURL>&&);
     123        ~Handle();
     124        Handle(Handle&&);
     125        Handle(const Handle&);
     126        URL url() const;
     127    private:
     128        Ref<BlobInternalURL> m_internalURL;
     129    };
     130
     131    // Keeping the handle alive will keep the Blob data alive (but not the Blob object).
     132    Handle handle() const;
    123133
    124134protected:
     
    145155    const char* activeDOMObjectName() const override;
    146156
     157    String m_type;
     158    mutable std::optional<unsigned long long> m_size;
     159
    147160    // This is an internal URL referring to the blob data associated with this object. It serves
    148161    // as an identifier for this blob. The internal URL is never used to source the blob's content
    149162    // into an HTML or for FileRead'ing, public blob URLs must be used for those purposes.
    150     URL m_internalURL;
     163    Ref<BlobInternalURL> m_internalURL;
    151164
    152     String m_type;
    153 
    154     mutable std::optional<unsigned long long> m_size;
    155165    HashSet<std::unique_ptr<BlobLoader>> m_blobLoaders;
    156166};
  • trunk/Source/WebCore/loader/EmptyClients.cpp

    r280053 r280547  
    11761176    void registerChannel(const SecurityOriginData&, const String&, BroadcastChannelIdentifier) final { }
    11771177    void unregisterChannel(const SecurityOriginData&, const String&, BroadcastChannelIdentifier) final { }
    1178     void postMessage(const SecurityOriginData&, const String&, BroadcastChannelIdentifier, Ref<SerializedScriptValue>&&) final { }
     1178    void postMessage(const SecurityOriginData&, const String&, BroadcastChannelIdentifier, Ref<SerializedScriptValue>&&, CompletionHandler<void()>&&) final { }
    11791179};
    11801180
  • trunk/Source/WebKit/ChangeLog

    r280542 r280547  
     12021-08-02  Chris Dumez  <cdumez@apple.com>
     2
     3        imported/w3c/web-platform-tests/webmessaging/broadcastchannel/blobs.html is a flaky failure since implementing BlobChannel
     4        https://bugs.webkit.org/show_bug.cgi?id=228168
     5        <rdar://problem/80922502>
     6
     7        Reviewed by Alex Christensen.
     8
     9        * NetworkProcess/NetworkBroadcastChannelRegistry.cpp:
     10        (WebKit::NetworkBroadcastChannelRegistry::postMessage):
     11        * NetworkProcess/NetworkBroadcastChannelRegistry.h:
     12        * NetworkProcess/NetworkBroadcastChannelRegistry.messages.in:
     13
     14        * Platform/IPC/HandleMessage.h:
     15        (IPC::handleMessageAsyncWantsConnection):
     16        handleMessageAsyncWantsConnection() had gotten out of sync with handleMessageAsync(). This was causing IPC decoding
     17        failures when using both "Async" and "WantsConnection" for the IPC message.
     18
     19        * WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.cpp:
     20        (WebKit::WebBroadcastChannelRegistry::postMessage):
     21        (WebKit::WebBroadcastChannelRegistry::postMessageToRemote):
     22        * WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.h:
     23        * WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.messages.in:
     24
    1252021-08-02  Per Arne Vollan  <pvollan@apple.com>
    226
  • trunk/Source/WebKit/NetworkProcess/NetworkBroadcastChannelRegistry.cpp

    r280419 r280547  
    2929#include "WebBroadcastChannelRegistryMessages.h"
    3030#include <WebCore/MessageWithMessagePorts.h>
     31#include <wtf/CallbackAggregator.h>
    3132
    3233namespace WebKit {
     
    5960}
    6061
    61 void NetworkBroadcastChannelRegistry::postMessage(IPC::Connection& connection, const WebCore::SecurityOriginData& origin, const String& name, WebCore::BroadcastChannelIdentifier source, WebCore::MessageWithMessagePorts&& message)
     62void NetworkBroadcastChannelRegistry::postMessage(IPC::Connection& connection, const WebCore::SecurityOriginData& origin, const String& name, WebCore::BroadcastChannelIdentifier source, WebCore::MessageWithMessagePorts&& message, CompletionHandler<void()>&& completionHandler)
    6263{
    6364    auto channelsForOriginIterator = m_broadcastChannels.find(origin);
    6465    ASSERT(channelsForOriginIterator != m_broadcastChannels.end());
    6566    if (channelsForOriginIterator == m_broadcastChannels.end())
    66         return;
     67        return completionHandler();
    6768    auto channelsForNameIterator = channelsForOriginIterator->value.find(name);
    6869    ASSERT(channelsForNameIterator != channelsForOriginIterator->value.end());
    6970    if (channelsForNameIterator == channelsForOriginIterator->value.end())
    70         return;
     71        return completionHandler();
    7172
     73    auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
    7274    GlobalBroadcastChannelIdentifier sourceGlobalChannelIdentifier { connection.uniqueID(), source };
    7375    for (auto& globalIdentifier : channelsForNameIterator->value) {
     
    7577            continue;
    7678
    77         IPC::Connection::send(globalIdentifier.connectionIdentifier, Messages::WebBroadcastChannelRegistry::PostMessageToRemote(globalIdentifier.channelIndentifierInProcess, message), 0);
     79        RefPtr connection = IPC::Connection::connection(globalIdentifier.connectionIdentifier);
     80        if (!connection)
     81            continue;
     82
     83        connection->sendWithAsyncReply(Messages::WebBroadcastChannelRegistry::PostMessageToRemote(globalIdentifier.channelIndentifierInProcess, message), [callbackAggregator] { }, 0);
    7884    }
    7985}
  • trunk/Source/WebKit/NetworkProcess/NetworkBroadcastChannelRegistry.h

    r279971 r280547  
    4848    void registerChannel(IPC::Connection&, const WebCore::SecurityOriginData&, const String& name, WebCore::BroadcastChannelIdentifier);
    4949    void unregisterChannel(IPC::Connection&, const WebCore::SecurityOriginData&, const String& name, WebCore::BroadcastChannelIdentifier);
    50     void postMessage(IPC::Connection&, const WebCore::SecurityOriginData&, const String& name, WebCore::BroadcastChannelIdentifier source, WebCore::MessageWithMessagePorts&&);
     50    void postMessage(IPC::Connection&, const WebCore::SecurityOriginData&, const String& name, WebCore::BroadcastChannelIdentifier source, WebCore::MessageWithMessagePorts&&, CompletionHandler<void()>&&);
    5151
    5252private:
  • trunk/Source/WebKit/NetworkProcess/NetworkBroadcastChannelRegistry.messages.in

    r279971 r280547  
    2424    RegisterChannel(struct WebCore::SecurityOriginData origin, String name, WebCore::BroadcastChannelIdentifier channelIdentifier) WantsConnection
    2525    UnregisterChannel(struct WebCore::SecurityOriginData origin, String name, WebCore::BroadcastChannelIdentifier channelIdentifier) WantsConnection
    26     PostMessage(struct WebCore::SecurityOriginData origin, String name, WebCore::BroadcastChannelIdentifier source, struct WebCore::MessageWithMessagePorts message) WantsConnection
     26    PostMessage(struct WebCore::SecurityOriginData origin, String name, WebCore::BroadcastChannelIdentifier source, struct WebCore::MessageWithMessagePorts message) -> () Async WantsConnection
    2727}
  • trunk/Source/WebKit/Platform/IPC/HandleMessage.h

    r278253 r280547  
    201201void handleMessageAsyncWantsConnection(Connection& connection, Decoder& decoder, C* object, MF function)
    202202{
    203     std::optional<typename CodingType<typename T::Arguments>::Type> arguments;
    204     decoder >> arguments;
    205     if (UNLIKELY(!arguments))
    206         return;
    207 
    208     typename T::AsyncReply completionHandler = [listenerID = decoder.destinationID(), connection = makeRef(connection)] (auto&&... args) mutable {
     203    std::optional<uint64_t> listenerID;
     204    decoder >> listenerID;
     205    if (!listenerID)
     206        return;
     207
     208    std::optional<typename CodingType<typename T::Arguments>::Type> arguments;
     209    decoder >> arguments;
     210    if (UNLIKELY(!arguments))
     211        return;
     212
     213    typename T::AsyncReply completionHandler = { [listenerID = *listenerID, connection = makeRef(connection)] (auto&&... args) mutable {
    209214        auto encoder = makeUniqueRef<Encoder>(T::asyncMessageReplyName(), listenerID);
    210215        T::send(WTFMove(encoder), WTFMove(connection), args...);
    211     };
     216    }, T::callbackThread };
    212217    callMemberFunction(connection, WTFMove(*arguments), WTFMove(completionHandler), object, function);
    213218}
  • trunk/Source/WebKit/WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.cpp

    r279971 r280547  
    5050}
    5151
    52 void WebBroadcastChannelRegistry::postMessage(const WebCore::SecurityOriginData& origin, const String& name, WebCore::BroadcastChannelIdentifier source, Ref<WebCore::SerializedScriptValue>&& message)
     52void WebBroadcastChannelRegistry::postMessage(const WebCore::SecurityOriginData& origin, const String& name, WebCore::BroadcastChannelIdentifier source, Ref<WebCore::SerializedScriptValue>&& message, CompletionHandler<void()>&& completionHandler)
    5353{
    54     networkProcessConnection().send(Messages::NetworkBroadcastChannelRegistry::PostMessage { origin, name, source, WebCore::MessageWithMessagePorts { WTFMove(message), { } } }, 0);
     54    networkProcessConnection().sendWithAsyncReply(Messages::NetworkBroadcastChannelRegistry::PostMessage { origin, name, source, WebCore::MessageWithMessagePorts { WTFMove(message), { } } }, WTFMove(completionHandler), 0);
    5555}
    5656
    57 void WebBroadcastChannelRegistry::postMessageToRemote(WebCore::BroadcastChannelIdentifier identifier, WebCore::MessageWithMessagePorts&& message)
     57void WebBroadcastChannelRegistry::postMessageToRemote(WebCore::BroadcastChannelIdentifier identifier, WebCore::MessageWithMessagePorts&& message, CompletionHandler<void()>&& completionHandler)
    5858{
    59     WebCore::BroadcastChannel::dispatchMessageTo(identifier, message.message.releaseNonNull());
     59    WebCore::BroadcastChannel::dispatchMessageTo(identifier, message.message.releaseNonNull(), WTFMove(completionHandler));
    6060}
    6161
  • trunk/Source/WebKit/WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.h

    r279971 r280547  
    4444    void registerChannel(const WebCore::SecurityOriginData&, const String& name, WebCore::BroadcastChannelIdentifier) final;
    4545    void unregisterChannel(const WebCore::SecurityOriginData&, const String& name, WebCore::BroadcastChannelIdentifier) final;
    46     void postMessage(const WebCore::SecurityOriginData&, const String& name, WebCore::BroadcastChannelIdentifier source, Ref<WebCore::SerializedScriptValue>&&) final;
     46    void postMessage(const WebCore::SecurityOriginData&, const String& name, WebCore::BroadcastChannelIdentifier source, Ref<WebCore::SerializedScriptValue>&&, CompletionHandler<void()>&&) final;
    4747
    4848    void didReceiveMessage(IPC::Connection&, IPC::Decoder&);
     
    5151    WebBroadcastChannelRegistry() = default;
    5252
    53     void postMessageToRemote(WebCore::BroadcastChannelIdentifier, WebCore::MessageWithMessagePorts&&);
     53    void postMessageToRemote(WebCore::BroadcastChannelIdentifier, WebCore::MessageWithMessagePorts&&, CompletionHandler<void()>&&);
    5454};
    5555
  • trunk/Source/WebKit/WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.messages.in

    r279971 r280547  
    2222
    2323messages -> WebBroadcastChannelRegistry {
    24     PostMessageToRemote(WebCore::BroadcastChannelIdentifier destination, struct WebCore::MessageWithMessagePorts message)
     24    PostMessageToRemote(WebCore::BroadcastChannelIdentifier destination, struct WebCore::MessageWithMessagePorts message) -> () Async
    2525}
  • trunk/Source/WebKitLegacy/ChangeLog

    r280053 r280547  
     12021-08-02  Chris Dumez  <cdumez@apple.com>
     2
     3        imported/w3c/web-platform-tests/webmessaging/broadcastchannel/blobs.html is a flaky failure since implementing BlobChannel
     4        https://bugs.webkit.org/show_bug.cgi?id=228168
     5        <rdar://problem/80922502>
     6
     7        Reviewed by Alex Christensen.
     8
     9        * WebCoreSupport/WebBroadcastChannelRegistry.cpp:
     10        (WebBroadcastChannelRegistry::postMessage):
     11        * WebCoreSupport/WebBroadcastChannelRegistry.h:
     12
    1132021-07-19  Sihui Liu  <sihui_liu@apple.com>
    214
  • trunk/Source/WebKitLegacy/WebCoreSupport/WebBroadcastChannelRegistry.cpp

    r279971 r280547  
    2828#include <WebCore/BroadcastChannel.h>
    2929#include <WebCore/SerializedScriptValue.h>
     30#include <wtf/CallbackAggregator.h>
    3031#include <wtf/HashMap.h>
    3132#include <wtf/NeverDestroyed.h>
     
    6667}
    6768
    68 void WebBroadcastChannelRegistry::postMessage(const WebCore::SecurityOriginData& origin, const String& name, WebCore::BroadcastChannelIdentifier source, Ref<WebCore::SerializedScriptValue>&& message)
     69void WebBroadcastChannelRegistry::postMessage(const WebCore::SecurityOriginData& origin, const String& name, WebCore::BroadcastChannelIdentifier source, Ref<WebCore::SerializedScriptValue>&& message, CompletionHandler<void()>&& completionHandler)
    6970{
    7071    ASSERT(isMainThread());
     72    auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
     73
    7174    auto channelsForOriginIterator = m_channels.find(origin);
    7275    ASSERT(channelsForOriginIterator != m_channels.end());
     
    7982        if (channelIdentifier == source)
    8083            continue;
    81         WebCore::BroadcastChannel::dispatchMessageTo(channelIdentifier, message.copyRef());
     84        WebCore::BroadcastChannel::dispatchMessageTo(channelIdentifier, message.copyRef(), [callbackAggregator] { });
    8285    }
    8386}
  • trunk/Source/WebKitLegacy/WebCoreSupport/WebBroadcastChannelRegistry.h

    r279971 r280547  
    3737    void registerChannel(const WebCore::SecurityOriginData&, const String& name, WebCore::BroadcastChannelIdentifier) final;
    3838    void unregisterChannel(const WebCore::SecurityOriginData&, const String& name, WebCore::BroadcastChannelIdentifier) final;
    39     void postMessage(const WebCore::SecurityOriginData&, const String& name, WebCore::BroadcastChannelIdentifier source, Ref<WebCore::SerializedScriptValue>&&) final;
     39    void postMessage(const WebCore::SecurityOriginData&, const String& name, WebCore::BroadcastChannelIdentifier source, Ref<WebCore::SerializedScriptValue>&&, CompletionHandler<void()>&&) final;
    4040
    4141private:
Note: See TracChangeset for help on using the changeset viewer.