Title: [226336] trunk/Source/WebCore
Revision
226336
Author
beid...@apple.com
Date
2018-01-02 14:42:16 -0800 (Tue, 02 Jan 2018)

Log 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):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (226335 => 226336)


--- trunk/Source/WebCore/ChangeLog	2018-01-02 21:06:46 UTC (rev 226335)
+++ trunk/Source/WebCore/ChangeLog	2018-01-02 22:42:16 UTC (rev 226336)
@@ -1,3 +1,59 @@
+2018-01-02  Brady Eidson  <beid...@apple.com>
+
+        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):
+
 2018-01-02  Youenn Fablet  <you...@apple.com>
 
         Memory cache should not reuse resources with different credential fetch option

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (226335 => 226336)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2018-01-02 21:06:46 UTC (rev 226335)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2018-01-02 22:42:16 UTC (rev 226336)
@@ -1456,6 +1456,7 @@
 		51F6456A1F4539C000B54DED /* ServiceWorkerJobType.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F645651F45399F00B54DED /* ServiceWorkerJobType.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		51F645971F4A686F00B54DED /* SWServerRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F645941F4A684F00B54DED /* SWServerRegistration.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		51F645D51FECDBCE00B54DED /* Process.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F645D31FECDBC800B54DED /* Process.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		51F645E01FF4594E00B54DED /* MessagePortIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F645DE1FF4594B00B54DED /* MessagePortIdentifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		51F798F01BE880E7008AE491 /* IDBIndexInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F798EC1BE880D3008AE491 /* IDBIndexInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		51F886C01F32923100C193EF /* JSNavigatorServiceWorker.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F886BF1F32920700C193EF /* JSNavigatorServiceWorker.h */; };
 		51FA2D78152132B300C1BA0B /* DOMWindowExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 517FBA18151AA71B00B57959 /* DOMWindowExtension.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -7926,6 +7927,7 @@
 		51F645A31F4C000C00B54DED /* ExceptionData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExceptionData.cpp; sourceTree = "<group>"; };
 		51F645D21FECDBC800B54DED /* Process.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Process.cpp; sourceTree = "<group>"; };
 		51F645D31FECDBC800B54DED /* Process.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Process.h; sourceTree = "<group>"; };
+		51F645DE1FF4594B00B54DED /* MessagePortIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessagePortIdentifier.h; sourceTree = "<group>"; };
 		51F6A3D50663BF04004D2919 /* HTMLCanvasElement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLCanvasElement.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
 		51F6A3D60663BF04004D2919 /* HTMLCanvasElement.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = HTMLCanvasElement.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
 		51F798EB1BE880D3008AE491 /* IDBIndexInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBIndexInfo.cpp; sourceTree = "<group>"; };
@@ -25513,6 +25515,7 @@
 				E1ADECC60E76AD1F004A1A5E /* MessagePort.idl */,
 				512B57BE1FE9902D000A1E5E /* MessagePortChannel.cpp */,
 				41BF700A0FE86F49005E8DEC /* MessagePortChannel.h */,
+				51F645DE1FF4594B00B54DED /* MessagePortIdentifier.h */,
 				CB8CF0151A934B43000D510B /* Microtasks.cpp */,
 				53B895AD19DC7C37009CAA93 /* Microtasks.h */,
 				E38D06091F8E811900649CF2 /* ModuleFetchParameters.h */,
@@ -28530,6 +28533,7 @@
 				75793E840D0CE0B3007FC0AC /* MessageEvent.h in Headers */,
 				E1ADECBF0E76ACF1004A1A5E /* MessagePort.h in Headers */,
 				41BF700C0FE86F49005E8DEC /* MessagePortChannel.h in Headers */,
+				51F645E01FF4594E00B54DED /* MessagePortIdentifier.h in Headers */,
 				53B895AF19DC7ED9009CAA93 /* Microtasks.h in Headers */,
 				BC772C4F0C4EB3040083285F /* MIMETypeRegistry.h in Headers */,
 				52F10866162B6DA8009AC81E /* MixedContentChecker.h in Headers */,

Modified: trunk/Source/WebCore/dom/InProcessMessagePortChannel.cpp (226335 => 226336)


--- trunk/Source/WebCore/dom/InProcessMessagePortChannel.cpp	2018-01-02 21:06:46 UTC (rev 226335)
+++ trunk/Source/WebCore/dom/InProcessMessagePortChannel.cpp	2018-01-02 22:42:16 UTC (rev 226336)
@@ -42,8 +42,8 @@
     channel1->m_entangledChannel = channel2.ptr();
     channel2->m_entangledChannel = channel1.ptr();
 
-    port1.entangle(WTFMove(channel2));
-    port2.entangle(WTFMove(channel1));
+    port1.entangleWithRemote(WTFMove(channel2));
+    port2.entangleWithRemote(WTFMove(channel1));
 }
 
 Ref<InProcessMessagePortChannel> InProcessMessagePortChannel::create(MessagePortQueue& incoming, MessagePortQueue& outgoing)
@@ -81,14 +81,14 @@
     return m_incomingQueue->takeAllMessages();
 }
 
-bool InProcessMessagePortChannel::isConnectedTo(MessagePort& port)
+bool InProcessMessagePortChannel::isConnectedTo(const MessagePortIdentifier& identifier)
 {
     // FIXME: What guarantees that the result remains the same after we release the lock?
     Locker<Lock> locker(m_lock);
-    return m_remotePort == &port;
+    return m_remotePort && m_remotePort->identifier() == identifier;
 }
 
-bool InProcessMessagePortChannel::entangleIfOpen(MessagePort& port)
+bool InProcessMessagePortChannel::entangleWithRemoteIfOpen(const MessagePortIdentifier& identifier)
 {
     // We can't call member functions on our remote pair while holding our mutex or we'll deadlock,
     // but we need to guard against the remote port getting closed/freed, so create a standalone reference.
@@ -101,8 +101,11 @@
     if (!remote)
         return false;
 
-    remote->setRemotePort(&port);
+    auto entangledPort = MessagePort::existingMessagePortForIdentifier(identifier);
+    ASSERT(entangledPort);
 
+    remote->setRemotePort(entangledPort.get());
+
     return true;
 }
 

Modified: trunk/Source/WebCore/dom/InProcessMessagePortChannel.h (226335 => 226336)


--- trunk/Source/WebCore/dom/InProcessMessagePortChannel.h	2018-01-02 21:06:46 UTC (rev 226335)
+++ trunk/Source/WebCore/dom/InProcessMessagePortChannel.h	2018-01-02 22:42:16 UTC (rev 226336)
@@ -38,8 +38,8 @@
 
     void postMessageToRemote(Ref<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>&&) final;
     Deque<std::unique_ptr<EventData>> takeAllMessagesFromRemote() final;
-    bool isConnectedTo(MessagePort&) final;
-    bool entangleIfOpen(MessagePort&) final;
+    bool isConnectedTo(const MessagePortIdentifier&) final;
+    bool entangleWithRemoteIfOpen(const MessagePortIdentifier&) final;
     void disentangle() final;
     bool hasPendingActivity() final;
     MessagePort* locallyEntangledPort(const ScriptExecutionContext*) final;

Modified: trunk/Source/WebCore/dom/MessageChannel.cpp (226335 => 226336)


--- trunk/Source/WebCore/dom/MessageChannel.cpp	2018-01-02 21:06:46 UTC (rev 226335)
+++ trunk/Source/WebCore/dom/MessageChannel.cpp	2018-01-02 22:42:16 UTC (rev 226336)
@@ -33,8 +33,8 @@
 namespace WebCore {
 
 MessageChannel::MessageChannel(ScriptExecutionContext& context)
-    : m_port1(MessagePort::create(context))
-    , m_port2(MessagePort::create(context))
+    : m_port1(MessagePort::create(context, { Process::identifier(), generateObjectIdentifier<MessagePortIdentifier::PortIdentifierType>() }))
+    , m_port2(MessagePort::create(context, { Process::identifier(), generateObjectIdentifier<MessagePortIdentifier::PortIdentifierType>() }))
 {
     MessagePortChannel::createChannelBetweenPorts(*m_port1, *m_port2);
 }

Modified: trunk/Source/WebCore/dom/MessagePort.cpp (226335 => 226336)


--- trunk/Source/WebCore/dom/MessagePort.cpp	2018-01-02 21:06:46 UTC (rev 226335)
+++ trunk/Source/WebCore/dom/MessagePort.cpp	2018-01-02 22:42:16 UTC (rev 226336)
@@ -34,9 +34,57 @@
 
 namespace WebCore {
 
-MessagePort::MessagePort(ScriptExecutionContext& scriptExecutionContext)
+static HashMap<MessagePortIdentifier, MessagePort*>& allMessagePorts()
+{
+    static NeverDestroyed<HashMap<MessagePortIdentifier, MessagePort*>> map;
+    return map;
+}
+
+static Lock& allMessagePortsLock()
+{
+    static NeverDestroyed<Lock> lock;
+    return lock;
+}
+
+void MessagePort::ref() const
+{
+    ++m_refCount;
+}
+
+void MessagePort::deref() const
+{
+    // MessagePort::existingMessagePortForIdentifier() is unique in that it holds a raw pointer to a MessagePort
+    // but might create a RefPtr from it.
+    // If that happens on one thread at the same time that a MessagePort is being deref'ed and destroyed on a
+    // different thread then Bad Things could happen.
+    // This custom deref() function is designed to handle that contention by guaranteeing that nobody can be
+    // creating a RefPtr inside existingMessagePortForIdentifier while the object is mid-deletion.
+
+    if (!--m_refCount) {
+        Locker<Lock> locker(allMessagePortsLock());
+
+        if (m_refCount)
+            return;
+
+        allMessagePorts().remove(m_identifier);
+        delete this;
+    }
+}
+
+RefPtr<MessagePort> MessagePort::existingMessagePortForIdentifier(const MessagePortIdentifier& identifier)
+{
+    Locker<Lock> locker(allMessagePortsLock());
+
+    return allMessagePorts().get(identifier);
+}
+
+MessagePort::MessagePort(ScriptExecutionContext& scriptExecutionContext, const MessagePortIdentifier& identifier)
     : ActiveDOMObject(&scriptExecutionContext)
+    , m_identifier(identifier)
 {
+    Locker<Lock> locker(allMessagePortsLock());
+    allMessagePorts().set(m_identifier, this);
+
     m_scriptExecutionContext->createdMessagePort(*this);
     suspendIfNeeded();
 
@@ -45,6 +93,8 @@
 
 MessagePort::~MessagePort()
 {
+    ASSERT(allMessagePortsLock().isLocked());
+
     close();
     if (m_scriptExecutionContext)
         m_scriptExecutionContext->destroyedMessagePort(*this);
@@ -65,9 +115,10 @@
     // Make sure we aren't connected to any of the passed-in ports.
     if (!ports.isEmpty()) {
         for (auto& dataPort : ports) {
-            if (dataPort == this || m_entangledChannel->isConnectedTo(*dataPort))
+            if (dataPort == this || m_entangledChannel->isConnectedTo(dataPort->identifier()))
                 return Exception { DataCloneError };
         }
+
         auto disentangleResult = MessagePort::disentanglePorts(WTFMove(ports));
         if (disentangleResult.hasException())
             return disentangleResult.releaseException();
@@ -123,7 +174,7 @@
     m_closed = true;
 }
 
-void MessagePort::entangle(RefPtr<MessagePortChannel>&& remote)
+void MessagePort::entangleWithRemote(RefPtr<MessagePortChannel>&& remote)
 {
     // Only invoked to set our initial entanglement.
     ASSERT(!m_entangledChannel);
@@ -130,7 +181,7 @@
     ASSERT(m_scriptExecutionContext);
 
     // Don't entangle the ports if the channel is closed.
-    if (remote->entangleIfOpen(*this))
+    if (remote->entangleWithRemoteIfOpen(m_identifier))
         m_entangledChannel = WTFMove(remote);
 }
 
@@ -210,8 +261,8 @@
     Vector<RefPtr<MessagePort>> portArray;
     portArray.reserveInitialCapacity(channels->size());
     for (unsigned int i = 0; i < channels->size(); ++i) {
-        auto port = MessagePort::create(context);
-        port->entangle(WTFMove((*channels)[i]));
+        auto port = MessagePort::create(context, { Process::identifier(), generateObjectIdentifier<MessagePortIdentifier::PortIdentifierType>() });
+        port->entangleWithRemote(WTFMove((*channels)[i]));
         portArray.uncheckedAppend(WTFMove(port));
     }
     return portArray;

Modified: trunk/Source/WebCore/dom/MessagePort.h (226335 => 226336)


--- trunk/Source/WebCore/dom/MessagePort.h	2018-01-02 21:06:46 UTC (rev 226335)
+++ trunk/Source/WebCore/dom/MessagePort.h	2018-01-02 22:42:16 UTC (rev 226336)
@@ -30,6 +30,7 @@
 #include "EventTarget.h"
 #include "ExceptionOr.h"
 #include "MessagePortChannel.h"
+#include "MessagePortIdentifier.h"
 
 namespace JSC {
 class ExecState;
@@ -41,9 +42,9 @@
 
 class Frame;
 
-class MessagePort final : public ThreadSafeRefCounted<MessagePort>, public ActiveDOMObject, public EventTargetWithInlineData {
+class MessagePort final : public ActiveDOMObject, public EventTargetWithInlineData {
 public:
-    static Ref<MessagePort> create(ScriptExecutionContext& scriptExecutionContext) { return adoptRef(*new MessagePort(scriptExecutionContext)); }
+    static Ref<MessagePort> create(ScriptExecutionContext& scriptExecutionContext, const MessagePortIdentifier& identifier) { return adoptRef(*new MessagePort(scriptExecutionContext, identifier)); }
     virtual ~MessagePort();
 
     ExceptionOr<void> postMessage(JSC::ExecState&, JSC::JSValue message, Vector<JSC::Strong<JSC::JSObject>>&&);
@@ -51,12 +52,12 @@
     void start();
     void close();
 
-    void entangle(RefPtr<MessagePortChannel>&&);
+    void entangleWithRemote(RefPtr<MessagePortChannel>&&);
 
     // Returns nullptr if the passed-in vector is empty.
     static ExceptionOr<std::unique_ptr<MessagePortChannelArray>> disentanglePorts(Vector<RefPtr<MessagePort>>&&);
-
     static Vector<RefPtr<MessagePort>> entanglePorts(ScriptExecutionContext&, std::unique_ptr<MessagePortChannelArray>&&);
+    static RefPtr<MessagePort> existingMessagePortForIdentifier(const MessagePortIdentifier&);
 
     void messageAvailable();
     bool started() const { return m_started; }
@@ -68,9 +69,11 @@
     // of the remote port (since it may live cross-process) - those platforms may always return null.
     MessagePort* locallyEntangledPort() const;
 
-    using ThreadSafeRefCounted::ref;
-    using ThreadSafeRefCounted::deref;
+    const MessagePortIdentifier& identifier() const { return m_identifier; }
 
+    void ref() const;
+    void deref() const;
+
     // ActiveDOMObject
     const char* activeDOMObjectName() const final;
     bool canSuspendForDocumentSuspension() const final;
@@ -85,7 +88,7 @@
     void derefEventTarget() final { deref(); }
 
 private:
-    explicit MessagePort(ScriptExecutionContext&);
+    explicit MessagePort(ScriptExecutionContext&, const MessagePortIdentifier&);
 
     bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) final;
 
@@ -101,6 +104,10 @@
     RefPtr<MessagePort> m_messageProtector;
     bool m_started { false };
     bool m_closed { false };
+
+    MessagePortIdentifier m_identifier;
+
+    mutable std::atomic<unsigned> m_refCount { 1 };
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/dom/MessagePortChannel.h (226335 => 226336)


--- trunk/Source/WebCore/dom/MessagePortChannel.h	2018-01-02 21:06:46 UTC (rev 226335)
+++ trunk/Source/WebCore/dom/MessagePortChannel.h	2018-01-02 22:42:16 UTC (rev 226336)
@@ -43,6 +43,8 @@
 class MessagePortChannel;
 class ScriptExecutionContext;
 
+struct MessagePortIdentifier;
+
 // The overwhelmingly common case is sending a single port, so handle that efficiently with an inline buffer of size 1.
 typedef Vector<RefPtr<MessagePortChannel>, 1> MessagePortChannelArray;
 
@@ -64,12 +66,10 @@
 
     static void createChannelBetweenPorts(MessagePort&, MessagePort&);
 
-    void setRemotePort(MessagePort*);
-
     virtual void postMessageToRemote(Ref<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>&&) = 0;
     virtual Deque<std::unique_ptr<EventData>> takeAllMessagesFromRemote() = 0;
-    virtual bool isConnectedTo(MessagePort&) = 0;
-    virtual bool entangleIfOpen(MessagePort&) = 0;
+    virtual bool isConnectedTo(const MessagePortIdentifier&) = 0;
+    virtual bool entangleWithRemoteIfOpen(const MessagePortIdentifier&) = 0;
     virtual void disentangle() = 0;
     virtual bool hasPendingActivity() = 0;
     virtual MessagePort* locallyEntangledPort(const ScriptExecutionContext*) = 0;

Added: trunk/Source/WebCore/dom/MessagePortIdentifier.h (0 => 226336)


--- trunk/Source/WebCore/dom/MessagePortIdentifier.h	                        (rev 0)
+++ trunk/Source/WebCore/dom/MessagePortIdentifier.h	2018-01-02 22:42:16 UTC (rev 226336)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "Process.h"
+#include <wtf/Hasher.h>
+
+namespace WebCore {
+
+struct MessagePortIdentifier {
+    ProcessIdentifier processIdentifier;
+    enum PortIdentifierType { };
+    ObjectIdentifier<PortIdentifierType> portIdentifier;
+
+    unsigned hash() const;
+
+    template<class Encoder> void encode(Encoder&) const;
+    template<class Decoder> static std::optional<MessagePortIdentifier> decode(Decoder&);
+};
+
+inline bool operator==(const MessagePortIdentifier& a, const MessagePortIdentifier& b)
+{
+    return a.processIdentifier == b.processIdentifier &&  a.portIdentifier == b.portIdentifier;
+}
+
+template<class Encoder>
+void MessagePortIdentifier::encode(Encoder& encoder) const
+{
+    encoder << processIdentifier << portIdentifier;
+}
+
+template<class Decoder>
+std::optional<MessagePortIdentifier> MessagePortIdentifier::decode(Decoder& decoder)
+{
+    std::optional<ProcessIdentifier> processIdentifier;
+    decoder >> processIdentifier;
+    if (!processIdentifier)
+        return std::nullopt;
+
+    std::optional<ObjectIdentifier<PortIdentifierType>> portIdentifier;
+    decoder >> portIdentifier;
+    if (!portIdentifier)
+        return std::nullopt;
+
+    return { { WTFMove(*processIdentifier), WTFMove(*portIdentifier) } };
+}
+
+inline unsigned MessagePortIdentifier::hash() const
+{
+    return computeHash(processIdentifier.toUInt64(), portIdentifier.toUInt64());
+}
+
+} // namespace WebCore
+
+namespace WTF {
+
+struct MessagePortIdentifierHash {
+    static unsigned hash(const WebCore::MessagePortIdentifier& key) { return key.hash(); }
+    static bool equal(const WebCore::MessagePortIdentifier& a, const WebCore::MessagePortIdentifier& b) { return a == b; }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+template<> struct HashTraits<WebCore::MessagePortIdentifier> : GenericHashTraits<WebCore::MessagePortIdentifier> {
+    static WebCore::MessagePortIdentifier emptyValue() { return { }; }
+
+    static void constructDeletedValue(WebCore::MessagePortIdentifier& slot) { slot.processIdentifier = makeObjectIdentifier<WebCore::ProcessIdentifierType>(std::numeric_limits<uint64_t>::max()); }
+
+    static bool isDeletedValue(const WebCore::MessagePortIdentifier& slot) { return slot.processIdentifier.toUInt64() == std::numeric_limits<uint64_t>::max(); }
+};
+
+template<> struct DefaultHash<WebCore::MessagePortIdentifier> {
+    typedef MessagePortIdentifierHash Hash;
+};
+
+} // namespace WTF
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to