Make in-process MessagePorts be (mostly) asynchronous
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 19 Jan 2018 06:33:11 +0000 (06:33 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 19 Jan 2018 06:33:11 +0000 (06:33 +0000)
https://bugs.webkit.org/show_bug.cgi?id=181454

Reviewed by Alex Christensen.

No new tests (Covered *brutally* by existing tests)

Part of making MessagePorts be a thing we can pass across processes is making them work async.

The existing "MessagePortChannel" method of abstraction was not cut out for this.
This patch gets rid of MessagePortChannel and adds a new MessagePortChannelProvider abstraction.
It then gets the new machinery working in-process (with some pieces of out-of-process in place)

One synchronous behavior this patch maintains is the hasPendingActivity() check used to support GC.
That will (creatively) be made async in the next followup.

More generally from MessagePorts, this patch also adds a "MessageWithMessagePorts" object to be used
with all forms of postMessage(). Much better.

* CMakeLists.txt:
* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:

* dom/InProcessMessagePortChannel.cpp: Removed.
* dom/InProcessMessagePortChannel.h: Removed.
* dom/MessagePortChannel.cpp: Removed.
* dom/MessagePortChannel.h: Removed.

* dom/MessageChannel.cpp:
(WebCore::MessageChannel::create):
(WebCore::MessageChannel::MessageChannel):
(WebCore::m_port2): Deleted.
* dom/MessageChannel.h:
(WebCore::MessageChannel::create): Deleted.

* dom/MessagePort.cpp:
(WebCore::MessagePort::create):
(WebCore::MessagePort::MessagePort):
(WebCore::MessagePort::~MessagePort):
(WebCore::MessagePort::entangle):
(WebCore::MessagePort::postMessage):
(WebCore::MessagePort::disentangle):
(WebCore::MessagePort::messageAvailable):
(WebCore::MessagePort::start):
(WebCore::MessagePort::close):
(WebCore::MessagePort::contextDestroyed):
(WebCore::MessagePort::dispatchMessages):
(WebCore::MessagePort::hasPendingActivity const):
(WebCore::MessagePort::locallyEntangledPort const):
(WebCore::MessagePort::disentanglePorts):
(WebCore::MessagePort::entanglePorts):
(WebCore::MessagePort::entangleWithRemote): Deleted.
* dom/MessagePort.h:

* dom/MessagePortIdentifier.h:
(WebCore::MessagePortIdentifier::logString const):

* dom/ScriptExecutionContext.cpp:
(WebCore::ScriptExecutionContext::processMessageWithMessagePortsSoon):
(WebCore::ScriptExecutionContext::dispatchMessagePortEvents):
(WebCore::ScriptExecutionContext::processMessagePortMessagesSoon): Deleted.
* dom/ScriptExecutionContext.h:

Add a single object that represents two intertwined ports, tracks their pending
messages, tracks which process they're in, etc etc:
* dom/messageports/MessagePortChannel.cpp: Added.
(WebCore::MessagePortChannel::create):
(WebCore::MessagePortChannel::MessagePortChannel):
(WebCore::MessagePortChannel::~MessagePortChannel):
(WebCore::MessagePortChannel::includesPort):
(WebCore::MessagePortChannel::entanglePortWithProcess):
(WebCore::MessagePortChannel::disentanglePort):
(WebCore::MessagePortChannel::closePort):
(WebCore::MessagePortChannel::postMessageToRemote):
(WebCore::MessagePortChannel::takeAllMessagesForPort):
(WebCore::MessagePortChannel::hasAnyMessagesPendingOrInFlight const):
* dom/messageports/MessagePortChannel.h: Added.
(WebCore::MessagePortChannel::port1 const):
(WebCore::MessagePortChannel::port2 const):
(WebCore::MessagePortChannel::logString const):

Abstraction for creating and operating on MessagePorts in a potentially cross-process way:
* dom/messageports/MessagePortChannelProvider.cpp: Added.
(WebCore::MessagePortChannelProvider::singleton):
(WebCore::MessagePortChannelProvider::setSharedProvider):
* dom/messageports/MessagePortChannelProvider.h: Added.
(WebCore::MessagePortChannelProvider::~MessagePortChannelProvider):

Adds a concrete implementation of that provider to be used in-process (e.g. WK1):
* dom/messageports/MessagePortChannelProviderImpl.cpp: Added.
(WebCore::MessagePortChannelProviderImpl::~MessagePortChannelProviderImpl):
(WebCore::MessagePortChannelProviderImpl::performActionOnAppropriateThread):
(WebCore::MessagePortChannelProviderImpl::createNewMessagePortChannel):
(WebCore::MessagePortChannelProviderImpl::entangleLocalPortInThisProcessToRemote):
(WebCore::MessagePortChannelProviderImpl::messagePortDisentangled):
(WebCore::MessagePortChannelProviderImpl::messagePortClosed):
(WebCore::MessagePortChannelProviderImpl::postMessageToRemote):
(WebCore::MessagePortChannelProviderImpl::takeAllMessagesForPort):
(WebCore::MessagePortChannelProviderImpl::hasMessagesForPorts_temporarySync):
* dom/messageports/MessagePortChannelProviderImpl.h: Added.

Adds a main thread object to handle the set of all MessagePortChannels that are open.
For now it lives in the WebProcess, but for out-of-process it will live in the UIProcess:
* dom/messageports/MessagePortChannelRegistry.cpp: Added.
(WebCore::MessagePortChannelRegistry::~MessagePortChannelRegistry):
(WebCore::MessagePortChannelRegistry::didCreateMessagePortChannel):
(WebCore::MessagePortChannelRegistry::messagePortChannelCreated):
(WebCore::MessagePortChannelRegistry::messagePortChannelDestroyed):
(WebCore::MessagePortChannelRegistry::didEntangleLocalToRemote):
(WebCore::MessagePortChannelRegistry::didDisentangleMessagePort):
(WebCore::MessagePortChannelRegistry::didCloseMessagePort):
(WebCore::MessagePortChannelRegistry::didPostMessageToRemote):
(WebCore::MessagePortChannelRegistry::takeAllMessagesForPort):
(WebCore::MessagePortChannelRegistry::hasMessagesForPorts_temporarySync): This is named against style
  and weird on purpose - to call attention to how bad it is and how it's temporary.
(WebCore::MessagePortChannelRegistry::existingChannelContainingPort):
* dom/messageports/MessagePortChannelRegistry.h: Added.

Add an object that represents a "SerializedScriptValue for the message payload and the ports
that are being transferred along with that payload". This is used in all forms of postMessage():
* dom/messageports/MessageWithMessagePorts.cpp: Added.
* dom/messageports/MessageWithMessagePorts.h: Added.

* page/DOMWindow.cpp:
(WebCore::PostMessageTimer::PostMessageTimer):
(WebCore::PostMessageTimer::event):
(WebCore::DOMWindow::postMessage):

* platform/Logging.h:

* workers/DedicatedWorkerGlobalScope.cpp:
(WebCore::DedicatedWorkerGlobalScope::postMessage):

* workers/Worker.cpp:
(WebCore::Worker::postMessage):

* workers/WorkerGlobalScopeProxy.h:

* workers/WorkerMessagingProxy.cpp:
(WebCore::WorkerMessagingProxy::postMessageToWorkerObject):
(WebCore::WorkerMessagingProxy::postMessageToWorkerGlobalScope):
* workers/WorkerMessagingProxy.h:

* workers/WorkerObjectProxy.h:

* workers/service/ServiceWorker.cpp:
(WebCore::ServiceWorker::postMessage):

* workers/service/ServiceWorkerClient.cpp:
(WebCore::ServiceWorkerClient::postMessage):

* workers/service/context/SWContextManager.cpp:
(WebCore::SWContextManager::postMessageToServiceWorker):

* workers/service/context/ServiceWorkerThread.cpp:
(WebCore::fireMessageEvent):
(WebCore::ServiceWorkerThread::postMessageToServiceWorker):
* workers/service/context/ServiceWorkerThread.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@227190 268f45cc-cd09-0410-ab3c-d52691b4dbfc

38 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/dom/InProcessMessagePortChannel.cpp [deleted file]
Source/WebCore/dom/InProcessMessagePortChannel.h [deleted file]
Source/WebCore/dom/MessageChannel.cpp
Source/WebCore/dom/MessageChannel.h
Source/WebCore/dom/MessagePort.cpp
Source/WebCore/dom/MessagePort.h
Source/WebCore/dom/MessagePortChannel.cpp [deleted file]
Source/WebCore/dom/MessagePortChannel.h [deleted file]
Source/WebCore/dom/MessagePortIdentifier.h
Source/WebCore/dom/ScriptExecutionContext.cpp
Source/WebCore/dom/ScriptExecutionContext.h
Source/WebCore/dom/messageports/MessagePortChannel.cpp [new file with mode: 0644]
Source/WebCore/dom/messageports/MessagePortChannel.h [new file with mode: 0644]
Source/WebCore/dom/messageports/MessagePortChannelProvider.cpp [new file with mode: 0644]
Source/WebCore/dom/messageports/MessagePortChannelProvider.h [new file with mode: 0644]
Source/WebCore/dom/messageports/MessagePortChannelProviderImpl.cpp [new file with mode: 0644]
Source/WebCore/dom/messageports/MessagePortChannelProviderImpl.h [new file with mode: 0644]
Source/WebCore/dom/messageports/MessagePortChannelRegistry.cpp [new file with mode: 0644]
Source/WebCore/dom/messageports/MessagePortChannelRegistry.h [new file with mode: 0644]
Source/WebCore/dom/messageports/MessageWithMessagePorts.cpp [new file with mode: 0644]
Source/WebCore/dom/messageports/MessageWithMessagePorts.h [new file with mode: 0644]
Source/WebCore/page/DOMWindow.cpp
Source/WebCore/platform/Logging.h
Source/WebCore/workers/DedicatedWorkerGlobalScope.cpp
Source/WebCore/workers/Worker.cpp
Source/WebCore/workers/WorkerGlobalScopeProxy.h
Source/WebCore/workers/WorkerMessagingProxy.cpp
Source/WebCore/workers/WorkerMessagingProxy.h
Source/WebCore/workers/WorkerObjectProxy.h
Source/WebCore/workers/service/ServiceWorker.cpp
Source/WebCore/workers/service/ServiceWorkerClient.cpp
Source/WebCore/workers/service/context/SWContextManager.cpp
Source/WebCore/workers/service/context/ServiceWorkerThread.cpp
Source/WebCore/workers/service/context/ServiceWorkerThread.h

index d59345a..a82bef9 100644 (file)
@@ -68,6 +68,7 @@ set(WebCore_INCLUDE_DIRECTORIES
     "${WEBCORE_DIR}/cssjit"
     "${WEBCORE_DIR}/dom"
     "${WEBCORE_DIR}/dom/default"
+    "${WEBCORE_DIR}/dom/messageports"
     "${WEBCORE_DIR}/domjit"
     "${WEBCORE_DIR}/editing"
     "${WEBCORE_DIR}/fileapi"
index fa0f0df..03ca508 100644 (file)
@@ -1,3 +1,164 @@
+2018-01-18  Brady Eidson  <beidson@apple.com>
+
+        Make in-process MessagePorts be (mostly) asynchronous
+        https://bugs.webkit.org/show_bug.cgi?id=181454
+
+        Reviewed by Alex Christensen.
+
+        No new tests (Covered *brutally* by existing tests)
+
+        Part of making MessagePorts be a thing we can pass across processes is making them work async.
+        
+        The existing "MessagePortChannel" method of abstraction was not cut out for this.
+        This patch gets rid of MessagePortChannel and adds a new MessagePortChannelProvider abstraction.
+        It then gets the new machinery working in-process (with some pieces of out-of-process in place)
+
+        One synchronous behavior this patch maintains is the hasPendingActivity() check used to support GC.
+        That will (creatively) be made async in the next followup.
+        
+        More generally from MessagePorts, this patch also adds a "MessageWithMessagePorts" object to be used
+        with all forms of postMessage(). Much better.
+        
+        * CMakeLists.txt:
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+
+        * dom/InProcessMessagePortChannel.cpp: Removed.
+        * dom/InProcessMessagePortChannel.h: Removed.
+        * dom/MessagePortChannel.cpp: Removed.
+        * dom/MessagePortChannel.h: Removed.
+
+        * dom/MessageChannel.cpp:
+        (WebCore::MessageChannel::create):
+        (WebCore::MessageChannel::MessageChannel):
+        (WebCore::m_port2): Deleted.
+        * dom/MessageChannel.h:
+        (WebCore::MessageChannel::create): Deleted.
+
+        * dom/MessagePort.cpp:
+        (WebCore::MessagePort::create):
+        (WebCore::MessagePort::MessagePort):
+        (WebCore::MessagePort::~MessagePort):
+        (WebCore::MessagePort::entangle):
+        (WebCore::MessagePort::postMessage):
+        (WebCore::MessagePort::disentangle):
+        (WebCore::MessagePort::messageAvailable):
+        (WebCore::MessagePort::start):
+        (WebCore::MessagePort::close):
+        (WebCore::MessagePort::contextDestroyed):
+        (WebCore::MessagePort::dispatchMessages):
+        (WebCore::MessagePort::hasPendingActivity const):
+        (WebCore::MessagePort::locallyEntangledPort const):
+        (WebCore::MessagePort::disentanglePorts):
+        (WebCore::MessagePort::entanglePorts):
+        (WebCore::MessagePort::entangleWithRemote): Deleted.
+        * dom/MessagePort.h:
+
+        * dom/MessagePortIdentifier.h:
+        (WebCore::MessagePortIdentifier::logString const):
+
+        * dom/ScriptExecutionContext.cpp:
+        (WebCore::ScriptExecutionContext::processMessageWithMessagePortsSoon):
+        (WebCore::ScriptExecutionContext::dispatchMessagePortEvents):
+        (WebCore::ScriptExecutionContext::processMessagePortMessagesSoon): Deleted.
+        * dom/ScriptExecutionContext.h:
+
+        Add a single object that represents two intertwined ports, tracks their pending
+        messages, tracks which process they're in, etc etc:
+        * dom/messageports/MessagePortChannel.cpp: Added.
+        (WebCore::MessagePortChannel::create):
+        (WebCore::MessagePortChannel::MessagePortChannel):
+        (WebCore::MessagePortChannel::~MessagePortChannel):
+        (WebCore::MessagePortChannel::includesPort):
+        (WebCore::MessagePortChannel::entanglePortWithProcess):
+        (WebCore::MessagePortChannel::disentanglePort):
+        (WebCore::MessagePortChannel::closePort):
+        (WebCore::MessagePortChannel::postMessageToRemote):
+        (WebCore::MessagePortChannel::takeAllMessagesForPort):
+        (WebCore::MessagePortChannel::hasAnyMessagesPendingOrInFlight const):
+        * dom/messageports/MessagePortChannel.h: Added.
+        (WebCore::MessagePortChannel::port1 const):
+        (WebCore::MessagePortChannel::port2 const):
+        (WebCore::MessagePortChannel::logString const):
+
+        Abstraction for creating and operating on MessagePorts in a potentially cross-process way:
+        * dom/messageports/MessagePortChannelProvider.cpp: Added.
+        (WebCore::MessagePortChannelProvider::singleton):
+        (WebCore::MessagePortChannelProvider::setSharedProvider):
+        * dom/messageports/MessagePortChannelProvider.h: Added.
+        (WebCore::MessagePortChannelProvider::~MessagePortChannelProvider):
+
+        Adds a concrete implementation of that provider to be used in-process (e.g. WK1):
+        * dom/messageports/MessagePortChannelProviderImpl.cpp: Added.
+        (WebCore::MessagePortChannelProviderImpl::~MessagePortChannelProviderImpl):
+        (WebCore::MessagePortChannelProviderImpl::performActionOnAppropriateThread):
+        (WebCore::MessagePortChannelProviderImpl::createNewMessagePortChannel):
+        (WebCore::MessagePortChannelProviderImpl::entangleLocalPortInThisProcessToRemote):
+        (WebCore::MessagePortChannelProviderImpl::messagePortDisentangled):
+        (WebCore::MessagePortChannelProviderImpl::messagePortClosed):
+        (WebCore::MessagePortChannelProviderImpl::postMessageToRemote):
+        (WebCore::MessagePortChannelProviderImpl::takeAllMessagesForPort):
+        (WebCore::MessagePortChannelProviderImpl::hasMessagesForPorts_temporarySync):
+        * dom/messageports/MessagePortChannelProviderImpl.h: Added.
+
+        Adds a main thread object to handle the set of all MessagePortChannels that are open.
+        For now it lives in the WebProcess, but for out-of-process it will live in the UIProcess:
+        * dom/messageports/MessagePortChannelRegistry.cpp: Added.
+        (WebCore::MessagePortChannelRegistry::~MessagePortChannelRegistry):
+        (WebCore::MessagePortChannelRegistry::didCreateMessagePortChannel):
+        (WebCore::MessagePortChannelRegistry::messagePortChannelCreated):
+        (WebCore::MessagePortChannelRegistry::messagePortChannelDestroyed):
+        (WebCore::MessagePortChannelRegistry::didEntangleLocalToRemote):
+        (WebCore::MessagePortChannelRegistry::didDisentangleMessagePort):
+        (WebCore::MessagePortChannelRegistry::didCloseMessagePort):
+        (WebCore::MessagePortChannelRegistry::didPostMessageToRemote):
+        (WebCore::MessagePortChannelRegistry::takeAllMessagesForPort):
+        (WebCore::MessagePortChannelRegistry::hasMessagesForPorts_temporarySync): This is named against style
+          and weird on purpose - to call attention to how bad it is and how it's temporary.
+        (WebCore::MessagePortChannelRegistry::existingChannelContainingPort):
+        * dom/messageports/MessagePortChannelRegistry.h: Added.
+
+        Add an object that represents a "SerializedScriptValue for the message payload and the ports
+        that are being transferred along with that payload". This is used in all forms of postMessage():
+        * dom/messageports/MessageWithMessagePorts.cpp: Added.
+        * dom/messageports/MessageWithMessagePorts.h: Added.
+
+        * page/DOMWindow.cpp:
+        (WebCore::PostMessageTimer::PostMessageTimer):
+        (WebCore::PostMessageTimer::event):
+        (WebCore::DOMWindow::postMessage):
+
+        * platform/Logging.h:
+
+        * workers/DedicatedWorkerGlobalScope.cpp:
+        (WebCore::DedicatedWorkerGlobalScope::postMessage):
+
+        * workers/Worker.cpp:
+        (WebCore::Worker::postMessage):
+
+        * workers/WorkerGlobalScopeProxy.h:
+
+        * workers/WorkerMessagingProxy.cpp:
+        (WebCore::WorkerMessagingProxy::postMessageToWorkerObject):
+        (WebCore::WorkerMessagingProxy::postMessageToWorkerGlobalScope):
+        * workers/WorkerMessagingProxy.h:
+
+        * workers/WorkerObjectProxy.h:
+
+        * workers/service/ServiceWorker.cpp:
+        (WebCore::ServiceWorker::postMessage):
+
+        * workers/service/ServiceWorkerClient.cpp:
+        (WebCore::ServiceWorkerClient::postMessage):
+
+        * workers/service/context/SWContextManager.cpp:
+        (WebCore::SWContextManager::postMessageToServiceWorker):
+
+        * workers/service/context/ServiceWorkerThread.cpp:
+        (WebCore::fireMessageEvent):
+        (WebCore::ServiceWorkerThread::postMessageToServiceWorker):
+        * workers/service/context/ServiceWorkerThread.h:
+
 2018-01-18  Ryan Haddad  <ryanhaddad@apple.com>
 
         Unreviewed build fix, removed unused lambda capture.
index 9c2b0a5..82898b2 100644 (file)
@@ -735,7 +735,6 @@ dom/FocusEvent.cpp
 dom/GenericEventQueue.cpp
 dom/IdTargetObserver.cpp
 dom/IdTargetObserverRegistry.cpp
-dom/InProcessMessagePortChannel.cpp
 dom/InlineClassicScript.cpp
 dom/InlineStyleSheetOwner.cpp
 dom/InputEvent.cpp
@@ -747,7 +746,6 @@ dom/LoadableScript.cpp
 dom/MessageChannel.cpp
 dom/MessageEvent.cpp
 dom/MessagePort.cpp
-dom/MessagePortChannel.cpp
 dom/Microtasks.cpp
 dom/MouseEvent.cpp
 dom/MouseRelatedEvent.cpp
@@ -823,6 +821,12 @@ dom/WebKitAnimationEvent.cpp
 dom/WebKitTransitionEvent.cpp
 dom/WheelEvent.cpp
 
+dom/messageports/MessagePortChannel.cpp
+dom/messageports/MessagePortChannelProvider.cpp
+dom/messageports/MessagePortChannelProviderImpl.cpp
+dom/messageports/MessagePortChannelRegistry.cpp
+dom/messageports/MessageWithMessagePorts.cpp
+
 domjit/DOMJITHelpers.cpp
 domjit/JSDocumentDOMJIT.cpp
 domjit/JSDocumentFragmentDOMJIT.cpp
index 21b9d16..4d67f59 100644 (file)
                41B28B151F8501D300FB52AC /* MediaEndpointConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 41B28B121F8501A300FB52AC /* MediaEndpointConfiguration.h */; };
                41B28B3D1F860EF300FB52AC /* LibWebRTCProviderCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 41B28B361F860BD000FB52AC /* LibWebRTCProviderCocoa.h */; settings = {ATTRIBUTES = (Private, ); }; };
                41B2A6261EF1BF6D002B9D7A /* WebAudioSourceProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 41B2A6251EF1BF60002B9D7A /* WebAudioSourceProvider.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               41BF700C0FE86F49005E8DEC /* MessagePortChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 41BF700A0FE86F49005E8DEC /* MessagePortChannel.h */; settings = {ATTRIBUTES = (Private, ); }; };
                41C760B10EDE03D300C1655F /* ScriptState.h in Headers */ = {isa = PBXBuildFile; fileRef = 41C760B00EDE03D300C1655F /* ScriptState.h */; settings = {ATTRIBUTES = (Private, ); }; };
                41CAD71E1EA090A100178164 /* VideoToolBoxEncoderFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41CAD71C1EA0905700178164 /* VideoToolBoxEncoderFactory.cpp */; };
                41D015CA0F4B5C71004A662F /* ContentType.h in Headers */ = {isa = PBXBuildFile; fileRef = 41D015C80F4B5C71004A662F /* ContentType.h */; settings = {ATTRIBUTES = (Private, ); }; };
                511EC12C1C50ABBF0032F983 /* SQLiteIDBTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 511EC12A1C50ABBA0032F983 /* SQLiteIDBTransaction.h */; };
                511EC1301C50ABF50032F983 /* SQLiteIDBCursor.h in Headers */ = {isa = PBXBuildFile; fileRef = 511EC12E1C50ABEC0032F983 /* SQLiteIDBCursor.h */; };
                5120BBAF1F1CECE700EFEBF1 /* CookieStorageObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 5120BBAD1F1CE77000EFEBF1 /* CookieStorageObserver.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               512B57C01FE99083000A1E5E /* InProcessMessagePortChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 512B57BC1FE9902C000A1E5E /* InProcessMessagePortChannel.h */; };
                512BDB4B1C456FFA006494DF /* SQLiteIDBBackingStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 512BDB491C456FAB006494DF /* SQLiteIDBBackingStore.h */; };
                512DD8F50D91E6AF000F89EE /* LegacyWebArchive.h in Headers */ = {isa = PBXBuildFile; fileRef = 512DD8EB0D91E6AF000F89EE /* LegacyWebArchive.h */; settings = {ATTRIBUTES = (Private, ); }; };
                512DD8F60D91E6AF000F89EE /* Archive.h in Headers */ = {isa = PBXBuildFile; fileRef = 512DD8EC0D91E6AF000F89EE /* Archive.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51A052561058874000CC9E95 /* ProtectionSpaceHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 51A052551058874000CC9E95 /* ProtectionSpaceHash.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51A4BB0A1954D61600FA5C2E /* Gamepad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51A4BB071954D61600FA5C2E /* Gamepad.cpp */; };
                51A4BB101954D62700FA5C2E /* NavigatorGamepad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51A4BB0D1954D62700FA5C2E /* NavigatorGamepad.cpp */; };
+               51A748E32005D0E80075BA68 /* MessageWithMessagePorts.h in Headers */ = {isa = PBXBuildFile; fileRef = 51A748E02005D0E00075BA68 /* MessageWithMessagePorts.h */; };
+               51A748E62006004F0075BA68 /* MessagePortChannelProviderImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 51A748E5200600210075BA68 /* MessagePortChannelProviderImpl.h */; };
                51A9D9E9195B931F001B2B5C /* GamepadManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51A9D9E7195B931F001B2B5C /* GamepadManager.cpp */; };
                51A9D9EA195B931F001B2B5C /* GamepadManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 51A9D9E8195B931F001B2B5C /* GamepadManager.h */; };
                51ABAE1E103C1913008C5260 /* SocketStreamHandleImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 51ABAE1C103C1913008C5260 /* SocketStreamHandleImpl.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51E399021D6E4750009C8831 /* GameControllerGamepadProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E398FE1D6E474B009C8831 /* GameControllerGamepadProvider.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51E3AA0B1B98BCAB0036AD81 /* SecurityOriginData.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E3AA091B98BC9A0036AD81 /* SecurityOriginData.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51E6821016387302003BBF3C /* LoaderStrategy.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E6820F16387302003BBF3C /* LoaderStrategy.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               51ECC3F6200587BF00483EAE /* MessagePortChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 51ECC3F4200587B700483EAE /* MessagePortChannel.h */; };
+               51ECC3F8200587BF00483EAE /* MessagePortChannelRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 51ECC3F1200587B500483EAE /* MessagePortChannelRegistry.h */; };
+               51ECC3FD2005930D00483EAE /* MessagePortChannelProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 51ECC3FB2005930100483EAE /* MessagePortChannelProvider.h */; };
                51EE7B381AA50B0500F92B21 /* ResourceLoadInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 51EE7B371AA50B0500F92B21 /* ResourceLoadInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51EEAA741BEFFAB100218008 /* IndexValueEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = 51EEAA721BEFFA7900218008 /* IndexValueEntry.h */; };
                51F174FE1F35899200C74950 /* WorkerType.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F174FC1F35898800C74950 /* WorkerType.h */; settings = {ATTRIBUTES = (Private, ); }; };
                41B2A6251EF1BF60002B9D7A /* WebAudioSourceProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebAudioSourceProvider.h; sourceTree = "<group>"; };
                41B459DA1F4CADB90000F6FD /* ReadableStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReadableStream.h; sourceTree = "<group>"; };
                41B459ED1F55EBC70000F6FD /* ReadableStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ReadableStream.cpp; sourceTree = "<group>"; };
-               41BF700A0FE86F49005E8DEC /* MessagePortChannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessagePortChannel.h; sourceTree = "<group>"; };
                41C760B00EDE03D300C1655F /* ScriptState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptState.h; sourceTree = "<group>"; };
                41C7E1051E6A54360027B4DE /* CanvasCaptureMediaStreamTrack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CanvasCaptureMediaStreamTrack.cpp; sourceTree = "<group>"; };
                41C7E1061E6A54360027B4DE /* CanvasCaptureMediaStreamTrack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CanvasCaptureMediaStreamTrack.h; sourceTree = "<group>"; };
                5123AF161890A4CA0031CDC9 /* IDBKeyRangeData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBKeyRangeData.cpp; sourceTree = "<group>"; };
                5123AF171890A4CA0031CDC9 /* IDBKeyRangeData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBKeyRangeData.h; sourceTree = "<group>"; };
                5123AF1C18918AE40031CDC9 /* IDBGetResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBGetResult.h; sourceTree = "<group>"; };
-               512B57BC1FE9902C000A1E5E /* InProcessMessagePortChannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InProcessMessagePortChannel.h; sourceTree = "<group>"; };
-               512B57BE1FE9902D000A1E5E /* MessagePortChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MessagePortChannel.cpp; sourceTree = "<group>"; };
-               512B57BF1FE9902E000A1E5E /* InProcessMessagePortChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InProcessMessagePortChannel.cpp; sourceTree = "<group>"; };
                512BDB481C456FAB006494DF /* SQLiteIDBBackingStore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SQLiteIDBBackingStore.cpp; sourceTree = "<group>"; };
                512BDB491C456FAB006494DF /* SQLiteIDBBackingStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQLiteIDBBackingStore.h; sourceTree = "<group>"; };
                512BDB4C1C46B0FF006494DF /* JSIDBCursorCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSIDBCursorCustom.cpp; sourceTree = "<group>"; };
                51A4BB0D1954D62700FA5C2E /* NavigatorGamepad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NavigatorGamepad.cpp; sourceTree = "<group>"; };
                51A4BB0E1954D62700FA5C2E /* NavigatorGamepad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NavigatorGamepad.h; sourceTree = "<group>"; };
                51A4BB0F1954D62700FA5C2E /* NavigatorGamepad.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = NavigatorGamepad.idl; sourceTree = "<group>"; };
+               51A748E02005D0E00075BA68 /* MessageWithMessagePorts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessageWithMessagePorts.h; sourceTree = "<group>"; };
+               51A748E12005D0E00075BA68 /* MessageWithMessagePorts.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MessageWithMessagePorts.cpp; sourceTree = "<group>"; };
+               51A748E4200600210075BA68 /* MessagePortChannelProviderImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MessagePortChannelProviderImpl.cpp; sourceTree = "<group>"; };
+               51A748E5200600210075BA68 /* MessagePortChannelProviderImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessagePortChannelProviderImpl.h; sourceTree = "<group>"; };
                51A9D9E7195B931F001B2B5C /* GamepadManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GamepadManager.cpp; sourceTree = "<group>"; };
                51A9D9E8195B931F001B2B5C /* GamepadManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GamepadManager.h; sourceTree = "<group>"; };
                51AA3F6E0BD5AA9E00892971 /* ResourceLoaderMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ResourceLoaderMac.mm; sourceTree = "<group>"; };
                51E3F9D50DA05E1D00250911 /* JSStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStorage.h; sourceTree = "<group>"; };
                51E6820F16387302003BBF3C /* LoaderStrategy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoaderStrategy.h; sourceTree = "<group>"; };
                51EAC5B018163F4E004F1BA4 /* IDBRecordIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBRecordIdentifier.h; sourceTree = "<group>"; };
+               51ECC3F1200587B500483EAE /* MessagePortChannelRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessagePortChannelRegistry.h; sourceTree = "<group>"; };
+               51ECC3F3200587B600483EAE /* MessagePortChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MessagePortChannel.cpp; sourceTree = "<group>"; };
+               51ECC3F4200587B700483EAE /* MessagePortChannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessagePortChannel.h; sourceTree = "<group>"; };
+               51ECC3F5200587B700483EAE /* MessagePortChannelRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MessagePortChannelRegistry.cpp; sourceTree = "<group>"; };
+               51ECC3FB2005930100483EAE /* MessagePortChannelProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessagePortChannelProvider.h; sourceTree = "<group>"; };
+               51ECC3FC2005930200483EAE /* MessagePortChannelProvider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MessagePortChannelProvider.cpp; sourceTree = "<group>"; };
                51EE7B371AA50B0500F92B21 /* ResourceLoadInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResourceLoadInfo.h; sourceTree = "<group>"; };
                51EE7B391AA5123100F92B21 /* ResourceLoadInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ResourceLoadInfo.cpp; sourceTree = "<group>"; };
                51EEAA711BEFFA7900218008 /* IndexValueEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndexValueEntry.cpp; sourceTree = "<group>"; };
                        path = mac;
                        sourceTree = "<group>";
                };
+               51ECC3E42005831F00483EAE /* messageports */ = {
+                       isa = PBXGroup;
+                       children = (
+                               51ECC3F3200587B600483EAE /* MessagePortChannel.cpp */,
+                               51ECC3F4200587B700483EAE /* MessagePortChannel.h */,
+                               51ECC3FC2005930200483EAE /* MessagePortChannelProvider.cpp */,
+                               51ECC3FB2005930100483EAE /* MessagePortChannelProvider.h */,
+                               51A748E4200600210075BA68 /* MessagePortChannelProviderImpl.cpp */,
+                               51A748E5200600210075BA68 /* MessagePortChannelProviderImpl.h */,
+                               51ECC3F5200587B700483EAE /* MessagePortChannelRegistry.cpp */,
+                               51ECC3F1200587B500483EAE /* MessagePortChannelRegistry.h */,
+                               51A748E12005D0E00075BA68 /* MessageWithMessagePorts.cpp */,
+                               51A748E02005D0E00075BA68 /* MessageWithMessagePorts.h */,
+                       );
+                       path = messageports;
+                       sourceTree = "<group>";
+               };
                51F175441F3EBBF200C74950 /* service */ = {
                        isa = PBXGroup;
                        children = (
                        children = (
                                CE2616A4187E65C1007955F3 /* ios */,
                                2D5036661BCDDDC400E20BB3 /* mac */,
+                               51ECC3E42005831F00483EAE /* messageports */,
                                7CD0E2B61F80A4820016A4CE /* AbortController.cpp */,
                                7CD0E2B51F80A4820016A4CE /* AbortController.h */,
                                7CD0E2B71F80A4820016A4CE /* AbortController.idl */,
                                E30592621E27A38C00D57C98 /* InlineClassicScript.h */,
                                AA4C3A740B2B1679002334A2 /* InlineStyleSheetOwner.cpp */,
                                AA4C3A750B2B1679002334A2 /* InlineStyleSheetOwner.h */,
-                               512B57BF1FE9902E000A1E5E /* InProcessMessagePortChannel.cpp */,
-                               512B57BC1FE9902C000A1E5E /* InProcessMessagePortChannel.h */,
                                2EB767551DA19B99003E23B5 /* InputEvent.cpp */,
                                2EB767541DA19B67003E23B5 /* InputEvent.h */,
                                2EB767531DA19313003E23B5 /* InputEvent.idl */,
                                E1ADECBE0E76ACF1004A1A5E /* MessagePort.cpp */,
                                E1ADECBD0E76ACF1004A1A5E /* MessagePort.h */,
                                E1ADECC60E76AD1F004A1A5E /* MessagePort.idl */,
-                               512B57BE1FE9902D000A1E5E /* MessagePortChannel.cpp */,
-                               41BF700A0FE86F49005E8DEC /* MessagePortChannel.h */,
                                51F645DE1FF4594B00B54DED /* MessagePortIdentifier.h */,
                                CB8CF0151A934B43000D510B /* Microtasks.cpp */,
                                53B895AD19DC7C37009CAA93 /* Microtasks.h */,
                                BCEA485A097D93020094C9E4 /* InlineTextBox.h in Headers */,
                                1C010701192594DF008A4201 /* InlineTextBoxStyle.h in Headers */,
                                510A58E51BAA40B100C19282 /* InProcessIDBServer.h in Headers */,
-                               512B57C01FE99083000A1E5E /* InProcessMessagePortChannel.h in Headers */,
                                2EB767571DA19BDF003E23B5 /* InputEvent.h in Headers */,
                                37E3524D12450C6600BAF5D9 /* InputType.h in Headers */,
                                C348612415FDE21E007A1CC9 /* InputTypeNames.h in Headers */,
                                E1ADECCE0E76AD8B004A1A5E /* MessageChannel.h in Headers */,
                                75793E840D0CE0B3007FC0AC /* MessageEvent.h in Headers */,
                                E1ADECBF0E76ACF1004A1A5E /* MessagePort.h in Headers */,
-                               41BF700C0FE86F49005E8DEC /* MessagePortChannel.h in Headers */,
+                               51ECC3F6200587BF00483EAE /* MessagePortChannel.h in Headers */,
+                               51ECC3FD2005930D00483EAE /* MessagePortChannelProvider.h in Headers */,
+                               51A748E62006004F0075BA68 /* MessagePortChannelProviderImpl.h in Headers */,
+                               51ECC3F8200587BF00483EAE /* MessagePortChannelRegistry.h in Headers */,
                                51F645E01FF4594E00B54DED /* MessagePortIdentifier.h in Headers */,
+                               51A748E32005D0E80075BA68 /* MessageWithMessagePorts.h in Headers */,
                                53B895AF19DC7ED9009CAA93 /* Microtasks.h in Headers */,
                                BC772C4F0C4EB3040083285F /* MIMETypeRegistry.h in Headers */,
                                52F10866162B6DA8009AC81E /* MixedContentChecker.h in Headers */,
diff --git a/Source/WebCore/dom/InProcessMessagePortChannel.cpp b/Source/WebCore/dom/InProcessMessagePortChannel.cpp
deleted file mode 100644 (file)
index 2467f94..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#include "config.h"
-#include "InProcessMessagePortChannel.h"
-
-#include "MessagePort.h"
-#include <wtf/CompletionHandler.h>
-#include <wtf/Locker.h>
-
-namespace WebCore {
-
-void InProcessMessagePortChannel::createChannelBetweenPorts(MessagePort& port1, MessagePort& port2)
-{
-    auto queue1 = MessagePortQueue::create();
-    auto queue2 = MessagePortQueue::create();
-
-    auto channel1 = InProcessMessagePortChannel::create(queue1.get(), queue2.get());
-    auto channel2 = InProcessMessagePortChannel::create(queue2.get(), queue1.get());
-
-    channel1->m_entangledChannel = channel2.ptr();
-    channel2->m_entangledChannel = channel1.ptr();
-
-    port1.entangleWithRemote(WTFMove(channel2));
-    port2.entangleWithRemote(WTFMove(channel1));
-}
-
-Ref<InProcessMessagePortChannel> InProcessMessagePortChannel::create(MessagePortQueue& incoming, MessagePortQueue& outgoing)
-{
-    return adoptRef(*new InProcessMessagePortChannel(incoming, outgoing));
-}
-
-InProcessMessagePortChannel::InProcessMessagePortChannel(MessagePortQueue& incoming, MessagePortQueue& outgoing)
-    : m_incomingQueue(&incoming)
-    , m_outgoingQueue(&outgoing)
-{
-}
-
-InProcessMessagePortChannel::~InProcessMessagePortChannel()
-{
-    // Channels being destroyed should to have been closed.
-    ASSERT(!m_outgoingQueue);
-}
-
-void InProcessMessagePortChannel::postMessageToRemote(Ref<SerializedScriptValue>&& message, std::unique_ptr<MessagePortChannelArray>&& channels)
-{
-    Locker<Lock> locker(m_lock);
-
-    if (!m_outgoingQueue)
-        return;
-
-    bool wasEmpty = m_outgoingQueue->appendAndCheckEmpty(std::make_unique<EventData>(WTFMove(message), WTFMove(channels)));
-    if (wasEmpty && m_remotePort)
-        m_remotePort->messageAvailable();
-}
-
-void InProcessMessagePortChannel::takeAllMessagesFromRemote(CompletionHandler<void(Deque<std::unique_ptr<EventData>>&&)>&& callback)
-{
-    Deque<std::unique_ptr<EventData>> messages;
-    {
-        Locker<Lock> locker(m_lock);
-        messages = m_incomingQueue->takeAllMessages();
-    }
-
-    callback(WTFMove(messages));
-}
-
-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 && m_remotePort->identifier() == identifier;
-}
-
-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.
-    RefPtr<InProcessMessagePortChannel> remote;
-    {
-        Locker<Lock> locker(m_lock);
-        remote = m_entangledChannel;
-    }
-
-    if (!remote)
-        return false;
-
-    auto entangledPort = MessagePort::existingMessagePortForIdentifier(identifier);
-    ASSERT(entangledPort);
-
-    remote->setRemotePort(entangledPort.get());
-
-    return true;
-}
-
-void InProcessMessagePortChannel::disentangle()
-{
-    Locker<Lock> locker(m_lock);
-
-    if (m_entangledChannel)
-        m_entangledChannel->setRemotePort(nullptr);
-}
-
-bool InProcessMessagePortChannel::hasPendingActivity()
-{
-    // FIXME: What guarantees that the result remains the same after we release the lock?
-    Locker<Lock> locker(m_lock);
-    return !m_incomingQueue->isEmpty();
-}
-
-MessagePort* InProcessMessagePortChannel::locallyEntangledPort(const ScriptExecutionContext* context)
-{
-    Locker<Lock> locker(m_lock);
-
-    // See if both contexts are run by the same thread (are the same context, or are both documents).
-    if (!m_remotePort)
-        return nullptr;
-
-    // The remote port's ScriptExecutionContext is guaranteed not to change here - MessagePort::contextDestroyed()
-    // will close the port before the context goes away, and close() will block because we are holding the mutex.
-    ScriptExecutionContext* remoteContext = m_remotePort->scriptExecutionContext();
-    if (remoteContext == context || (remoteContext && remoteContext->isDocument() && context->isDocument()))
-        return m_remotePort;
-
-    return nullptr;
-}
-
-RefPtr<InProcessMessagePortChannel> InProcessMessagePortChannel::takeEntangledChannel()
-{
-    RefPtr<InProcessMessagePortChannel> channel;
-
-    {
-        Locker<Lock> locker(m_lock);
-        channel = WTFMove(m_entangledChannel);
-    }
-
-    return channel;
-}
-
-void InProcessMessagePortChannel::close()
-{
-    Locker<Lock> locker(m_lock);
-
-    RefPtr<InProcessMessagePortChannel> channel;
-    if (m_entangledChannel) {
-        channel = m_entangledChannel->takeEntangledChannel();
-        ASSERT(channel == this);
-        m_entangledChannel->close();
-    }
-
-    // Disentangle ourselves from the other end. We still maintain a reference to our incoming queue, since previously-existing messages should still be delivered.
-    m_remotePort = nullptr;
-    m_outgoingQueue = nullptr;
-    m_entangledChannel = nullptr;
-}
-
-void InProcessMessagePortChannel::setRemotePort(MessagePort* port)
-{
-    Locker<Lock> locker(m_lock);
-
-    // Should never set port if it is already set.
-    ASSERT(!port || !m_remotePort);
-
-    m_remotePort = port;
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/dom/InProcessMessagePortChannel.h b/Source/WebCore/dom/InProcessMessagePortChannel.h
deleted file mode 100644 (file)
index 15b01cf..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2017 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 "MessagePortChannel.h"
-#include <wtf/MessageQueue.h>
-
-namespace WebCore {
-
-class InProcessMessagePortChannel : public MessagePortChannel {
-public:
-    static void createChannelBetweenPorts(MessagePort&, MessagePort&);
-
-    ~InProcessMessagePortChannel() final;
-
-    void postMessageToRemote(Ref<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>&&) final;
-    void takeAllMessagesFromRemote(CompletionHandler<void(Deque<std::unique_ptr<EventData>>&&)>&&) final;
-    bool isConnectedTo(const MessagePortIdentifier&) final;
-    bool entangleWithRemoteIfOpen(const MessagePortIdentifier&) final;
-    void disentangle() final;
-    bool hasPendingActivity() final;
-    MessagePort* locallyEntangledPort(const ScriptExecutionContext*) final;
-    void close() final;
-
-private:
-    // Wrapper for MessageQueue that allows us to do thread safe sharing by two proxies.
-    class MessagePortQueue : public ThreadSafeRefCounted<MessagePortQueue> {
-    public:
-        static Ref<MessagePortQueue> create() { return adoptRef(*new MessagePortQueue()); }
-
-        Deque<std::unique_ptr<MessagePortChannel::EventData>> takeAllMessages()
-        {
-            return m_queue.takeAllMessages();
-        }
-
-        bool appendAndCheckEmpty(std::unique_ptr<MessagePortChannel::EventData>&& message)
-        {
-            return m_queue.appendAndCheckEmpty(WTFMove(message));
-        }
-
-        bool isEmpty()
-        {
-            return m_queue.isEmpty();
-        }
-
-    private:
-        MessagePortQueue() { }
-
-        MessageQueue<MessagePortChannel::EventData> m_queue;
-    };
-
-    static Ref<InProcessMessagePortChannel> create(MessagePortQueue& incoming, MessagePortQueue& outgoing);
-    InProcessMessagePortChannel(MessagePortQueue& incoming, MessagePortQueue& outgoing);
-
-    void setRemotePort(MessagePort*);
-    RefPtr<InProcessMessagePortChannel> takeEntangledChannel();
-
-    Lock m_lock;
-
-    RefPtr<InProcessMessagePortChannel> m_entangledChannel;
-
-    RefPtr<MessagePortQueue> m_incomingQueue;
-    RefPtr<MessagePortQueue> m_outgoingQueue;
-
-    MessagePort* m_remotePort { nullptr };
-};
-
-} // namespace WebCore
index 2637d9f..72932d8 100644 (file)
 #include "MessageChannel.h"
 
 #include "MessagePort.h"
-#include "MessagePortChannel.h"
+#include "MessagePortChannelProvider.h"
 
 namespace WebCore {
 
+Ref<MessageChannel> MessageChannel::create(ScriptExecutionContext& context)
+{
+    return adoptRef(*new MessageChannel(context));
+}
+
 MessageChannel::MessageChannel(ScriptExecutionContext& 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);
+    MessagePortIdentifier id1 = { Process::identifier(), generateObjectIdentifier<MessagePortIdentifier::PortIdentifierType>() };
+    MessagePortIdentifier id2 = { Process::identifier(), generateObjectIdentifier<MessagePortIdentifier::PortIdentifierType>() };
+
+    m_port1 = MessagePort::create(context, id1, id2);
+    m_port2 = MessagePort::create(context, id2, id1);
+
+    if (!context.activeDOMObjectsAreStopped()) {
+        ASSERT(!m_port1->closed());
+        ASSERT(!m_port2->closed());
+        MessagePortChannelProvider::singleton().createNewMessagePortChannel(id1, id2);
+    } else {
+        ASSERT(m_port1->closed());
+        ASSERT(m_port2->closed());
+    }
 }
 
 MessageChannel::~MessageChannel() = default;
index ead9c2c..e00db99 100644 (file)
@@ -36,7 +36,7 @@ class ScriptExecutionContext;
 
 class MessageChannel : public RefCounted<MessageChannel> {
 public:
-    static Ref<MessageChannel> create(ScriptExecutionContext& context) { return adoptRef(*new MessageChannel(context)); }
+    static Ref<MessageChannel> create(ScriptExecutionContext&);
     ~MessageChannel();
 
     MessagePort* port1() const { return m_port1.get(); }
index b3c3b6b..a8d1390 100644 (file)
 
 #include "Document.h"
 #include "EventNames.h"
+#include "Logging.h"
 #include "MessageEvent.h"
+#include "MessagePortChannelProvider.h"
+#include "MessageWithMessagePorts.h"
 #include "WorkerGlobalScope.h"
 
 namespace WebCore {
@@ -78,61 +81,86 @@ RefPtr<MessagePort> MessagePort::existingMessagePortForIdentifier(const MessageP
     return allMessagePorts().get(identifier);
 }
 
-MessagePort::MessagePort(ScriptExecutionContext& scriptExecutionContext, const MessagePortIdentifier& identifier)
+Ref<MessagePort> MessagePort::create(ScriptExecutionContext& scriptExecutionContext, const MessagePortIdentifier& local, const MessagePortIdentifier& remote)
+{
+    return adoptRef(*new MessagePort(scriptExecutionContext, local, remote));
+}
+
+MessagePort::MessagePort(ScriptExecutionContext& scriptExecutionContext, const MessagePortIdentifier& local, const MessagePortIdentifier& remote)
     : ActiveDOMObject(&scriptExecutionContext)
-    , m_identifier(identifier)
+    , m_identifier(local)
+    , m_remoteIdentifier(remote)
 {
+    LOG(MessagePorts, "Created MessagePort %s (%p)", m_identifier.logString().utf8().data(), this);
+
     Locker<Lock> locker(allMessagePortsLock());
     allMessagePorts().set(m_identifier, this);
 
     m_scriptExecutionContext->createdMessagePort(*this);
     suspendIfNeeded();
 
-    // Don't need to call processMessagePortMessagesSoon() here, because the port will not be opened until start() is invoked.
+    // Don't need to call processMessageWithMessagePortsSoon() here, because the port will not be opened until start() is invoked.
 }
 
 MessagePort::~MessagePort()
 {
+    LOG(MessagePorts, "Destroyed MessagePort %s (%p)", m_identifier.logString().utf8().data(), this);
+
     ASSERT(allMessagePortsLock().isLocked());
 
-    close();
+    if (m_entangled)
+        close();
+
     if (m_scriptExecutionContext)
         m_scriptExecutionContext->destroyedMessagePort(*this);
 }
 
+void MessagePort::entangle()
+{
+    MessagePortChannelProvider::singleton().entangleLocalPortInThisProcessToRemote(m_identifier, m_remoteIdentifier);
+}
+
 ExceptionOr<void> MessagePort::postMessage(JSC::ExecState& state, JSC::JSValue messageValue, Vector<JSC::Strong<JSC::JSObject>>&& transfer)
 {
+    LOG(MessagePorts, "Attempting to post message to port %s (to be received by port %s)", m_identifier.logString().utf8().data(), m_remoteIdentifier.logString().utf8().data());
+
     Vector<RefPtr<MessagePort>> ports;
-    auto message = SerializedScriptValue::create(state, messageValue, WTFMove(transfer), ports);
-    if (message.hasException())
-        return message.releaseException();
+    auto messageData = SerializedScriptValue::create(state, messageValue, WTFMove(transfer), ports);
+    if (messageData.hasException())
+        return messageData.releaseException();
 
     if (!isEntangled())
         return { };
     ASSERT(m_scriptExecutionContext);
 
-    std::unique_ptr<MessagePortChannelArray> channels;
+    TransferredMessagePortArray transferredPorts;
     // 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->identifier()))
+        for (auto& port : ports) {
+            if (port->identifier() == m_identifier || port->identifier() == m_remoteIdentifier)
                 return Exception { DataCloneError };
         }
 
         auto disentangleResult = MessagePort::disentanglePorts(WTFMove(ports));
         if (disentangleResult.hasException())
             return disentangleResult.releaseException();
-        channels = disentangleResult.releaseReturnValue();
+        transferredPorts = disentangleResult.releaseReturnValue();
     }
-    m_entangledChannel->postMessageToRemote(message.releaseReturnValue(), WTFMove(channels));
+
+    MessageWithMessagePorts message { messageData.releaseReturnValue(), WTFMove(transferredPorts) };
+
+    LOG(MessagePorts, "Actually posting message to port %s (to be received by port %s)", m_identifier.logString().utf8().data(), m_remoteIdentifier.logString().utf8().data());
+
+    MessagePortChannelProvider::singleton().postMessageToRemote(WTFMove(message), m_remoteIdentifier);
     return { };
 }
 
-RefPtr<MessagePortChannel> MessagePort::disentangle()
+void MessagePort::disentangle()
 {
-    ASSERT(m_entangledChannel);
+    ASSERT(m_entangled);
 
-    m_entangledChannel->disentangle();
+    m_entangled = false;
+    MessagePortChannelProvider::singleton().messagePortDisentangled(m_identifier);
 
     // We can't receive any messages or generate any events after this, so remove ourselves from the list of active ports.
     ASSERT(m_scriptExecutionContext);
@@ -141,16 +169,18 @@ RefPtr<MessagePortChannel> MessagePort::disentangle()
     m_scriptExecutionContext->willDestroyDestructionObserver(*this);
 
     m_scriptExecutionContext = nullptr;
-
-    return WTFMove(m_entangledChannel);
 }
 
 // Invoked to notify us that there are messages available for this port.
 // This code may be called from another thread, and so should not call any non-threadsafe APIs (i.e. should not call into the entangled channel or access mutable variables).
 void MessagePort::messageAvailable()
 {
-    ASSERT(m_scriptExecutionContext);
-    m_scriptExecutionContext->processMessagePortMessagesSoon();
+    // This MessagePort object might be disentangled because the port is being transferred,
+    // in which case we'll notify it that messages are available once a new end point is created.
+    if (!m_scriptExecutionContext)
+        return;
+
+    m_scriptExecutionContext->processMessageWithMessagePortsSoon();
 }
 
 void MessagePort::start()
@@ -164,33 +194,25 @@ void MessagePort::start()
         return;
 
     m_started = true;
-    m_scriptExecutionContext->processMessagePortMessagesSoon();
+    m_scriptExecutionContext->processMessageWithMessagePortsSoon();
 }
 
 void MessagePort::close()
 {
-    if (isEntangled())
-        m_entangledChannel->close();
-    m_closed = true;
-}
+    if (m_closed)
+        return;
 
-void MessagePort::entangleWithRemote(RefPtr<MessagePortChannel>&& remote)
-{
-    // Only invoked to set our initial entanglement.
-    ASSERT(!m_entangledChannel);
-    ASSERT(m_scriptExecutionContext);
+    MessagePortChannelProvider::singleton().messagePortClosed(m_identifier);
 
-    // Don't entangle the ports if the channel is closed.
-    if (remote->entangleWithRemoteIfOpen(m_identifier))
-        m_entangledChannel = WTFMove(remote);
+    m_closed = true;
 }
 
 void MessagePort::contextDestroyed()
 {
     ASSERT(m_scriptExecutionContext);
-    // Must be closed before blowing away the cached context, to ensure that we get no more calls to messageAvailable().
-    // ScriptExecutionContext::closeMessagePorts() takes care of that.
-    ASSERT(m_closed);
+    if (!m_closed)
+        close();
+
     m_scriptExecutionContext = nullptr;
 }
 
@@ -200,32 +222,53 @@ void MessagePort::dispatchMessages()
     // The HTML5 spec specifies that any messages sent to a document that is not fully active should be dropped, so this behavior is OK.
     ASSERT(started());
 
-    if (!m_entangledChannel)
+    if (!isEntangled())
         return;
 
-    m_entangledChannel->takeAllMessagesFromRemote([this, protectedThis = makeRef(*this)](Deque<std::unique_ptr<MessagePortChannel::EventData>>&& messages) {
+    auto messagesTakenHandler = [this, protectedThis = makeRef(*this)](Vector<MessageWithMessagePorts>&& messages, Function<void()>&& completionCallback) mutable {
+        auto innerHandler = [this, otherProtectedThis = WTFMove(protectedThis)](Vector<MessageWithMessagePorts>&& messages) {
+            LOG(MessagePorts, "MessagePort %s (%p) dispatching %zu messages", m_identifier.logString().utf8().data(), this, messages.size());
+
+            if (!m_scriptExecutionContext)
+                return;
+
+            ASSERT(m_scriptExecutionContext->isContextThread());
+
+            bool contextIsWorker = is<WorkerGlobalScope>(*m_scriptExecutionContext);
+            for (auto& message : messages) {
+                // close() in Worker onmessage handler should prevent next message from dispatching.
+                if (contextIsWorker && downcast<WorkerGlobalScope>(*m_scriptExecutionContext).isClosing())
+                    return;
+                auto ports = MessagePort::entanglePorts(*m_scriptExecutionContext, WTFMove(message.transferredPorts));
+                dispatchEvent(MessageEvent::create(WTFMove(ports), WTFMove(message.message)));
+            }
+        };
+
         if (!m_scriptExecutionContext)
             return;
 
-        bool contextIsWorker = is<WorkerGlobalScope>(*m_scriptExecutionContext);
-        for (auto& message : messages) {
-            // close() in Worker onmessage handler should prevent next message from dispatching.
-            if (contextIsWorker && downcast<WorkerGlobalScope>(*m_scriptExecutionContext).isClosing())
-                return;
-            auto ports = MessagePort::entanglePorts(*m_scriptExecutionContext, WTFMove(message->channels));
-            dispatchEvent(MessageEvent::create(WTFMove(ports), WTFMove(message->message)));
+        if (m_scriptExecutionContext->isContextThread()) {
+            innerHandler(WTFMove(messages));
+            completionCallback();
+            return;
         }
-    });
+
+        m_scriptExecutionContext->postTask([innerHandler = WTFMove(innerHandler), messages = WTFMove(messages), completionCallback = WTFMove(completionCallback)](ScriptExecutionContext&) mutable {
+            innerHandler(WTFMove(messages));
+            RunLoop::main().dispatch([completionCallback = WTFMove(completionCallback)] {
+                completionCallback();
+            });
+        });
+    };
+
+    MessagePortChannelProvider::singleton().takeAllMessagesForPort(m_identifier, WTFMove(messagesTakenHandler));
 }
 
 bool MessagePort::hasPendingActivity() const
 {
     // The spec says that entangled message ports should always be treated as if they have a strong reference.
     // We'll also stipulate that the queue needs to be open (if the app drops its reference to the port before start()-ing it, then it's not really entangled as it's unreachable).
-    if (m_started && m_entangledChannel && m_entangledChannel->hasPendingActivity())
-        return true;
-
-    if (isEntangled() && !locallyEntangledPort())
+    if (m_started && isEntangled() && MessagePortChannelProvider::singleton().hasMessagesForPorts_temporarySync(m_identifier, m_remoteIdentifier))
         return true;
 
     return false;
@@ -233,41 +276,49 @@ bool MessagePort::hasPendingActivity() const
 
 MessagePort* MessagePort::locallyEntangledPort() const
 {
-    return m_entangledChannel ? m_entangledChannel->locallyEntangledPort(m_scriptExecutionContext) : nullptr;
+    // FIXME: As the header describes, this is an optional optimization.
+    // Even in the new async model we should be able to get it right.
+    return nullptr;
 }
 
-ExceptionOr<std::unique_ptr<MessagePortChannelArray>> MessagePort::disentanglePorts(Vector<RefPtr<MessagePort>>&& ports)
+ExceptionOr<TransferredMessagePortArray> MessagePort::disentanglePorts(Vector<RefPtr<MessagePort>>&& ports)
 {
     if (ports.isEmpty())
-        return nullptr;
+        return TransferredMessagePortArray { };
 
     // Walk the incoming array - if there are any duplicate ports, or null ports or cloned ports, throw an error (per section 8.3.3 of the HTML5 spec).
     HashSet<MessagePort*> portSet;
     for (auto& port : ports) {
-        if (!port || port->isNeutered() || !portSet.add(port.get()).isNewEntry)
+        if (!port || !port->m_entangled || !portSet.add(port.get()).isNewEntry)
             return Exception { DataCloneError };
     }
 
     // Passed-in ports passed validity checks, so we can disentangle them.
-    auto portArray = std::make_unique<MessagePortChannelArray>(ports.size());
-    for (unsigned i = 0 ; i < ports.size(); ++i)
-        (*portArray)[i] = ports[i]->disentangle();
+    TransferredMessagePortArray portArray;
+    portArray.reserveInitialCapacity(ports.size());
+    for (auto& port : ports) {
+        portArray.uncheckedAppend({ port->identifier(), port->remoteIdentifier() });
+        port->disentangle();
+    }
+
     return WTFMove(portArray);
 }
 
-Vector<RefPtr<MessagePort>> MessagePort::entanglePorts(ScriptExecutionContext& context, std::unique_ptr<MessagePortChannelArray>&& channels)
+Vector<RefPtr<MessagePort>> MessagePort::entanglePorts(ScriptExecutionContext& context, TransferredMessagePortArray&& transferredPorts)
 {
-    if (!channels || !channels->size())
+    LOG(MessagePorts, "Entangling %zu transferred ports to ScriptExecutionContext %s (%p)", transferredPorts.size(), context.url().string().utf8().data(), &context);
+
+    if (transferredPorts.isEmpty())
         return { };
 
-    Vector<RefPtr<MessagePort>> portArray;
-    portArray.reserveInitialCapacity(channels->size());
-    for (unsigned int i = 0; i < channels->size(); ++i) {
-        auto port = MessagePort::create(context, { Process::identifier(), generateObjectIdentifier<MessagePortIdentifier::PortIdentifierType>() });
-        port->entangleWithRemote(WTFMove((*channels)[i]));
-        portArray.uncheckedAppend(WTFMove(port));
+    Vector<RefPtr<MessagePort>> ports;
+    ports.reserveInitialCapacity(transferredPorts.size());
+    for (auto& transferredPort : transferredPorts) {
+        auto port = MessagePort::create(context, transferredPort.first, transferredPort.second);
+        port->entangle();
+        ports.uncheckedAppend(WTFMove(port));
     }
-    return portArray;
+    return ports;
 }
 
 bool MessagePort::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, const AddEventListenerOptions& options)
index e73b632..145a5a9 100644 (file)
@@ -31,6 +31,7 @@
 #include "ExceptionOr.h"
 #include "MessagePortChannel.h"
 #include "MessagePortIdentifier.h"
+#include "MessageWithMessagePorts.h"
 
 namespace JSC {
 class ExecState;
@@ -44,23 +45,23 @@ class Frame;
 
 class MessagePort final : public ActiveDOMObject, public EventTargetWithInlineData {
 public:
-    static Ref<MessagePort> create(ScriptExecutionContext& scriptExecutionContext, const MessagePortIdentifier& identifier) { return adoptRef(*new MessagePort(scriptExecutionContext, identifier)); }
+    static Ref<MessagePort> create(ScriptExecutionContext&, const MessagePortIdentifier& local, const MessagePortIdentifier& remote);
     virtual ~MessagePort();
 
     ExceptionOr<void> postMessage(JSC::ExecState&, JSC::JSValue message, Vector<JSC::Strong<JSC::JSObject>>&&);
 
     void start();
     void close();
-
-    void entangleWithRemote(RefPtr<MessagePortChannel>&&);
+    void entangle();
 
     // 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 ExceptionOr<TransferredMessagePortArray> disentanglePorts(Vector<RefPtr<MessagePort>>&&);
+    static Vector<RefPtr<MessagePort>> entanglePorts(ScriptExecutionContext&, TransferredMessagePortArray&&);
     static RefPtr<MessagePort> existingMessagePortForIdentifier(const MessagePortIdentifier&);
 
     void messageAvailable();
     bool started() const { return m_started; }
+    bool closed() const { return m_closed; }
 
     void dispatchMessages();
 
@@ -70,6 +71,7 @@ public:
     MessagePort* locallyEntangledPort() const;
 
     const MessagePortIdentifier& identifier() const { return m_identifier; }
+    const MessagePortIdentifier& remoteIdentifier() const { return m_remoteIdentifier; }
 
     void ref() const;
     void deref() const;
@@ -88,24 +90,21 @@ public:
     void derefEventTarget() final { deref(); }
 
 private:
-    explicit MessagePort(ScriptExecutionContext&, const MessagePortIdentifier&);
+    explicit MessagePort(ScriptExecutionContext&, const MessagePortIdentifier& local, const MessagePortIdentifier& remote);
 
     bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) final;
 
-    RefPtr<MessagePortChannel> disentangle();
+    void disentangle();
 
     // A port starts out its life entangled, and remains entangled until it is closed or is cloned.
-    bool isEntangled() const { return !m_closed && !isNeutered(); }
-
-    // A port gets neutered when it is transferred to a new owner via postMessage().
-    bool isNeutered() const { return !m_entangledChannel; }
+    bool isEntangled() const { return !m_closed && m_entangled; }
 
-    RefPtr<MessagePortChannel> m_entangledChannel;
-    RefPtr<MessagePort> m_messageProtector;
     bool m_started { false };
     bool m_closed { false };
+    bool m_entangled { true };
 
     MessagePortIdentifier m_identifier;
+    MessagePortIdentifier m_remoteIdentifier;
 
     mutable std::atomic<unsigned> m_refCount { 1 };
 };
diff --git a/Source/WebCore/dom/MessagePortChannel.cpp b/Source/WebCore/dom/MessagePortChannel.cpp
deleted file mode 100644 (file)
index 2cf42b9..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
- * Copyright (C) 2013 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:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * 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.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
- * OWNER OR 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.
- */
-
-#include "config.h"
-#include "MessagePortChannel.h"
-
-#include "InProcessMessagePortChannel.h"
-#include "MessagePort.h"
-#include "ScriptExecutionContext.h"
-
-namespace WebCore {
-
-void MessagePortChannel::createChannelBetweenPorts(MessagePort& port1, MessagePort& port2)
-{
-    // FIXME: Later this will become client-configurable.
-    // e.g. WK1 will use the InProcessMessagePortChannel, but WK2 will install a multi-process aware channel.
-    InProcessMessagePortChannel::createChannelBetweenPorts(port1, port2);
-}
-
-MessagePortChannel::MessagePortChannel()
-{
-}
-
-} // namespace WebCore
-
diff --git a/Source/WebCore/dom/MessagePortChannel.h b/Source/WebCore/dom/MessagePortChannel.h
deleted file mode 100644 (file)
index 08fa0cb..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2009 Google 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:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * 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.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
- * OWNER OR 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 "SerializedScriptValue.h"
-#include <memory>
-#include <wtf/Deque.h>
-#include <wtf/Forward.h>
-#include <wtf/RefPtr.h>
-#include <wtf/text/WTFString.h>
-
-namespace WebCore {
-
-class MessagePort;
-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;
-
-class MessagePortChannel : public ThreadSafeRefCounted<MessagePortChannel> {
-    WTF_MAKE_NONCOPYABLE(MessagePortChannel); WTF_MAKE_FAST_ALLOCATED;
-public:
-    struct EventData {
-        EventData(Ref<SerializedScriptValue>&& message, std::unique_ptr<MessagePortChannelArray>&& channels)
-            : message(WTFMove(message))
-            , channels(WTFMove(channels))
-        { }
-
-        Ref<SerializedScriptValue> message;
-        std::unique_ptr<MessagePortChannelArray> channels;
-    };
-
-    MessagePortChannel();
-    virtual ~MessagePortChannel() { }
-
-    static void createChannelBetweenPorts(MessagePort&, MessagePort&);
-
-    virtual void postMessageToRemote(Ref<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>&&) = 0;
-    virtual void takeAllMessagesFromRemote(CompletionHandler<void(Deque<std::unique_ptr<EventData>>&&)>&&) = 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;
-    virtual void close() = 0;
-};
-
-} // namespace WebCore
index 035cdae..f88a049 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "Process.h"
 #include <wtf/Hasher.h>
+#include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
@@ -39,6 +40,10 @@ struct MessagePortIdentifier {
 
     template<class Encoder> void encode(Encoder&) const;
     template<class Decoder> static std::optional<MessagePortIdentifier> decode(Decoder&);
+
+#if !LOG_DISABLED
+    String logString() const;
+#endif
 };
 
 inline bool operator==(const MessagePortIdentifier& a, const MessagePortIdentifier& b)
@@ -73,6 +78,13 @@ inline unsigned MessagePortIdentifier::hash() const
     return computeHash(processIdentifier.toUInt64(), portIdentifier.toUInt64());
 }
 
+#if !LOG_DISABLED
+inline String MessagePortIdentifier::logString() const
+{
+    return makeString(String::number(processIdentifier.toUInt64()), "-", String::number(portIdentifier.toUInt64()));
+}
+#endif
+
 } // namespace WebCore
 
 namespace WTF {
index fc3f096..4d53d8c 100644 (file)
@@ -132,12 +132,12 @@ ScriptExecutionContext::~ScriptExecutionContext()
 #endif
 }
 
-void ScriptExecutionContext::processMessagePortMessagesSoon()
+void ScriptExecutionContext::processMessageWithMessagePortsSoon()
 {
-    if (m_willProcessMessagePortMessagesSoon)
+    if (m_willprocessMessageWithMessagePortsSoon)
         return;
 
-    m_willProcessMessagePortMessagesSoon = true;
+    m_willprocessMessageWithMessagePortsSoon = true;
     postTask([] (ScriptExecutionContext& context) {
         context.dispatchMessagePortEvents();
     });
@@ -148,8 +148,8 @@ void ScriptExecutionContext::dispatchMessagePortEvents()
     checkConsistency();
 
     Ref<ScriptExecutionContext> protectedThis(*this);
-    ASSERT(m_willProcessMessagePortMessagesSoon);
-    m_willProcessMessagePortMessagesSoon = false;
+    ASSERT(m_willprocessMessageWithMessagePortsSoon);
+    m_willprocessMessageWithMessagePortsSoon = false;
 
     // Make a frozen copy of the ports so we can iterate while new ones might be added or destroyed.
     for (auto* messagePort : copyToVector(m_messagePorts)) {
index 681cdcf..52375fb 100644 (file)
@@ -146,7 +146,7 @@ public:
     void willDestroyDestructionObserver(ContextDestructionObserver&);
 
     // MessagePort is conceptually a kind of ActiveDOMObject, but it needs to be tracked separately for message dispatch.
-    void processMessagePortMessagesSoon();
+    void processMessageWithMessagePortsSoon();
     void dispatchMessagePortEvents();
     void createdMessagePort(MessagePort&);
     void destroyedMessagePort(MessagePort&);
@@ -313,7 +313,7 @@ private:
     bool m_activeDOMObjectsAreStopped { false };
     bool m_inDispatchErrorEvent { false };
     bool m_activeDOMObjectAdditionForbidden { false };
-    bool m_willProcessMessagePortMessagesSoon { false };
+    bool m_willprocessMessageWithMessagePortsSoon { false };
 
 #if !ASSERT_DISABLED
     bool m_inScriptExecutionContextDestructor { false };
diff --git a/Source/WebCore/dom/messageports/MessagePortChannel.cpp b/Source/WebCore/dom/messageports/MessagePortChannel.cpp
new file mode 100644 (file)
index 0000000..f00bf0a
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "MessagePortChannel.h"
+
+#include "Logging.h"
+#include "MessagePortChannelRegistry.h"
+
+namespace WebCore {
+
+Ref<MessagePortChannel> MessagePortChannel::create(MessagePortChannelRegistry& registry, const MessagePortIdentifier& port1, const MessagePortIdentifier& port2)
+{
+    return adoptRef(*new MessagePortChannel(registry, port1, port2));
+}
+
+MessagePortChannel::MessagePortChannel(MessagePortChannelRegistry& registry, const MessagePortIdentifier& port1, const MessagePortIdentifier& port2)
+    : m_registry(registry)
+{
+    relaxAdoptionRequirement();
+
+    m_ports[0] = port1;
+    m_processes[0] = port1.processIdentifier;
+    m_entangledToProcessProtectors[0] = this;
+    m_ports[1] = port2;
+    m_processes[1] = port2.processIdentifier;
+    m_entangledToProcessProtectors[1] = this;
+
+    m_registry.messagePortChannelCreated(*this);
+}
+
+MessagePortChannel::~MessagePortChannel()
+{
+    m_registry.messagePortChannelDestroyed(*this);
+}
+
+bool MessagePortChannel::includesPort(const MessagePortIdentifier& port)
+{
+    Locker<Lock> locker(m_lock);
+
+    return m_ports[0] == port || m_ports[1] == port;
+}
+
+void MessagePortChannel::entanglePortWithProcess(const MessagePortIdentifier& port, ProcessIdentifier process)
+{
+    Locker<Lock> locker(m_lock);
+
+    LOG(MessagePorts, "MessagePortChannel %s (%p) entangling port %s", logString().utf8().data(), this, port.logString().utf8().data());
+
+    ASSERT(port == m_ports[0] || port == m_ports[1]);
+    size_t i = port == m_ports[0] ? 0 : 1;
+
+    ASSERT(!m_processes[i] || *m_processes[i] == process);
+    m_processes[i] = process;
+    m_entangledToProcessProtectors[i] = this;
+}
+
+void MessagePortChannel::disentanglePort(const MessagePortIdentifier& port)
+{
+    Locker<Lock> locker(m_lock);
+
+    LOG(MessagePorts, "MessagePortChannel %s (%p) disentangling port %s", logString().utf8().data(), this, port.logString().utf8().data());
+
+    ASSERT(port == m_ports[0] || port == m_ports[1]);
+    size_t i = port == m_ports[0] ? 0 : 1;
+
+    ASSERT(m_processes[i] || m_isClosed[i]);
+    m_processes[i] = std::nullopt;
+
+    // This set of steps is to guarantee that the lock is unlocked before the
+    // last ref to this object is released.
+    auto protectedThis = WTFMove(m_entangledToProcessProtectors[i]);
+    locker.unlockEarly();
+}
+
+void MessagePortChannel::closePort(const MessagePortIdentifier& port)
+{
+    Locker<Lock> locker(m_lock);
+
+    ASSERT(port == m_ports[0] || port == m_ports[1]);
+    size_t i = port == m_ports[0] ? 0 : 1;
+
+    m_processes[i] = std::nullopt;
+    m_isClosed[i] = true;
+
+    // This set of steps is to guarantee that the lock is unlocked before the
+    // last ref to this object is released.
+    auto protectedThis = makeRef(*this);
+
+    m_pendingMessages[i].clear();
+    m_pendingMessagePortTransfers[i].clear();
+    m_pendingMessageProtectors[i] = nullptr;
+    m_entangledToProcessProtectors[i] = nullptr;
+
+    locker.unlockEarly();
+}
+
+bool MessagePortChannel::postMessageToRemote(MessageWithMessagePorts&& message, const MessagePortIdentifier& remoteTarget)
+{
+    Locker<Lock> locker(m_lock);
+
+    ASSERT(remoteTarget == m_ports[0] || remoteTarget == m_ports[1]);
+    size_t i = remoteTarget == m_ports[0] ? 0 : 1;
+
+    for (auto& channelPair : message.transferredPorts) {
+        auto* channel = m_registry.existingChannelContainingPort(channelPair.first);
+        // One of the ports in the channel might have been closed, therefore removing record of the channel.
+        // That's okay; such ports can still be transferred. We just don't have to protect the channel.
+        if (!channel)
+            continue;
+
+        ASSERT(channel->includesPort(channelPair.second));
+
+#ifndef NDEBUG
+        if (auto* otherChannel = m_registry.existingChannelContainingPort(channelPair.second))
+            ASSERT(channel == otherChannel);
+#endif
+        // Having a pending message should keep a port alive with a ref.
+        // The ref will be cleared after the batch of pending messages has been delivered.
+        m_pendingMessagePortTransfers[i].add(channel);
+    }
+
+    m_pendingMessages[i].append(WTFMove(message));
+    LOG(MessagePorts, "MessagePortChannel %s (%p) now has %zu messages pending on port %s", logString().utf8().data(), this, m_pendingMessages[i].size(), remoteTarget.logString().utf8().data());
+
+    if (m_pendingMessages[i].size() == 1) {
+        m_pendingMessageProtectors[i] = this;
+        return true;
+    }
+
+    ASSERT(m_pendingMessageProtectors[i] == this);
+    return false;
+}
+
+void MessagePortChannel::takeAllMessagesForPort(const MessagePortIdentifier& port, Function<void(Vector<MessageWithMessagePorts>&&, Function<void()>&&)>&& callback)
+{
+    Locker<Lock> locker(m_lock);
+
+    LOG(MessagePorts, "MessagePortChannel %p taking all messages for port %s", this, port.logString().utf8().data());
+
+    ASSERT(port == m_ports[0] || port == m_ports[1]);
+    size_t i = port == m_ports[0] ? 0 : 1;
+
+    if (m_pendingMessages[i].isEmpty()) {
+        callback({ }, [] { });
+        return;
+    }
+
+    ASSERT(m_pendingMessageProtectors[i]);
+
+    Vector<MessageWithMessagePorts> result;
+    result.swap(m_pendingMessages[i]);
+
+    ++m_messageBatchesInFlight;
+
+    LOG(MessagePorts, "There are %zu messages to take for port %s. Taking them now, messages in flight is now %llu", result.size(), port.logString().utf8().data(), m_messageBatchesInFlight);
+
+    auto size = result.size();
+    HashSet<RefPtr<MessagePortChannel>> transferredPortProtectors;
+    transferredPortProtectors.swap(m_pendingMessagePortTransfers[i]);
+
+    locker.unlockEarly();
+    callback(WTFMove(result), [size, this, port, protectedThis = WTFMove(m_pendingMessageProtectors[i]), transferredPortProtectors = WTFMove(transferredPortProtectors)] {
+        UNUSED_PARAM(port);
+        --m_messageBatchesInFlight;
+        LOG(MessagePorts, "Message port channel %s was notified that a batch of %zu message port messages targeted for port %s just completed dispatch, in flight is now %llu", logString().utf8().data(), size, port.logString().utf8().data(), m_messageBatchesInFlight);
+
+    });
+}
+
+bool MessagePortChannel::hasAnyMessagesPendingOrInFlight() const
+{
+    Locker<Lock> locker(m_lock);
+
+    return m_messageBatchesInFlight || !m_pendingMessages[0].isEmpty() || !m_pendingMessages[1].isEmpty();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/dom/messageports/MessagePortChannel.h b/Source/WebCore/dom/messageports/MessagePortChannel.h
new file mode 100644 (file)
index 0000000..2146bd0
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * 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 "MessagePortIdentifier.h"
+#include "MessageWithMessagePorts.h"
+#include "Process.h"
+#include <wtf/HashSet.h>
+#include <wtf/Lock.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class MessagePortChannelRegistry;
+
+class MessagePortChannel : public RefCounted<MessagePortChannel> {
+public:
+    static Ref<MessagePortChannel> create(MessagePortChannelRegistry&, const MessagePortIdentifier& port1, const MessagePortIdentifier& port2);
+
+    ~MessagePortChannel();
+
+    const MessagePortIdentifier& port1() const { return m_ports[0]; }
+    const MessagePortIdentifier& port2() const { return m_ports[1]; }
+
+    bool includesPort(const MessagePortIdentifier&);
+    void entanglePortWithProcess(const MessagePortIdentifier&, ProcessIdentifier);
+    void disentanglePort(const MessagePortIdentifier&);
+    void closePort(const MessagePortIdentifier&);
+    bool postMessageToRemote(MessageWithMessagePorts&&, const MessagePortIdentifier& remoteTarget);
+
+    void takeAllMessagesForPort(const MessagePortIdentifier&, Function<void(Vector<MessageWithMessagePorts>&&, Function<void()>&&)>&&);
+
+    bool hasAnyMessagesPendingOrInFlight() const;
+
+    uint64_t beingTransferredCount();
+
+#ifndef NDEBUG
+    String logString() const { return makeString(m_ports[0].logString(), ":", m_ports[1].logString()); }
+#endif
+
+private:
+    MessagePortChannel(MessagePortChannelRegistry&, const MessagePortIdentifier& port1, const MessagePortIdentifier& port2);
+
+    // FIXME: This lock is to temporarily support synchronous background-thread GC.
+    // It should be removed and this class relegated to main thread only.
+    mutable Lock m_lock;
+
+    MessagePortIdentifier m_ports[2];
+    bool m_isClosed[2] { false, false };
+    std::optional<ProcessIdentifier> m_processes[2];
+    RefPtr<MessagePortChannel> m_entangledToProcessProtectors[2];
+    Vector<MessageWithMessagePorts> m_pendingMessages[2];
+    HashSet<RefPtr<MessagePortChannel>> m_pendingMessagePortTransfers[2];
+    RefPtr<MessagePortChannel> m_pendingMessageProtectors[2];
+    uint64_t m_messageBatchesInFlight { 0 };
+
+    MessagePortChannelRegistry& m_registry;
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/dom/messageports/MessagePortChannelProvider.cpp b/Source/WebCore/dom/messageports/MessagePortChannelProvider.cpp
new file mode 100644 (file)
index 0000000..0a5cd17
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "MessagePortChannelProvider.h"
+
+#include "MessagePortChannelProviderImpl.h"
+#include <wtf/MainThread.h>
+
+namespace WebCore {
+
+static MessagePortChannelProvider* globalProvider;
+
+MessagePortChannelProvider& MessagePortChannelProvider::singleton()
+{
+    static std::once_flag onceFlag;
+    std::call_once(onceFlag, [] {
+        if (!globalProvider)
+            globalProvider = new MessagePortChannelProviderImpl;
+    });
+
+    return *globalProvider;
+}
+
+void MessagePortChannelProvider::setSharedProvider(MessagePortChannelProvider& provider)
+{
+    RELEASE_ASSERT(isMainThread());
+    RELEASE_ASSERT(!globalProvider);
+    globalProvider = &provider;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/dom/messageports/MessagePortChannelProvider.h b/Source/WebCore/dom/messageports/MessagePortChannelProvider.h
new file mode 100644 (file)
index 0000000..9042e07
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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 <wtf/Function.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+struct MessagePortIdentifier;
+struct MessageWithMessagePorts;
+
+class MessagePortChannelProvider {
+public:
+    static MessagePortChannelProvider& singleton();
+    static void setSharedProvider(MessagePortChannelProvider&);
+
+    virtual ~MessagePortChannelProvider() { }
+
+    virtual void createNewMessagePortChannel(const MessagePortIdentifier& local, const MessagePortIdentifier& remote) = 0;
+    virtual void entangleLocalPortInThisProcessToRemote(const MessagePortIdentifier& local, const MessagePortIdentifier& remote) = 0;
+    virtual void messagePortDisentangled(const MessagePortIdentifier& local) = 0;
+    virtual void messagePortClosed(const MessagePortIdentifier& local) = 0;
+    virtual void takeAllMessagesForPort(const MessagePortIdentifier&, Function<void(Vector<MessageWithMessagePorts>&&, Function<void()>&&)>&&) = 0;
+    virtual void postMessageToRemote(MessageWithMessagePorts&&, const MessagePortIdentifier& remoteTarget) = 0;
+
+    virtual bool hasMessagesForPorts_temporarySync(const MessagePortIdentifier&, const MessagePortIdentifier&) = 0;
+
+private:
+
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/dom/messageports/MessagePortChannelProviderImpl.cpp b/Source/WebCore/dom/messageports/MessagePortChannelProviderImpl.cpp
new file mode 100644 (file)
index 0000000..e0a1463
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "MessagePortChannelProviderImpl.h"
+
+#include "MessagePort.h"
+#include <wtf/MainThread.h>
+#include <wtf/RunLoop.h>
+
+namespace WebCore {
+
+MessagePortChannelProviderImpl::~MessagePortChannelProviderImpl()
+{
+    ASSERT_NOT_REACHED();
+}
+
+void MessagePortChannelProviderImpl::performActionOnMainThread(Function<void()>&& action)
+{
+    if (isMainThread())
+        action();
+    else
+        callOnMainThread(WTFMove(action));
+}
+
+void MessagePortChannelProviderImpl::createNewMessagePortChannel(const MessagePortIdentifier& local, const MessagePortIdentifier& remote)
+{
+    performActionOnMainThread([registry = &m_registry, local, remote] {
+        registry->didCreateMessagePortChannel(local, remote);
+    });
+}
+
+void MessagePortChannelProviderImpl::entangleLocalPortInThisProcessToRemote(const MessagePortIdentifier& local, const MessagePortIdentifier& remote)
+{
+    performActionOnMainThread([registry = &m_registry, local, remote] {
+        registry->didEntangleLocalToRemote(local, remote, Process::identifier());
+    });
+}
+
+void MessagePortChannelProviderImpl::messagePortDisentangled(const MessagePortIdentifier& local)
+{
+    performActionOnMainThread([registry = &m_registry, local] {
+        registry->didDisentangleMessagePort(local);
+    });
+}
+
+void MessagePortChannelProviderImpl::messagePortClosed(const MessagePortIdentifier& local)
+{
+    performActionOnMainThread([registry = &m_registry, local] {
+        registry->didCloseMessagePort(local);
+    });
+}
+
+void MessagePortChannelProviderImpl::postMessageToRemote(MessageWithMessagePorts&& message, const MessagePortIdentifier& remoteTarget)
+{
+    performActionOnMainThread([registry = &m_registry, message = WTFMove(message), remoteTarget]() mutable {
+        bool wasFirstMessageInQueue = registry->didPostMessageToRemote(WTFMove(message), remoteTarget);
+        if (wasFirstMessageInQueue) {
+            if (auto remotePort = MessagePort::existingMessagePortForIdentifier(remoteTarget))
+                remotePort->messageAvailable();
+        }
+    });
+}
+
+void MessagePortChannelProviderImpl::takeAllMessagesForPort(const MessagePortIdentifier& port, Function<void(Vector<MessageWithMessagePorts>&&, Function<void()>&&)>&& outerCallback)
+{
+    // It is the responsibility of outerCallback to get itself to the appropriate thread (e.g. WebWorker thread)
+    auto callback = [outerCallback = WTFMove(outerCallback)](Vector<MessageWithMessagePorts>&& messages, Function<void()>&& messageDeliveryCallback) {
+        ASSERT(isMainThread());
+        outerCallback(WTFMove(messages), WTFMove(messageDeliveryCallback));
+    };
+
+    performActionOnMainThread([registry = &m_registry, port, callback = WTFMove(callback)]() mutable {
+        registry->takeAllMessagesForPort(port, WTFMove(callback));
+    });
+}
+
+bool MessagePortChannelProviderImpl::hasMessagesForPorts_temporarySync(const MessagePortIdentifier& port1, const MessagePortIdentifier& port2)
+{
+    // FIXME: Remove this sync function call when GC logic is made asynchronous.
+    return m_registry.hasMessagesForPorts_temporarySync(port1, port2);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/dom/messageports/MessagePortChannelProviderImpl.h b/Source/WebCore/dom/messageports/MessagePortChannelProviderImpl.h
new file mode 100644 (file)
index 0000000..de71298
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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 "MessagePortChannelProvider.h"
+#include "MessagePortChannelRegistry.h"
+
+namespace WebCore {
+
+class MessagePortChannelProviderImpl : public MessagePortChannelProvider {
+public:
+    ~MessagePortChannelProviderImpl() final;
+
+private:
+    void createNewMessagePortChannel(const MessagePortIdentifier& local, const MessagePortIdentifier& remote) final;
+    void entangleLocalPortInThisProcessToRemote(const MessagePortIdentifier& local, const MessagePortIdentifier& remote) final;
+    void messagePortDisentangled(const MessagePortIdentifier& local) final;
+    void messagePortClosed(const MessagePortIdentifier& local) final;
+    void postMessageToRemote(MessageWithMessagePorts&&, const MessagePortIdentifier& remoteTarget) final;
+    void takeAllMessagesForPort(const MessagePortIdentifier&, Function<void(Vector<MessageWithMessagePorts>&&, Function<void()>&&)>&&) final;
+
+    bool hasMessagesForPorts_temporarySync(const MessagePortIdentifier&, const MessagePortIdentifier&) final;
+
+    void performActionOnMainThread(Function<void()>&&);
+
+    MessagePortChannelRegistry m_registry;
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/dom/messageports/MessagePortChannelRegistry.cpp b/Source/WebCore/dom/messageports/MessagePortChannelRegistry.cpp
new file mode 100644 (file)
index 0000000..6a81123
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "MessagePortChannelRegistry.h"
+
+#include <wtf/MainThread.h>
+
+namespace WebCore {
+
+MessagePortChannelRegistry::~MessagePortChannelRegistry()
+{
+    ASSERT(m_openChannels.isEmpty());
+}
+
+void MessagePortChannelRegistry::didCreateMessagePortChannel(const MessagePortIdentifier& port1, const MessagePortIdentifier& port2)
+{
+    LOG(MessagePorts, "Registry: Creating MessagePortChannel %p linking %s and %s", this, port1.logString().utf8().data(), port2.logString().utf8().data());
+    ASSERT(isMainThread());
+
+    MessagePortChannel::create(*this, port1, port2);
+}
+
+void MessagePortChannelRegistry::messagePortChannelCreated(MessagePortChannel& channel)
+{
+    Locker<Lock> locker(m_openChannelsLock);
+    ASSERT(isMainThread());
+
+    auto result = m_openChannels.ensure(channel.port1(), [this, channel = &channel] {
+        return channel;
+    });
+    ASSERT(result.isNewEntry);
+
+    result = m_openChannels.ensure(channel.port2(), [this, channel = &channel] {
+        return channel;
+    });
+    ASSERT(result.isNewEntry);
+}
+
+void MessagePortChannelRegistry::messagePortChannelDestroyed(MessagePortChannel& channel)
+{
+    Locker<Lock> locker(m_openChannelsLock);
+    ASSERT(isMainThread());
+
+    ASSERT(m_openChannels.get(channel.port1()) == &channel);
+    ASSERT(m_openChannels.get(channel.port2()) == &channel);
+
+    m_openChannels.remove(channel.port1());
+    m_openChannels.remove(channel.port2());
+
+    LOG(MessagePorts, "Registry: After removing channel %s there are %u channels left in the registry:", channel.logString().utf8().data(), m_openChannels.size());
+}
+
+void MessagePortChannelRegistry::didEntangleLocalToRemote(const MessagePortIdentifier& local, const MessagePortIdentifier& remote, ProcessIdentifier process)
+{
+    ASSERT(isMainThread());
+    Locker<Lock> locker(m_openChannelsLock);
+
+    // The channel might be gone if the remote side was closed.
+    auto* channel = m_openChannels.get(local);
+    if (!channel)
+        return;
+
+    ASSERT_UNUSED(remote, channel->includesPort(remote));
+
+    channel->entanglePortWithProcess(local, process);
+}
+
+void MessagePortChannelRegistry::didDisentangleMessagePort(const MessagePortIdentifier& port)
+{
+    ASSERT(isMainThread());
+    Locker<Lock> locker(m_openChannelsLock);
+
+    // The channel might be gone if the remote side was closed.
+    auto* channel = m_openChannels.get(port);
+    if (!channel)
+        return;
+
+    locker.unlockEarly();
+    channel->disentanglePort(port);
+}
+
+void MessagePortChannelRegistry::didCloseMessagePort(const MessagePortIdentifier& port)
+{
+    ASSERT(isMainThread());
+    Locker<Lock> locker(m_openChannelsLock);
+
+    LOG(MessagePorts, "Registry: MessagePort %s closed in registry", port.logString().utf8().data());
+
+    auto* channel = m_openChannels.get(port);
+    if (!channel)
+        return;
+
+#ifndef NDEBUG
+    if (channel && channel->hasAnyMessagesPendingOrInFlight())
+        LOG(MessagePorts, "Registry: (Note) The channel closed for port %s had messages pending or in flight", port.logString().utf8().data());
+#endif
+
+    locker.unlockEarly();
+    channel->closePort(port);
+
+    // FIXME: When making message ports be multi-process, this should probably push a notification
+    // to the remaining port to tell it this port closed.
+}
+
+bool MessagePortChannelRegistry::didPostMessageToRemote(MessageWithMessagePorts&& message, const MessagePortIdentifier& remoteTarget)
+{
+    ASSERT(isMainThread());
+    Locker<Lock> locker(m_openChannelsLock);
+
+    LOG(MessagePorts, "Registry: Posting message to MessagePort %s in registry", remoteTarget.logString().utf8().data());
+
+    // The channel might be gone if the remote side was closed.
+    auto* channel = m_openChannels.get(remoteTarget);
+    if (!channel) {
+        LOG(MessagePorts, "Registry: Could not find MessagePortChannel for port %s; It was probably closed. Message will be dropped.", remoteTarget.logString().utf8().data());
+        return false;
+    }
+
+    locker.unlockEarly();
+    return channel->postMessageToRemote(WTFMove(message), remoteTarget);
+}
+
+void MessagePortChannelRegistry::takeAllMessagesForPort(const MessagePortIdentifier& port, Function<void(Vector<MessageWithMessagePorts>&&, Function<void()>&&)>&& callback)
+{
+    ASSERT(isMainThread());
+    Locker<Lock> locker(m_openChannelsLock);
+
+    LOG(MessagePorts, "Registry: Taking all messages for MessagePort %s", port.logString().utf8().data());
+
+    // The channel might be gone if the remote side was closed.
+    auto* channel = m_openChannels.get(port);
+    if (!channel) {
+        callback({ }, [] { });
+        return;
+    }
+
+    locker.unlockEarly();
+    channel->takeAllMessagesForPort(port, WTFMove(callback));
+}
+
+bool MessagePortChannelRegistry::hasMessagesForPorts_temporarySync(const MessagePortIdentifier& port1, const MessagePortIdentifier& port2)
+{
+    // FIXME: Remove this function (and the lock) with a followup patch to do async garbage collection
+    Locker<Lock> locker(m_openChannelsLock);
+
+    auto* channel1 = m_openChannels.get(port1);
+    if (!channel1)
+        return false;
+
+    auto* channel2 = m_openChannels.get(port2);
+    ASSERT_UNUSED(channel2, channel2);
+    if (!channel2)
+        return false;
+
+    ASSERT(channel1 == channel2);
+
+    return channel1->hasAnyMessagesPendingOrInFlight();
+}
+
+MessagePortChannel* MessagePortChannelRegistry::existingChannelContainingPort(const MessagePortIdentifier& port)
+{
+    ASSERT(isMainThread());
+
+    Locker<Lock> locker(m_openChannelsLock);
+
+    return m_openChannels.get(port);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/dom/messageports/MessagePortChannelRegistry.h b/Source/WebCore/dom/messageports/MessagePortChannelRegistry.h
new file mode 100644 (file)
index 0000000..45d0a57
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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 "MessagePortChannel.h"
+#include "MessagePortIdentifier.h"
+#include "Process.h"
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+class MessagePortChannelRegistry {
+public:
+    ~MessagePortChannelRegistry();
+    
+    void didCreateMessagePortChannel(const MessagePortIdentifier& port1, const MessagePortIdentifier& port2);
+    void didEntangleLocalToRemote(const MessagePortIdentifier& local, const MessagePortIdentifier& remote, ProcessIdentifier);
+    void didDisentangleMessagePort(const MessagePortIdentifier& local);
+    void didCloseMessagePort(const MessagePortIdentifier& local);
+    bool didPostMessageToRemote(MessageWithMessagePorts&&, const MessagePortIdentifier& remoteTarget);
+    void takeAllMessagesForPort(const MessagePortIdentifier&, Function<void(Vector<MessageWithMessagePorts>&&, Function<void()>&&)>&&);
+
+    MessagePortChannel* existingChannelContainingPort(const MessagePortIdentifier&);
+    bool hasMessagesForPorts_temporarySync(const MessagePortIdentifier&, const MessagePortIdentifier&);
+
+    void messagePortChannelCreated(MessagePortChannel&);
+    void messagePortChannelDestroyed(MessagePortChannel&);
+
+private:
+
+    // FIXME: The need for the open channels lock is temporary.
+    // It should be removed and this class should be main-thread only.
+    Lock m_openChannelsLock;
+    HashMap<MessagePortIdentifier, MessagePortChannel*> m_openChannels;
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/dom/messageports/MessageWithMessagePorts.cpp b/Source/WebCore/dom/messageports/MessageWithMessagePorts.cpp
new file mode 100644 (file)
index 0000000..6bee1a8
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "MessageWithMessagePorts.h"
+
+namespace WebCore {
+
+} // namespace WebCore
diff --git a/Source/WebCore/dom/messageports/MessageWithMessagePorts.h b/Source/WebCore/dom/messageports/MessageWithMessagePorts.h
new file mode 100644 (file)
index 0000000..969a62a
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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 "SerializedScriptValue.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+struct MessagePortIdentifier;
+
+// When a message port is transferred, it is represented by a pair of identifiers.
+// The first identifier is the port being transferred and the second is its remote port.
+typedef Vector<std::pair<WebCore::MessagePortIdentifier, WebCore::MessagePortIdentifier>> TransferredMessagePortArray;
+
+struct MessageWithMessagePorts {
+    RefPtr<SerializedScriptValue> message;
+    TransferredMessagePortArray transferredPorts;
+};
+
+} // namespace WebCore
index 390e754..0c2361a 100644 (file)
@@ -71,6 +71,7 @@
 #include "MediaQueryList.h"
 #include "MediaQueryMatcher.h"
 #include "MessageEvent.h"
+#include "MessageWithMessagePorts.h"
 #include "NavigationScheduler.h"
 #include "Navigator.h"
 #include "Page.h"
@@ -146,12 +147,11 @@ using namespace Inspector;
 
 class PostMessageTimer : public TimerBase {
 public:
-    PostMessageTimer(DOMWindow& window, Ref<SerializedScriptValue>&& message, const String& sourceOrigin, DOMWindow& source, std::unique_ptr<MessagePortChannelArray> channels, RefPtr<SecurityOrigin>&& targetOrigin, RefPtr<ScriptCallStack>&& stackTrace)
+    PostMessageTimer(DOMWindow& window, MessageWithMessagePorts&& message, const String& sourceOrigin, DOMWindow& source, RefPtr<SecurityOrigin>&& targetOrigin, RefPtr<ScriptCallStack>&& stackTrace)
         : m_window(window)
         , m_message(WTFMove(message))
         , m_origin(sourceOrigin)
         , m_source(source)
-        , m_channels(WTFMove(channels))
         , m_targetOrigin(WTFMove(targetOrigin))
         , m_stackTrace(stackTrace)
         , m_userGestureToForward(UserGestureIndicator::currentUserGesture())
@@ -160,7 +160,7 @@ public:
 
     Ref<MessageEvent> event(ScriptExecutionContext& context)
     {
-        return MessageEvent::create(MessagePort::entanglePorts(context, WTFMove(m_channels)), WTFMove(m_message), m_origin, { }, MessageEventSource(RefPtr<DOMWindow>(WTFMove(m_source))));
+        return MessageEvent::create(MessagePort::entanglePorts(context, WTFMove(m_message.transferredPorts)), WTFMove(m_message.message), m_origin, { }, MessageEventSource(RefPtr<DOMWindow>(WTFMove(m_source))));
     }
 
     SecurityOrigin* targetOrigin() const { return m_targetOrigin.get(); }
@@ -177,10 +177,9 @@ private:
     }
 
     Ref<DOMWindow> m_window;
-    Ref<SerializedScriptValue> m_message;
+    MessageWithMessagePorts m_message;
     String m_origin;
     Ref<DOMWindow> m_source;
-    std::unique_ptr<MessagePortChannelArray> m_channels;
     RefPtr<SecurityOrigin> m_targetOrigin;
     RefPtr<ScriptCallStack> m_stackTrace;
     RefPtr<UserGestureToken> m_userGestureToForward;
@@ -937,13 +936,13 @@ ExceptionOr<void> DOMWindow::postMessage(JSC::ExecState& state, DOMWindow& incum
     }
 
     Vector<RefPtr<MessagePort>> ports;
-    auto message = SerializedScriptValue::create(state, messageValue, WTFMove(transfer), ports, SerializationContext::WindowPostMessage);
-    if (message.hasException())
-        return message.releaseException();
+    auto messageData = SerializedScriptValue::create(state, messageValue, WTFMove(transfer), ports, SerializationContext::WindowPostMessage);
+    if (messageData.hasException())
+        return messageData.releaseException();
 
-    auto channels = MessagePort::disentanglePorts(WTFMove(ports));
-    if (channels.hasException())
-        return channels.releaseException();
+    auto disentangledPorts = MessagePort::disentanglePorts(WTFMove(ports));
+    if (disentangledPorts.hasException())
+        return disentangledPorts.releaseException();
 
     // Capture the source of the message.  We need to do this synchronously
     // in order to capture the source of the message correctly.
@@ -956,8 +955,10 @@ ExceptionOr<void> DOMWindow::postMessage(JSC::ExecState& state, DOMWindow& incum
     if (InspectorInstrumentation::consoleAgentEnabled(sourceDocument))
         stackTrace = createScriptCallStack(JSMainThreadExecState::currentState());
 
+    MessageWithMessagePorts message { messageData.releaseReturnValue(), disentangledPorts.releaseReturnValue() };
+
     // Schedule the message.
-    auto* timer = new PostMessageTimer(*this, message.releaseReturnValue(), sourceOrigin, incumbentWindow, channels.releaseReturnValue(), WTFMove(target), WTFMove(stackTrace));
+    auto* timer = new PostMessageTimer(*this, WTFMove(message), sourceOrigin, incumbentWindow, WTFMove(target), WTFMove(stackTrace));
     timer->startOneShot(0_s);
 
     InspectorInstrumentation::didPostMessage(*m_frame, *timer, state);
index cf7020c..e0f441d 100644 (file)
@@ -69,6 +69,7 @@ namespace WebCore {
     M(MediaStream) \
     M(MediaSourceSamples) \
     M(MemoryPressure) \
+    M(MessagePorts) \
     M(Network) \
     M(NotYetImplemented) \
     M(PageCache) \
index 3289993..ba9989c 100644 (file)
@@ -72,7 +72,8 @@ ExceptionOr<void> DedicatedWorkerGlobalScope::postMessage(JSC::ExecState& state,
     auto channels = MessagePort::disentanglePorts(WTFMove(ports));
     if (channels.hasException())
         return channels.releaseException();
-    thread().workerObjectProxy().postMessageToWorkerObject(message.releaseReturnValue(), channels.releaseReturnValue());
+
+    thread().workerObjectProxy().postMessageToWorkerObject({ message.releaseReturnValue(), channels.releaseReturnValue() });
     return { };
 }
 
index 386f0e5..9278bc8 100644 (file)
@@ -124,7 +124,8 @@ ExceptionOr<void> Worker::postMessage(JSC::ExecState& state, JSC::JSValue messag
     auto channels = MessagePort::disentanglePorts(WTFMove(ports));
     if (channels.hasException())
         return channels.releaseException();
-    m_contextProxy.postMessageToWorkerGlobalScope(message.releaseReturnValue(), channels.releaseReturnValue());
+
+    m_contextProxy.postMessageToWorkerGlobalScope({ message.releaseReturnValue(), channels.releaseReturnValue() });
     return { };
 }
 
index 7e5d290..6372539 100644 (file)
@@ -31,7 +31,7 @@
 
 #pragma once
 
-#include "MessagePortChannel.h"
+#include "MessageWithMessagePorts.h"
 #include <runtime/RuntimeFlags.h>
 #include <wtf/MonotonicTime.h>
 
@@ -52,7 +52,7 @@ public:
 
     virtual void startWorkerGlobalScope(const URL& scriptURL, const String& userAgent, bool isOnline, const String& sourceCode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, MonotonicTime timeOrigin, JSC::RuntimeFlags, PAL::SessionID) = 0;
     virtual void terminateWorkerGlobalScope() = 0;
-    virtual void postMessageToWorkerGlobalScope(Ref<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>&&) = 0;
+    virtual void postMessageToWorkerGlobalScope(MessageWithMessagePorts&&) = 0;
     virtual bool hasPendingActivity() const = 0;
     virtual void workerObjectDestroyed() = 0;
     virtual void notifyNetworkStateChange(bool isOnline) = 0;
index ed024a2..4d98fc3 100644 (file)
@@ -46,6 +46,7 @@
 #include <wtf/MainThread.h>
 #include <wtf/RunLoop.h>
 
+
 namespace WebCore {
 
 WorkerGlobalScopeProxy& WorkerGlobalScopeProxy::create(Worker& worker)
@@ -96,28 +97,28 @@ void WorkerMessagingProxy::startWorkerGlobalScope(const URL& scriptURL, const St
     m_inspectorProxy->workerStarted(m_scriptExecutionContext.get(), thread.ptr(), scriptURL);
 }
 
-void WorkerMessagingProxy::postMessageToWorkerObject(Ref<SerializedScriptValue>&& message, std::unique_ptr<MessagePortChannelArray>&& channels)
+void WorkerMessagingProxy::postMessageToWorkerObject(MessageWithMessagePorts&& message)
 {
-    m_scriptExecutionContext->postTask([this, channels = WTFMove(channels), message = WTFMove(message)] (ScriptExecutionContext& context) mutable {
+    m_scriptExecutionContext->postTask([this, message = WTFMove(message)] (ScriptExecutionContext& context) mutable {
         Worker* workerObject = this->workerObject();
         if (!workerObject || askedToTerminate())
             return;
 
-        auto ports = MessagePort::entanglePorts(context, WTFMove(channels));
-        workerObject->dispatchEvent(MessageEvent::create(WTFMove(ports), WTFMove(message)));
+        auto ports = MessagePort::entanglePorts(context, WTFMove(message.transferredPorts));
+        workerObject->dispatchEvent(MessageEvent::create(WTFMove(ports), WTFMove(message.message)));
     });
 }
 
-void WorkerMessagingProxy::postMessageToWorkerGlobalScope(Ref<SerializedScriptValue>&& message, std::unique_ptr<MessagePortChannelArray>&& channels)
+void WorkerMessagingProxy::postMessageToWorkerGlobalScope(MessageWithMessagePorts&& message)
 {
     if (m_askedToTerminate)
         return;
 
-    ScriptExecutionContext::Task task([channels = WTFMove(channels), message = WTFMove(message)] (ScriptExecutionContext& scriptContext) mutable {
+    ScriptExecutionContext::Task task([message = WTFMove(message)] (ScriptExecutionContext& scriptContext) mutable {
         ASSERT_WITH_SECURITY_IMPLICATION(scriptContext.isWorkerGlobalScope());
         auto& context = static_cast<DedicatedWorkerGlobalScope&>(scriptContext);
-        auto ports = MessagePort::entanglePorts(scriptContext, WTFMove(channels));
-        context.dispatchEvent(MessageEvent::create(WTFMove(ports), WTFMove(message)));
+        auto ports = MessagePort::entanglePorts(scriptContext, WTFMove(message.transferredPorts));
+        context.dispatchEvent(MessageEvent::create(WTFMove(ports), WTFMove(message.message)));
         context.thread().workerObjectProxy().confirmMessageFromWorkerObject(context.hasPendingActivity());
     });
 
index e9fa148..4eff2fa 100644 (file)
@@ -48,14 +48,14 @@ private:
     // (Only use these functions in the worker object thread.)
     void startWorkerGlobalScope(const URL& scriptURL, const String& userAgent, bool isOnline, const String& sourceCode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, MonotonicTime timeOrigin, JSC::RuntimeFlags, PAL::SessionID) final;
     void terminateWorkerGlobalScope() final;
-    void postMessageToWorkerGlobalScope(Ref<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>&&) final;
+    void postMessageToWorkerGlobalScope(MessageWithMessagePorts&&) final;
     bool hasPendingActivity() const final;
     void workerObjectDestroyed() final;
     void notifyNetworkStateChange(bool isOnline) final;
 
     // Implementation of WorkerObjectProxy.
     // (Only use these functions in the worker context thread.)
-    void postMessageToWorkerObject(Ref<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>&&) final;
+    void postMessageToWorkerObject(MessageWithMessagePorts&&) final;
     void postExceptionToWorkerObject(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL) final;
     void confirmMessageFromWorkerObject(bool hasPendingActivity) final;
     void reportPendingActivity(bool hasPendingActivity) final;
index 28e5c6e..2801314 100644 (file)
 
 #pragma once
 
+#include "MessageWithMessagePorts.h"
 #include "WorkerReportingProxy.h"
-#include "MessagePort.h"
 #include <memory>
 
 namespace WebCore {
 
-    class MessagePortChannel;
+// A proxy to talk to the worker object.
+class WorkerObjectProxy : public WorkerReportingProxy {
+public:
+    virtual void postMessageToWorkerObject(MessageWithMessagePorts&&) = 0;
 
-    // A proxy to talk to the worker object.
-    class WorkerObjectProxy : public WorkerReportingProxy {
-    public:
-        virtual void postMessageToWorkerObject(Ref<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>&&) = 0;
+    virtual void confirmMessageFromWorkerObject(bool hasPendingActivity) = 0;
+    virtual void reportPendingActivity(bool hasPendingActivity) = 0;
 
-        virtual void confirmMessageFromWorkerObject(bool hasPendingActivity) = 0;
-        virtual void reportPendingActivity(bool hasPendingActivity) = 0;
-
-        // No need to notify the parent page context when dedicated workers are closing.
-        void workerGlobalScopeClosed() override { }
-    };
+    // No need to notify the parent page context when dedicated workers are closing.
+    void workerGlobalScopeClosed() override { }
+};
 
 } // namespace WebCore
index 507358c..e9f8cb0 100644 (file)
@@ -111,7 +111,7 @@ ExceptionOr<void> ServiceWorker::postMessage(ScriptExecutionContext& context, JS
 
     // FIXME: Support sending the channels.
     auto channels = channelsOrException.releaseReturnValue();
-    if (channels && !channels->isEmpty())
+    if (!channels.isEmpty())
         return Exception { NotSupportedError, ASCIILiteral("Passing MessagePort objects to postMessage is not yet supported") };
 
     ServiceWorkerOrClientIdentifier sourceIdentifier;
index 874a33c..4f0eed7 100644 (file)
@@ -99,7 +99,7 @@ ExceptionOr<void> ServiceWorkerClient::postMessage(ScriptExecutionContext& conte
 
     // FIXME: Support sending the channels.
     auto channels = channelsOrException.releaseReturnValue();
-    if (channels && !channels->isEmpty())
+    if (!channels.isEmpty())
         return Exception { NotSupportedError, ASCIILiteral("Passing MessagePort objects to postMessage is not yet supported") };
 
     auto sourceIdentifier = downcast<ServiceWorkerGlobalScope>(context).thread().identifier();
index bcae571..6a6c9a4 100644 (file)
  */
 
 #include "config.h"
-
-#if ENABLE(SERVICE_WORKER)
 #include "SWContextManager.h"
 
+#if ENABLE(SERVICE_WORKER)
 #include "Logging.h"
+#include "MessageWithMessagePorts.h"
 #include "ServiceWorkerClientIdentifier.h"
 #include "ServiceWorkerGlobalScope.h"
 #include <unistd.h>
@@ -84,7 +84,7 @@ void SWContextManager::postMessageToServiceWorker(ServiceWorkerIdentifier destin
     ASSERT(!serviceWorker->isTerminatingOrTerminated());
 
     // FIXME: We should pass valid MessagePortChannels.
-    serviceWorker->thread().postMessageToServiceWorker(WTFMove(message), nullptr, WTFMove(sourceData));
+    serviceWorker->thread().postMessageToServiceWorker({ WTFMove(message), { } }, WTFMove(sourceData));
 }
 
 void SWContextManager::fireInstallEvent(ServiceWorkerIdentifier identifier)
index b7324e0..2eb3853 100644 (file)
@@ -61,7 +61,7 @@ public:
 private:
     void postExceptionToWorkerObject(const String&, int, int, const String&) final { };
     void workerGlobalScopeDestroyed() final { };
-    void postMessageToWorkerObject(Ref<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>&&) final { };
+    void postMessageToWorkerObject(MessageWithMessagePorts&&) final { };
     void confirmMessageFromWorkerObject(bool) final { };
     void reportPendingActivity(bool) final { };
 };
@@ -102,18 +102,18 @@ void ServiceWorkerThread::postFetchTask(Ref<ServiceWorkerFetch::Client>&& client
     }, WorkerRunLoop::defaultMode());
 }
 
-static void fireMessageEvent(ServiceWorkerGlobalScope& scope, Ref<SerializedScriptValue>&& message, std::unique_ptr<MessagePortChannelArray>&& channels, ExtendableMessageEventSource&& source, Ref<SecurityOrigin>&& sourceOrigin)
+static void fireMessageEvent(ServiceWorkerGlobalScope& scope, MessageWithMessagePorts&& message, ExtendableMessageEventSource&& source, Ref<SecurityOrigin>&& sourceOrigin)
 {
-    auto ports = MessagePort::entanglePorts(scope, WTFMove(channels));
-    auto messageEvent = ExtendableMessageEvent::create(WTFMove(ports), WTFMove(message), sourceOrigin->toString(), { }, source);
+    auto ports = MessagePort::entanglePorts(scope, WTFMove(message.transferredPorts));
+    auto messageEvent = ExtendableMessageEvent::create(WTFMove(ports), WTFMove(message.message), sourceOrigin->toString(), { }, source);
     scope.dispatchEvent(messageEvent);
     scope.thread().workerObjectProxy().confirmMessageFromWorkerObject(scope.hasPendingActivity());
     scope.updateExtendedEventsSet(messageEvent.ptr());
 }
 
-void ServiceWorkerThread::postMessageToServiceWorker(Ref<SerializedScriptValue>&& message, std::unique_ptr<MessagePortChannelArray>&& channels, ServiceWorkerOrClientData&& sourceData)
+void ServiceWorkerThread::postMessageToServiceWorker(MessageWithMessagePorts&& message, ServiceWorkerOrClientData&& sourceData)
 {
-    runLoop().postTask([channels = WTFMove(channels), message = WTFMove(message), sourceData = WTFMove(sourceData)] (auto& context) mutable {
+    runLoop().postTask([message = WTFMove(message), sourceData = WTFMove(sourceData)] (auto& context) mutable {
         auto& serviceWorkerGlobalScope = downcast<ServiceWorkerGlobalScope>(context);
         RefPtr<SecurityOrigin> sourceOrigin;
         ExtendableMessageEventSource source;
@@ -126,7 +126,7 @@ void ServiceWorkerThread::postMessageToServiceWorker(Ref<SerializedScriptValue>&
             sourceOrigin = SecurityOrigin::create(sourceWorker->scriptURL());
             source = WTFMove(sourceWorker);
         }
-        fireMessageEvent(serviceWorkerGlobalScope, WTFMove(message), WTFMove(channels), ExtendableMessageEventSource { source }, sourceOrigin.releaseNonNull());
+        fireMessageEvent(serviceWorkerGlobalScope, WTFMove(message), ExtendableMessageEventSource { source }, sourceOrigin.releaseNonNull());
     });
 }
 
index c35592a..92184da 100644 (file)
@@ -40,12 +40,11 @@ class ExtendableEvent;
 class MessagePortChannel;
 class SerializedScriptValue;
 class WorkerObjectProxy;
+struct MessageWithMessagePorts;
 struct ServiceWorkerClientData;
 struct ServiceWorkerClientIdentifier;
 struct ServiceWorkerContextData;
 
-using MessagePortChannelArray = Vector<RefPtr<MessagePortChannel>, 1>;
-
 class ServiceWorkerThread : public WorkerThread {
 public:
     template<typename... Args> static Ref<ServiceWorkerThread> create(Args&&... args)
@@ -57,7 +56,7 @@ public:
     WorkerObjectProxy& workerObjectProxy() const { return m_workerObjectProxy; }
 
     WEBCORE_EXPORT void postFetchTask(Ref<ServiceWorkerFetch::Client>&&, std::optional<ServiceWorkerClientIdentifier>&&, ResourceRequest&&, String&& referrer, FetchOptions&&);
-    WEBCORE_EXPORT void postMessageToServiceWorker(Ref<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>&&, ServiceWorkerOrClientData&& sourceData);
+    WEBCORE_EXPORT void postMessageToServiceWorker(MessageWithMessagePorts&&, ServiceWorkerOrClientData&& sourceData);
 
     void fireInstallEvent();
     void fireActivateEvent();