MessageChannel.cpp (2753B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "MessageChannel.h" 8 9 #include "mozilla/dom/Document.h" 10 #include "mozilla/dom/MessageChannelBinding.h" 11 #include "mozilla/dom/MessagePort.h" 12 #include "mozilla/dom/Navigator.h" 13 #include "mozilla/dom/WorkerRunnable.h" 14 #include "nsIGlobalObject.h" 15 #include "nsServiceManagerUtils.h" 16 17 namespace mozilla::dom { 18 19 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MessageChannel, mGlobal, mPort1, mPort2) 20 NS_IMPL_CYCLE_COLLECTING_ADDREF(MessageChannel) 21 NS_IMPL_CYCLE_COLLECTING_RELEASE(MessageChannel) 22 23 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MessageChannel) 24 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY 25 NS_INTERFACE_MAP_ENTRY(nsISupports) 26 NS_INTERFACE_MAP_END 27 28 MessageChannel::MessageChannel(nsIGlobalObject* aGlobal) : mGlobal(aGlobal) { 29 MOZ_ASSERT(aGlobal); 30 } 31 32 MessageChannel::~MessageChannel() = default; 33 34 JSObject* MessageChannel::WrapObject(JSContext* aCx, 35 JS::Handle<JSObject*> aGivenProto) { 36 return MessageChannel_Binding::Wrap(aCx, this, aGivenProto); 37 } 38 39 /* static */ 40 already_AddRefed<MessageChannel> MessageChannel::Constructor( 41 const GlobalObject& aGlobal, ErrorResult& aRv) { 42 nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports()); 43 return Constructor(global, aRv); 44 } 45 46 /* static */ 47 already_AddRefed<MessageChannel> MessageChannel::Constructor( 48 nsIGlobalObject* aGlobal, ErrorResult& aRv) { 49 MOZ_ASSERT(aGlobal); 50 51 nsID portUUID1; 52 aRv = nsID::GenerateUUIDInPlace(portUUID1); 53 if (aRv.Failed()) { 54 return nullptr; 55 } 56 57 nsID portUUID2; 58 aRv = nsID::GenerateUUIDInPlace(portUUID2); 59 if (aRv.Failed()) { 60 return nullptr; 61 } 62 63 RefPtr<MessageChannel> channel = new MessageChannel(aGlobal); 64 65 channel->mPort1 = MessagePort::Create(aGlobal, portUUID1, portUUID2, aRv); 66 if (NS_WARN_IF(aRv.Failed())) { 67 return nullptr; 68 } 69 70 channel->mPort2 = MessagePort::Create(aGlobal, portUUID2, portUUID1, aRv); 71 if (NS_WARN_IF(aRv.Failed())) { 72 return nullptr; 73 } 74 75 channel->mPort1->UnshippedEntangle(channel->mPort2); 76 channel->mPort2->UnshippedEntangle(channel->mPort1); 77 78 // MessagePorts should not work if created from a disconnected window. 79 nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal); 80 if (window && !window->GetDocShell()) { 81 // The 2 ports are entangled. We can close one of them to close the other 82 // too. 83 channel->mPort1->CloseForced(); 84 } 85 86 return channel.forget(); 87 } 88 89 } // namespace mozilla::dom