Changeset 226336 in webkit


Ignore:
Timestamp:
Jan 2, 2018 2:42:16 PM (6 years ago)
Author:
beidson@apple.com
Message:

Identify MessagePorts by a globally unique MessagePortIdentifier.
https://bugs.webkit.org/show_bug.cgi?id=181172

Reviewed by Alex Christensen.

No new tests (Behavior change covered by all existing tests).

This cleans up the abstract MessagePortChannel interface to be in terms of identifiers
instead of actual MessagePort objects.

The identifiers are compounded with the current ProcessIdentifier meaning they are global
across all processes for the running UI process, enabling easy cross-process communication.

(Actual cross-process communication comes in a followup)

  • WebCore.xcodeproj/project.pbxproj:
  • dom/InProcessMessagePortChannel.cpp:

(WebCore::InProcessMessagePortChannel::createChannelBetweenPorts):
(WebCore::InProcessMessagePortChannel::isConnectedTo):
(WebCore::InProcessMessagePortChannel::entangleWithRemoteIfOpen):
(WebCore::InProcessMessagePortChannel::entangleIfOpen): Deleted.

  • dom/InProcessMessagePortChannel.h:
  • dom/MessageChannel.cpp:

(WebCore::MessageChannel::MessageChannel):
(WebCore::m_port2):

  • dom/MessagePort.cpp:

(WebCore::allMessagePortsLock):
(WebCore::MessagePort::ref const):
(WebCore::MessagePort::deref const):
(WebCore::MessagePort::existingMessagePortForIdentifier):
(WebCore::MessagePort::MessagePort):
(WebCore::MessagePort::~MessagePort):
(WebCore::MessagePort::postMessage):
(WebCore::MessagePort::entangleWithRemote):
(WebCore::MessagePort::entanglePorts):
(WebCore::MessagePort::entangle): Deleted.

  • dom/MessagePort.h:
  • dom/MessagePortChannel.h:
  • dom/MessagePortIdentifier.h: Added.

(WebCore::operator==):
(WebCore::MessagePortIdentifier::encode const):
(WebCore::MessagePortIdentifier::decode):
(WebCore::MessagePortIdentifier::hash const):
(WTF::MessagePortIdentifierHash::hash):
(WTF::MessagePortIdentifierHash::equal):
(WTF::HashTraits<WebCore::MessagePortIdentifier>::emptyValue):
(WTF::HashTraits<WebCore::MessagePortIdentifier>::constructDeletedValue):
(WTF::HashTraits<WebCore::MessagePortIdentifier>::isDeletedValue):

Location:
trunk/Source/WebCore
Files:
1 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r226333 r226336  
     12018-01-02  Brady Eidson  <beidson@apple.com>
     2
     3        Identify MessagePorts by a globally unique MessagePortIdentifier.
     4        https://bugs.webkit.org/show_bug.cgi?id=181172
     5
     6        Reviewed by Alex Christensen.
     7
     8        No new tests (Behavior change covered by all existing tests).
     9
     10        This cleans up the abstract MessagePortChannel interface to be in terms of identifiers
     11        instead of actual MessagePort objects.
     12       
     13        The identifiers are compounded with the current ProcessIdentifier meaning they are global
     14        across all processes for the running UI process, enabling easy cross-process communication.
     15       
     16        (Actual cross-process communication comes in a followup)
     17       
     18        * WebCore.xcodeproj/project.pbxproj:
     19       
     20        * dom/InProcessMessagePortChannel.cpp:
     21        (WebCore::InProcessMessagePortChannel::createChannelBetweenPorts):
     22        (WebCore::InProcessMessagePortChannel::isConnectedTo):
     23        (WebCore::InProcessMessagePortChannel::entangleWithRemoteIfOpen):
     24        (WebCore::InProcessMessagePortChannel::entangleIfOpen): Deleted.
     25        * dom/InProcessMessagePortChannel.h:
     26       
     27        * dom/MessageChannel.cpp:
     28        (WebCore::MessageChannel::MessageChannel):
     29        (WebCore::m_port2):
     30       
     31        * dom/MessagePort.cpp:
     32        (WebCore::allMessagePortsLock):
     33        (WebCore::MessagePort::ref const):
     34        (WebCore::MessagePort::deref const):
     35        (WebCore::MessagePort::existingMessagePortForIdentifier):
     36        (WebCore::MessagePort::MessagePort):
     37        (WebCore::MessagePort::~MessagePort):
     38        (WebCore::MessagePort::postMessage):
     39        (WebCore::MessagePort::entangleWithRemote):
     40        (WebCore::MessagePort::entanglePorts):
     41        (WebCore::MessagePort::entangle): Deleted.
     42        * dom/MessagePort.h:
     43       
     44        * dom/MessagePortChannel.h:
     45       
     46        * dom/MessagePortIdentifier.h: Added.
     47        (WebCore::operator==):
     48        (WebCore::MessagePortIdentifier::encode const):
     49        (WebCore::MessagePortIdentifier::decode):
     50        (WebCore::MessagePortIdentifier::hash const):
     51        (WTF::MessagePortIdentifierHash::hash):
     52        (WTF::MessagePortIdentifierHash::equal):
     53        (WTF::HashTraits<WebCore::MessagePortIdentifier>::emptyValue):
     54        (WTF::HashTraits<WebCore::MessagePortIdentifier>::constructDeletedValue):
     55        (WTF::HashTraits<WebCore::MessagePortIdentifier>::isDeletedValue):
     56
    1572018-01-02  Youenn Fablet  <youenn@apple.com>
    258
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r226332 r226336  
    14571457                51F645971F4A686F00B54DED /* SWServerRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F645941F4A684F00B54DED /* SWServerRegistration.h */; settings = {ATTRIBUTES = (Private, ); }; };
    14581458                51F645D51FECDBCE00B54DED /* Process.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F645D31FECDBC800B54DED /* Process.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1459                51F645E01FF4594E00B54DED /* MessagePortIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F645DE1FF4594B00B54DED /* MessagePortIdentifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
    14591460                51F798F01BE880E7008AE491 /* IDBIndexInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F798EC1BE880D3008AE491 /* IDBIndexInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
    14601461                51F886C01F32923100C193EF /* JSNavigatorServiceWorker.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F886BF1F32920700C193EF /* JSNavigatorServiceWorker.h */; };
     
    79277928                51F645D21FECDBC800B54DED /* Process.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Process.cpp; sourceTree = "<group>"; };
    79287929                51F645D31FECDBC800B54DED /* Process.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Process.h; sourceTree = "<group>"; };
     7930                51F645DE1FF4594B00B54DED /* MessagePortIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessagePortIdentifier.h; sourceTree = "<group>"; };
    79297931                51F6A3D50663BF04004D2919 /* HTMLCanvasElement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLCanvasElement.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
    79307932                51F6A3D60663BF04004D2919 /* HTMLCanvasElement.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = HTMLCanvasElement.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
     
    2551425516                                512B57BE1FE9902D000A1E5E /* MessagePortChannel.cpp */,
    2551525517                                41BF700A0FE86F49005E8DEC /* MessagePortChannel.h */,
     25518                                51F645DE1FF4594B00B54DED /* MessagePortIdentifier.h */,
    2551625519                                CB8CF0151A934B43000D510B /* Microtasks.cpp */,
    2551725520                                53B895AD19DC7C37009CAA93 /* Microtasks.h */,
     
    2853128534                                E1ADECBF0E76ACF1004A1A5E /* MessagePort.h in Headers */,
    2853228535                                41BF700C0FE86F49005E8DEC /* MessagePortChannel.h in Headers */,
     28536                                51F645E01FF4594E00B54DED /* MessagePortIdentifier.h in Headers */,
    2853328537                                53B895AF19DC7ED9009CAA93 /* Microtasks.h in Headers */,
    2853428538                                BC772C4F0C4EB3040083285F /* MIMETypeRegistry.h in Headers */,
  • trunk/Source/WebCore/dom/InProcessMessagePortChannel.cpp

    r226252 r226336  
    4343    channel2->m_entangledChannel = channel1.ptr();
    4444
    45     port1.entangle(WTFMove(channel2));
    46     port2.entangle(WTFMove(channel1));
     45    port1.entangleWithRemote(WTFMove(channel2));
     46    port2.entangleWithRemote(WTFMove(channel1));
    4747}
    4848
     
    8282}
    8383
    84 bool InProcessMessagePortChannel::isConnectedTo(MessagePort& port)
     84bool InProcessMessagePortChannel::isConnectedTo(const MessagePortIdentifier& identifier)
    8585{
    8686    // FIXME: What guarantees that the result remains the same after we release the lock?
    8787    Locker<Lock> locker(m_lock);
    88     return m_remotePort == &port;
     88    return m_remotePort && m_remotePort->identifier() == identifier;
    8989}
    9090
    91 bool InProcessMessagePortChannel::entangleIfOpen(MessagePort& port)
     91bool InProcessMessagePortChannel::entangleWithRemoteIfOpen(const MessagePortIdentifier& identifier)
    9292{
    9393    // We can't call member functions on our remote pair while holding our mutex or we'll deadlock,
     
    102102        return false;
    103103
    104     remote->setRemotePort(&port);
     104    auto entangledPort = MessagePort::existingMessagePortForIdentifier(identifier);
     105    ASSERT(entangledPort);
     106
     107    remote->setRemotePort(entangledPort.get());
    105108
    106109    return true;
  • trunk/Source/WebCore/dom/InProcessMessagePortChannel.h

    r226252 r226336  
    3939    void postMessageToRemote(Ref<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>&&) final;
    4040    Deque<std::unique_ptr<EventData>> takeAllMessagesFromRemote() final;
    41     bool isConnectedTo(MessagePort&) final;
    42     bool entangleIfOpen(MessagePort&) final;
     41    bool isConnectedTo(const MessagePortIdentifier&) final;
     42    bool entangleWithRemoteIfOpen(const MessagePortIdentifier&) final;
    4343    void disentangle() final;
    4444    bool hasPendingActivity() final;
  • trunk/Source/WebCore/dom/MessageChannel.cpp

    r226252 r226336  
    3434
    3535MessageChannel::MessageChannel(ScriptExecutionContext& context)
    36     : m_port1(MessagePort::create(context))
    37     , m_port2(MessagePort::create(context))
     36    : m_port1(MessagePort::create(context, { Process::identifier(), generateObjectIdentifier<MessagePortIdentifier::PortIdentifierType>() }))
     37    , m_port2(MessagePort::create(context, { Process::identifier(), generateObjectIdentifier<MessagePortIdentifier::PortIdentifierType>() }))
    3838{
    3939    MessagePortChannel::createChannelBetweenPorts(*m_port1, *m_port2);
  • trunk/Source/WebCore/dom/MessagePort.cpp

    r226252 r226336  
    3535namespace WebCore {
    3636
    37 MessagePort::MessagePort(ScriptExecutionContext& scriptExecutionContext)
     37static HashMap<MessagePortIdentifier, MessagePort*>& allMessagePorts()
     38{
     39    static NeverDestroyed<HashMap<MessagePortIdentifier, MessagePort*>> map;
     40    return map;
     41}
     42
     43static Lock& allMessagePortsLock()
     44{
     45    static NeverDestroyed<Lock> lock;
     46    return lock;
     47}
     48
     49void MessagePort::ref() const
     50{
     51    ++m_refCount;
     52}
     53
     54void MessagePort::deref() const
     55{
     56    // MessagePort::existingMessagePortForIdentifier() is unique in that it holds a raw pointer to a MessagePort
     57    // but might create a RefPtr from it.
     58    // If that happens on one thread at the same time that a MessagePort is being deref'ed and destroyed on a
     59    // different thread then Bad Things could happen.
     60    // This custom deref() function is designed to handle that contention by guaranteeing that nobody can be
     61    // creating a RefPtr inside existingMessagePortForIdentifier while the object is mid-deletion.
     62
     63    if (!--m_refCount) {
     64        Locker<Lock> locker(allMessagePortsLock());
     65
     66        if (m_refCount)
     67            return;
     68
     69        allMessagePorts().remove(m_identifier);
     70        delete this;
     71    }
     72}
     73
     74RefPtr<MessagePort> MessagePort::existingMessagePortForIdentifier(const MessagePortIdentifier& identifier)
     75{
     76    Locker<Lock> locker(allMessagePortsLock());
     77
     78    return allMessagePorts().get(identifier);
     79}
     80
     81MessagePort::MessagePort(ScriptExecutionContext& scriptExecutionContext, const MessagePortIdentifier& identifier)
    3882    : ActiveDOMObject(&scriptExecutionContext)
    39 {
     83    , m_identifier(identifier)
     84{
     85    Locker<Lock> locker(allMessagePortsLock());
     86    allMessagePorts().set(m_identifier, this);
     87
    4088    m_scriptExecutionContext->createdMessagePort(*this);
    4189    suspendIfNeeded();
     
    4694MessagePort::~MessagePort()
    4795{
     96    ASSERT(allMessagePortsLock().isLocked());
     97
    4898    close();
    4999    if (m_scriptExecutionContext)
     
    66116    if (!ports.isEmpty()) {
    67117        for (auto& dataPort : ports) {
    68             if (dataPort == this || m_entangledChannel->isConnectedTo(*dataPort))
     118            if (dataPort == this || m_entangledChannel->isConnectedTo(dataPort->identifier()))
    69119                return Exception { DataCloneError };
    70120        }
     121
    71122        auto disentangleResult = MessagePort::disentanglePorts(WTFMove(ports));
    72123        if (disentangleResult.hasException())
     
    124175}
    125176
    126 void MessagePort::entangle(RefPtr<MessagePortChannel>&& remote)
     177void MessagePort::entangleWithRemote(RefPtr<MessagePortChannel>&& remote)
    127178{
    128179    // Only invoked to set our initial entanglement.
     
    131182
    132183    // Don't entangle the ports if the channel is closed.
    133     if (remote->entangleIfOpen(*this))
     184    if (remote->entangleWithRemoteIfOpen(m_identifier))
    134185        m_entangledChannel = WTFMove(remote);
    135186}
     
    211262    portArray.reserveInitialCapacity(channels->size());
    212263    for (unsigned int i = 0; i < channels->size(); ++i) {
    213         auto port = MessagePort::create(context);
    214         port->entangle(WTFMove((*channels)[i]));
     264        auto port = MessagePort::create(context, { Process::identifier(), generateObjectIdentifier<MessagePortIdentifier::PortIdentifierType>() });
     265        port->entangleWithRemote(WTFMove((*channels)[i]));
    215266        portArray.uncheckedAppend(WTFMove(port));
    216267    }
  • trunk/Source/WebCore/dom/MessagePort.h

    r226252 r226336  
    3131#include "ExceptionOr.h"
    3232#include "MessagePortChannel.h"
     33#include "MessagePortIdentifier.h"
    3334
    3435namespace JSC {
     
    4243class Frame;
    4344
    44 class MessagePort final : public ThreadSafeRefCounted<MessagePort>, public ActiveDOMObject, public EventTargetWithInlineData {
     45class MessagePort final : public ActiveDOMObject, public EventTargetWithInlineData {
    4546public:
    46     static Ref<MessagePort> create(ScriptExecutionContext& scriptExecutionContext) { return adoptRef(*new MessagePort(scriptExecutionContext)); }
     47    static Ref<MessagePort> create(ScriptExecutionContext& scriptExecutionContext, const MessagePortIdentifier& identifier) { return adoptRef(*new MessagePort(scriptExecutionContext, identifier)); }
    4748    virtual ~MessagePort();
    4849
     
    5253    void close();
    5354
    54     void entangle(RefPtr<MessagePortChannel>&&);
     55    void entangleWithRemote(RefPtr<MessagePortChannel>&&);
    5556
    5657    // Returns nullptr if the passed-in vector is empty.
    5758    static ExceptionOr<std::unique_ptr<MessagePortChannelArray>> disentanglePorts(Vector<RefPtr<MessagePort>>&&);
    58 
    5959    static Vector<RefPtr<MessagePort>> entanglePorts(ScriptExecutionContext&, std::unique_ptr<MessagePortChannelArray>&&);
     60    static RefPtr<MessagePort> existingMessagePortForIdentifier(const MessagePortIdentifier&);
    6061
    6162    void messageAvailable();
     
    6970    MessagePort* locallyEntangledPort() const;
    7071
    71     using ThreadSafeRefCounted::ref;
    72     using ThreadSafeRefCounted::deref;
     72    const MessagePortIdentifier& identifier() const { return m_identifier; }
     73
     74    void ref() const;
     75    void deref() const;
    7376
    7477    // ActiveDOMObject
     
    8689
    8790private:
    88     explicit MessagePort(ScriptExecutionContext&);
     91    explicit MessagePort(ScriptExecutionContext&, const MessagePortIdentifier&);
    8992
    9093    bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) final;
     
    102105    bool m_started { false };
    103106    bool m_closed { false };
     107
     108    MessagePortIdentifier m_identifier;
     109
     110    mutable std::atomic<unsigned> m_refCount { 1 };
    104111};
    105112
  • trunk/Source/WebCore/dom/MessagePortChannel.h

    r226252 r226336  
    4444class ScriptExecutionContext;
    4545
     46struct MessagePortIdentifier;
     47
    4648// The overwhelmingly common case is sending a single port, so handle that efficiently with an inline buffer of size 1.
    4749typedef Vector<RefPtr<MessagePortChannel>, 1> MessagePortChannelArray;
     
    6567    static void createChannelBetweenPorts(MessagePort&, MessagePort&);
    6668
    67     void setRemotePort(MessagePort*);
    68 
    6969    virtual void postMessageToRemote(Ref<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>&&) = 0;
    7070    virtual Deque<std::unique_ptr<EventData>> takeAllMessagesFromRemote() = 0;
    71     virtual bool isConnectedTo(MessagePort&) = 0;
    72     virtual bool entangleIfOpen(MessagePort&) = 0;
     71    virtual bool isConnectedTo(const MessagePortIdentifier&) = 0;
     72    virtual bool entangleWithRemoteIfOpen(const MessagePortIdentifier&) = 0;
    7373    virtual void disentangle() = 0;
    7474    virtual bool hasPendingActivity() = 0;
Note: See TracChangeset for help on using the changeset viewer.