Changeset 226336 in webkit
- Timestamp:
- Jan 2, 2018 2:42:16 PM (6 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 1 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r226333 r226336 1 2018-01-02 Brady Eidson <beidson@apple.com> 2 3 Identify MessagePorts by a globally unique MessagePortIdentifier. 4 https://bugs.webkit.org/show_bug.cgi?id=181172 5 6 Reviewed by Alex Christensen. 7 8 No new tests (Behavior change covered by all existing tests). 9 10 This cleans up the abstract MessagePortChannel interface to be in terms of identifiers 11 instead of actual MessagePort objects. 12 13 The identifiers are compounded with the current ProcessIdentifier meaning they are global 14 across all processes for the running UI process, enabling easy cross-process communication. 15 16 (Actual cross-process communication comes in a followup) 17 18 * WebCore.xcodeproj/project.pbxproj: 19 20 * dom/InProcessMessagePortChannel.cpp: 21 (WebCore::InProcessMessagePortChannel::createChannelBetweenPorts): 22 (WebCore::InProcessMessagePortChannel::isConnectedTo): 23 (WebCore::InProcessMessagePortChannel::entangleWithRemoteIfOpen): 24 (WebCore::InProcessMessagePortChannel::entangleIfOpen): Deleted. 25 * dom/InProcessMessagePortChannel.h: 26 27 * dom/MessageChannel.cpp: 28 (WebCore::MessageChannel::MessageChannel): 29 (WebCore::m_port2): 30 31 * dom/MessagePort.cpp: 32 (WebCore::allMessagePortsLock): 33 (WebCore::MessagePort::ref const): 34 (WebCore::MessagePort::deref const): 35 (WebCore::MessagePort::existingMessagePortForIdentifier): 36 (WebCore::MessagePort::MessagePort): 37 (WebCore::MessagePort::~MessagePort): 38 (WebCore::MessagePort::postMessage): 39 (WebCore::MessagePort::entangleWithRemote): 40 (WebCore::MessagePort::entanglePorts): 41 (WebCore::MessagePort::entangle): Deleted. 42 * dom/MessagePort.h: 43 44 * dom/MessagePortChannel.h: 45 46 * dom/MessagePortIdentifier.h: Added. 47 (WebCore::operator==): 48 (WebCore::MessagePortIdentifier::encode const): 49 (WebCore::MessagePortIdentifier::decode): 50 (WebCore::MessagePortIdentifier::hash const): 51 (WTF::MessagePortIdentifierHash::hash): 52 (WTF::MessagePortIdentifierHash::equal): 53 (WTF::HashTraits<WebCore::MessagePortIdentifier>::emptyValue): 54 (WTF::HashTraits<WebCore::MessagePortIdentifier>::constructDeletedValue): 55 (WTF::HashTraits<WebCore::MessagePortIdentifier>::isDeletedValue): 56 1 57 2018-01-02 Youenn Fablet <youenn@apple.com> 2 58 -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r226332 r226336 1457 1457 51F645971F4A686F00B54DED /* SWServerRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F645941F4A684F00B54DED /* SWServerRegistration.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1458 1458 51F645D51FECDBCE00B54DED /* Process.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F645D31FECDBC800B54DED /* Process.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1459 51F645E01FF4594E00B54DED /* MessagePortIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F645DE1FF4594B00B54DED /* MessagePortIdentifier.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1459 1460 51F798F01BE880E7008AE491 /* IDBIndexInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F798EC1BE880D3008AE491 /* IDBIndexInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1460 1461 51F886C01F32923100C193EF /* JSNavigatorServiceWorker.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F886BF1F32920700C193EF /* JSNavigatorServiceWorker.h */; }; … … 7927 7928 51F645D21FECDBC800B54DED /* Process.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Process.cpp; sourceTree = "<group>"; }; 7928 7929 51F645D31FECDBC800B54DED /* Process.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Process.h; sourceTree = "<group>"; }; 7930 51F645DE1FF4594B00B54DED /* MessagePortIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessagePortIdentifier.h; sourceTree = "<group>"; }; 7929 7931 51F6A3D50663BF04004D2919 /* HTMLCanvasElement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLCanvasElement.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; 7930 7932 51F6A3D60663BF04004D2919 /* HTMLCanvasElement.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = HTMLCanvasElement.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; … … 25514 25516 512B57BE1FE9902D000A1E5E /* MessagePortChannel.cpp */, 25515 25517 41BF700A0FE86F49005E8DEC /* MessagePortChannel.h */, 25518 51F645DE1FF4594B00B54DED /* MessagePortIdentifier.h */, 25516 25519 CB8CF0151A934B43000D510B /* Microtasks.cpp */, 25517 25520 53B895AD19DC7C37009CAA93 /* Microtasks.h */, … … 28531 28534 E1ADECBF0E76ACF1004A1A5E /* MessagePort.h in Headers */, 28532 28535 41BF700C0FE86F49005E8DEC /* MessagePortChannel.h in Headers */, 28536 51F645E01FF4594E00B54DED /* MessagePortIdentifier.h in Headers */, 28533 28537 53B895AF19DC7ED9009CAA93 /* Microtasks.h in Headers */, 28534 28538 BC772C4F0C4EB3040083285F /* MIMETypeRegistry.h in Headers */, -
trunk/Source/WebCore/dom/InProcessMessagePortChannel.cpp
r226252 r226336 43 43 channel2->m_entangledChannel = channel1.ptr(); 44 44 45 port1.entangle (WTFMove(channel2));46 port2.entangle (WTFMove(channel1));45 port1.entangleWithRemote(WTFMove(channel2)); 46 port2.entangleWithRemote(WTFMove(channel1)); 47 47 } 48 48 … … 82 82 } 83 83 84 bool InProcessMessagePortChannel::isConnectedTo( MessagePort& port)84 bool InProcessMessagePortChannel::isConnectedTo(const MessagePortIdentifier& identifier) 85 85 { 86 86 // FIXME: What guarantees that the result remains the same after we release the lock? 87 87 Locker<Lock> locker(m_lock); 88 return m_remotePort == &port;88 return m_remotePort && m_remotePort->identifier() == identifier; 89 89 } 90 90 91 bool InProcessMessagePortChannel::entangle IfOpen(MessagePort& port)91 bool InProcessMessagePortChannel::entangleWithRemoteIfOpen(const MessagePortIdentifier& identifier) 92 92 { 93 93 // We can't call member functions on our remote pair while holding our mutex or we'll deadlock, … … 102 102 return false; 103 103 104 remote->setRemotePort(&port); 104 auto entangledPort = MessagePort::existingMessagePortForIdentifier(identifier); 105 ASSERT(entangledPort); 106 107 remote->setRemotePort(entangledPort.get()); 105 108 106 109 return true; -
trunk/Source/WebCore/dom/InProcessMessagePortChannel.h
r226252 r226336 39 39 void postMessageToRemote(Ref<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>&&) final; 40 40 Deque<std::unique_ptr<EventData>> takeAllMessagesFromRemote() final; 41 bool isConnectedTo( MessagePort&) final;42 bool entangle IfOpen(MessagePort&) final;41 bool isConnectedTo(const MessagePortIdentifier&) final; 42 bool entangleWithRemoteIfOpen(const MessagePortIdentifier&) final; 43 43 void disentangle() final; 44 44 bool hasPendingActivity() final; -
trunk/Source/WebCore/dom/MessageChannel.cpp
r226252 r226336 34 34 35 35 MessageChannel::MessageChannel(ScriptExecutionContext& context) 36 : m_port1(MessagePort::create(context ))37 , m_port2(MessagePort::create(context ))36 : m_port1(MessagePort::create(context, { Process::identifier(), generateObjectIdentifier<MessagePortIdentifier::PortIdentifierType>() })) 37 , m_port2(MessagePort::create(context, { Process::identifier(), generateObjectIdentifier<MessagePortIdentifier::PortIdentifierType>() })) 38 38 { 39 39 MessagePortChannel::createChannelBetweenPorts(*m_port1, *m_port2); -
trunk/Source/WebCore/dom/MessagePort.cpp
r226252 r226336 35 35 namespace WebCore { 36 36 37 MessagePort::MessagePort(ScriptExecutionContext& scriptExecutionContext) 37 static HashMap<MessagePortIdentifier, MessagePort*>& allMessagePorts() 38 { 39 static NeverDestroyed<HashMap<MessagePortIdentifier, MessagePort*>> map; 40 return map; 41 } 42 43 static Lock& allMessagePortsLock() 44 { 45 static NeverDestroyed<Lock> lock; 46 return lock; 47 } 48 49 void MessagePort::ref() const 50 { 51 ++m_refCount; 52 } 53 54 void MessagePort::deref() const 55 { 56 // MessagePort::existingMessagePortForIdentifier() is unique in that it holds a raw pointer to a MessagePort 57 // but might create a RefPtr from it. 58 // If that happens on one thread at the same time that a MessagePort is being deref'ed and destroyed on a 59 // different thread then Bad Things could happen. 60 // This custom deref() function is designed to handle that contention by guaranteeing that nobody can be 61 // creating a RefPtr inside existingMessagePortForIdentifier while the object is mid-deletion. 62 63 if (!--m_refCount) { 64 Locker<Lock> locker(allMessagePortsLock()); 65 66 if (m_refCount) 67 return; 68 69 allMessagePorts().remove(m_identifier); 70 delete this; 71 } 72 } 73 74 RefPtr<MessagePort> MessagePort::existingMessagePortForIdentifier(const MessagePortIdentifier& identifier) 75 { 76 Locker<Lock> locker(allMessagePortsLock()); 77 78 return allMessagePorts().get(identifier); 79 } 80 81 MessagePort::MessagePort(ScriptExecutionContext& scriptExecutionContext, const MessagePortIdentifier& identifier) 38 82 : ActiveDOMObject(&scriptExecutionContext) 39 { 83 , m_identifier(identifier) 84 { 85 Locker<Lock> locker(allMessagePortsLock()); 86 allMessagePorts().set(m_identifier, this); 87 40 88 m_scriptExecutionContext->createdMessagePort(*this); 41 89 suspendIfNeeded(); … … 46 94 MessagePort::~MessagePort() 47 95 { 96 ASSERT(allMessagePortsLock().isLocked()); 97 48 98 close(); 49 99 if (m_scriptExecutionContext) … … 66 116 if (!ports.isEmpty()) { 67 117 for (auto& dataPort : ports) { 68 if (dataPort == this || m_entangledChannel->isConnectedTo( *dataPort))118 if (dataPort == this || m_entangledChannel->isConnectedTo(dataPort->identifier())) 69 119 return Exception { DataCloneError }; 70 120 } 121 71 122 auto disentangleResult = MessagePort::disentanglePorts(WTFMove(ports)); 72 123 if (disentangleResult.hasException()) … … 124 175 } 125 176 126 void MessagePort::entangle (RefPtr<MessagePortChannel>&& remote)177 void MessagePort::entangleWithRemote(RefPtr<MessagePortChannel>&& remote) 127 178 { 128 179 // Only invoked to set our initial entanglement. … … 131 182 132 183 // Don't entangle the ports if the channel is closed. 133 if (remote->entangle IfOpen(*this))184 if (remote->entangleWithRemoteIfOpen(m_identifier)) 134 185 m_entangledChannel = WTFMove(remote); 135 186 } … … 211 262 portArray.reserveInitialCapacity(channels->size()); 212 263 for (unsigned int i = 0; i < channels->size(); ++i) { 213 auto port = MessagePort::create(context );214 port->entangle (WTFMove((*channels)[i]));264 auto port = MessagePort::create(context, { Process::identifier(), generateObjectIdentifier<MessagePortIdentifier::PortIdentifierType>() }); 265 port->entangleWithRemote(WTFMove((*channels)[i])); 215 266 portArray.uncheckedAppend(WTFMove(port)); 216 267 } -
trunk/Source/WebCore/dom/MessagePort.h
r226252 r226336 31 31 #include "ExceptionOr.h" 32 32 #include "MessagePortChannel.h" 33 #include "MessagePortIdentifier.h" 33 34 34 35 namespace JSC { … … 42 43 class Frame; 43 44 44 class MessagePort final : public ThreadSafeRefCounted<MessagePort>, publicActiveDOMObject, public EventTargetWithInlineData {45 class MessagePort final : public ActiveDOMObject, public EventTargetWithInlineData { 45 46 public: 46 static Ref<MessagePort> create(ScriptExecutionContext& scriptExecutionContext ) { return adoptRef(*new MessagePort(scriptExecutionContext)); }47 static Ref<MessagePort> create(ScriptExecutionContext& scriptExecutionContext, const MessagePortIdentifier& identifier) { return adoptRef(*new MessagePort(scriptExecutionContext, identifier)); } 47 48 virtual ~MessagePort(); 48 49 … … 52 53 void close(); 53 54 54 void entangle (RefPtr<MessagePortChannel>&&);55 void entangleWithRemote(RefPtr<MessagePortChannel>&&); 55 56 56 57 // Returns nullptr if the passed-in vector is empty. 57 58 static ExceptionOr<std::unique_ptr<MessagePortChannelArray>> disentanglePorts(Vector<RefPtr<MessagePort>>&&); 58 59 59 static Vector<RefPtr<MessagePort>> entanglePorts(ScriptExecutionContext&, std::unique_ptr<MessagePortChannelArray>&&); 60 static RefPtr<MessagePort> existingMessagePortForIdentifier(const MessagePortIdentifier&); 60 61 61 62 void messageAvailable(); … … 69 70 MessagePort* locallyEntangledPort() const; 70 71 71 using ThreadSafeRefCounted::ref; 72 using ThreadSafeRefCounted::deref; 72 const MessagePortIdentifier& identifier() const { return m_identifier; } 73 74 void ref() const; 75 void deref() const; 73 76 74 77 // ActiveDOMObject … … 86 89 87 90 private: 88 explicit MessagePort(ScriptExecutionContext& );91 explicit MessagePort(ScriptExecutionContext&, const MessagePortIdentifier&); 89 92 90 93 bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) final; … … 102 105 bool m_started { false }; 103 106 bool m_closed { false }; 107 108 MessagePortIdentifier m_identifier; 109 110 mutable std::atomic<unsigned> m_refCount { 1 }; 104 111 }; 105 112 -
trunk/Source/WebCore/dom/MessagePortChannel.h
r226252 r226336 44 44 class ScriptExecutionContext; 45 45 46 struct MessagePortIdentifier; 47 46 48 // The overwhelmingly common case is sending a single port, so handle that efficiently with an inline buffer of size 1. 47 49 typedef Vector<RefPtr<MessagePortChannel>, 1> MessagePortChannelArray; … … 65 67 static void createChannelBetweenPorts(MessagePort&, MessagePort&); 66 68 67 void setRemotePort(MessagePort*);68 69 69 virtual void postMessageToRemote(Ref<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>&&) = 0; 70 70 virtual Deque<std::unique_ptr<EventData>> takeAllMessagesFromRemote() = 0; 71 virtual bool isConnectedTo( MessagePort&) = 0;72 virtual bool entangle IfOpen(MessagePort&) = 0;71 virtual bool isConnectedTo(const MessagePortIdentifier&) = 0; 72 virtual bool entangleWithRemoteIfOpen(const MessagePortIdentifier&) = 0; 73 73 virtual void disentangle() = 0; 74 74 virtual bool hasPendingActivity() = 0;
Note: See TracChangeset
for help on using the changeset viewer.