dom/base/MessagePort.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "MessagePort.h"
michael@0 7 #include "MessageEvent.h"
michael@0 8 #include "mozilla/dom/Event.h"
michael@0 9 #include "mozilla/dom/MessageChannel.h"
michael@0 10 #include "mozilla/dom/MessagePortBinding.h"
michael@0 11 #include "mozilla/dom/MessagePortList.h"
michael@0 12 #include "mozilla/dom/StructuredCloneTags.h"
michael@0 13 #include "nsContentUtils.h"
michael@0 14 #include "nsGlobalWindow.h"
michael@0 15 #include "nsPresContext.h"
michael@0 16
michael@0 17 #include "nsIDocument.h"
michael@0 18 #include "nsIDOMFile.h"
michael@0 19 #include "nsIDOMFileList.h"
michael@0 20 #include "nsIPresShell.h"
michael@0 21
michael@0 22 namespace mozilla {
michael@0 23 namespace dom {
michael@0 24
michael@0 25 class DispatchEventRunnable : public nsRunnable
michael@0 26 {
michael@0 27 friend class MessagePort;
michael@0 28
michael@0 29 public:
michael@0 30 DispatchEventRunnable(MessagePort* aPort)
michael@0 31 : mPort(aPort)
michael@0 32 {
michael@0 33 }
michael@0 34
michael@0 35 NS_IMETHOD
michael@0 36 Run()
michael@0 37 {
michael@0 38 nsRefPtr<DispatchEventRunnable> mKungFuDeathGrip(this);
michael@0 39
michael@0 40 mPort->mDispatchRunnable = nullptr;
michael@0 41 mPort->Dispatch();
michael@0 42
michael@0 43 return NS_OK;
michael@0 44 }
michael@0 45
michael@0 46 private:
michael@0 47 nsRefPtr<MessagePort> mPort;
michael@0 48 };
michael@0 49
michael@0 50 class PostMessageRunnable : public nsRunnable
michael@0 51 {
michael@0 52 friend class MessagePort;
michael@0 53
michael@0 54 public:
michael@0 55 NS_DECL_NSIRUNNABLE
michael@0 56
michael@0 57 PostMessageRunnable()
michael@0 58 {
michael@0 59 }
michael@0 60
michael@0 61 ~PostMessageRunnable()
michael@0 62 {
michael@0 63 }
michael@0 64
michael@0 65 JSAutoStructuredCloneBuffer& Buffer()
michael@0 66 {
michael@0 67 return mBuffer;
michael@0 68 }
michael@0 69
michael@0 70 bool StoreISupports(nsISupports* aSupports)
michael@0 71 {
michael@0 72 mSupportsArray.AppendElement(aSupports);
michael@0 73 return true;
michael@0 74 }
michael@0 75
michael@0 76 void Dispatch(MessagePort* aPort)
michael@0 77 {
michael@0 78 mPort = aPort;
michael@0 79 NS_DispatchToCurrentThread(this);
michael@0 80 }
michael@0 81
michael@0 82 private:
michael@0 83 nsRefPtr<MessagePort> mPort;
michael@0 84 JSAutoStructuredCloneBuffer mBuffer;
michael@0 85
michael@0 86 nsTArray<nsCOMPtr<nsISupports> > mSupportsArray;
michael@0 87 };
michael@0 88
michael@0 89 namespace {
michael@0 90
michael@0 91 struct StructuredCloneInfo
michael@0 92 {
michael@0 93 PostMessageRunnable* mEvent;
michael@0 94 MessagePort* mPort;
michael@0 95 nsRefPtrHashtable<nsRefPtrHashKey<MessagePortBase>, MessagePortBase> mPorts;
michael@0 96 };
michael@0 97
michael@0 98 static JSObject*
michael@0 99 PostMessageReadStructuredClone(JSContext* cx,
michael@0 100 JSStructuredCloneReader* reader,
michael@0 101 uint32_t tag,
michael@0 102 uint32_t data,
michael@0 103 void* closure)
michael@0 104 {
michael@0 105 if (tag == SCTAG_DOM_BLOB || tag == SCTAG_DOM_FILELIST) {
michael@0 106 NS_ASSERTION(!data, "Data should be empty");
michael@0 107
michael@0 108 nsISupports* supports;
michael@0 109 if (JS_ReadBytes(reader, &supports, sizeof(supports))) {
michael@0 110 JS::Rooted<JS::Value> val(cx);
michael@0 111 if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, supports, &val))) {
michael@0 112 return JSVAL_TO_OBJECT(val);
michael@0 113 }
michael@0 114 }
michael@0 115 }
michael@0 116
michael@0 117 const JSStructuredCloneCallbacks* runtimeCallbacks =
michael@0 118 js::GetContextStructuredCloneCallbacks(cx);
michael@0 119
michael@0 120 if (runtimeCallbacks) {
michael@0 121 return runtimeCallbacks->read(cx, reader, tag, data, nullptr);
michael@0 122 }
michael@0 123
michael@0 124 return nullptr;
michael@0 125 }
michael@0 126
michael@0 127 static bool
michael@0 128 PostMessageWriteStructuredClone(JSContext* cx,
michael@0 129 JSStructuredCloneWriter* writer,
michael@0 130 JS::Handle<JSObject*> obj,
michael@0 131 void *closure)
michael@0 132 {
michael@0 133 StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
michael@0 134 NS_ASSERTION(scInfo, "Must have scInfo!");
michael@0 135
michael@0 136 nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative;
michael@0 137 nsContentUtils::XPConnect()->
michael@0 138 GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrappedNative));
michael@0 139 if (wrappedNative) {
michael@0 140 uint32_t scTag = 0;
michael@0 141 nsISupports* supports = wrappedNative->Native();
michael@0 142
michael@0 143 nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(supports);
michael@0 144 if (blob) {
michael@0 145 scTag = SCTAG_DOM_BLOB;
michael@0 146 }
michael@0 147
michael@0 148 nsCOMPtr<nsIDOMFileList> list = do_QueryInterface(supports);
michael@0 149 if (list) {
michael@0 150 scTag = SCTAG_DOM_FILELIST;
michael@0 151 }
michael@0 152
michael@0 153 if (scTag) {
michael@0 154 return JS_WriteUint32Pair(writer, scTag, 0) &&
michael@0 155 JS_WriteBytes(writer, &supports, sizeof(supports)) &&
michael@0 156 scInfo->mEvent->StoreISupports(supports);
michael@0 157 }
michael@0 158 }
michael@0 159
michael@0 160 const JSStructuredCloneCallbacks* runtimeCallbacks =
michael@0 161 js::GetContextStructuredCloneCallbacks(cx);
michael@0 162
michael@0 163 if (runtimeCallbacks) {
michael@0 164 return runtimeCallbacks->write(cx, writer, obj, nullptr);
michael@0 165 }
michael@0 166
michael@0 167 return false;
michael@0 168 }
michael@0 169
michael@0 170 static bool
michael@0 171 PostMessageReadTransferStructuredClone(JSContext* aCx,
michael@0 172 JSStructuredCloneReader* reader,
michael@0 173 uint32_t tag, void* data,
michael@0 174 uint64_t unused,
michael@0 175 void* aClosure,
michael@0 176 JS::MutableHandle<JSObject*> returnObject)
michael@0 177 {
michael@0 178 StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
michael@0 179 NS_ASSERTION(scInfo, "Must have scInfo!");
michael@0 180
michael@0 181 if (tag == SCTAG_DOM_MAP_MESSAGEPORT) {
michael@0 182 MessagePort* port = static_cast<MessagePort*>(data);
michael@0 183 port->BindToOwner(scInfo->mPort->GetOwner());
michael@0 184 scInfo->mPorts.Put(port, nullptr);
michael@0 185
michael@0 186 JS::Rooted<JSObject*> obj(aCx, port->WrapObject(aCx));
michael@0 187 if (JS_WrapObject(aCx, &obj)) {
michael@0 188 MOZ_ASSERT(port->GetOwner() == scInfo->mPort->GetOwner());
michael@0 189 returnObject.set(obj);
michael@0 190 }
michael@0 191 return true;
michael@0 192 }
michael@0 193
michael@0 194 return false;
michael@0 195 }
michael@0 196
michael@0 197 static bool
michael@0 198 PostMessageTransferStructuredClone(JSContext* aCx,
michael@0 199 JS::Handle<JSObject*> aObj,
michael@0 200 void* aClosure,
michael@0 201 uint32_t* aTag,
michael@0 202 JS::TransferableOwnership* aOwnership,
michael@0 203 void** aContent,
michael@0 204 uint64_t *aExtraData)
michael@0 205 {
michael@0 206 StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
michael@0 207 NS_ASSERTION(scInfo, "Must have scInfo!");
michael@0 208
michael@0 209 MessagePortBase *port = nullptr;
michael@0 210 nsresult rv = UNWRAP_OBJECT(MessagePort, aObj, port);
michael@0 211 if (NS_SUCCEEDED(rv)) {
michael@0 212 nsRefPtr<MessagePortBase> newPort;
michael@0 213 if (scInfo->mPorts.Get(port, getter_AddRefs(newPort))) {
michael@0 214 // No duplicate.
michael@0 215 return false;
michael@0 216 }
michael@0 217
michael@0 218 newPort = port->Clone();
michael@0 219 scInfo->mPorts.Put(port, newPort);
michael@0 220
michael@0 221 *aTag = SCTAG_DOM_MAP_MESSAGEPORT;
michael@0 222 *aOwnership = JS::SCTAG_TMO_CUSTOM;
michael@0 223 *aContent = newPort;
michael@0 224 *aExtraData = 0;
michael@0 225
michael@0 226 return true;
michael@0 227 }
michael@0 228
michael@0 229 return false;
michael@0 230 }
michael@0 231
michael@0 232 static void
michael@0 233 PostMessageFreeTransferStructuredClone(uint32_t aTag, JS::TransferableOwnership aOwnership,
michael@0 234 void* aData,
michael@0 235 uint64_t aExtraData,
michael@0 236 void* aClosure)
michael@0 237 {
michael@0 238 StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(aClosure);
michael@0 239 NS_ASSERTION(scInfo, "Must have scInfo!");
michael@0 240
michael@0 241 if (aTag == SCTAG_DOM_MAP_MESSAGEPORT) {
michael@0 242 MOZ_ASSERT(aOwnership == JS::SCTAG_TMO_CUSTOM);
michael@0 243 nsRefPtr<MessagePort> port(static_cast<MessagePort*>(aData));
michael@0 244 scInfo->mPorts.Remove(port);
michael@0 245 }
michael@0 246 }
michael@0 247
michael@0 248 JSStructuredCloneCallbacks kPostMessageCallbacks = {
michael@0 249 PostMessageReadStructuredClone,
michael@0 250 PostMessageWriteStructuredClone,
michael@0 251 nullptr,
michael@0 252 PostMessageReadTransferStructuredClone,
michael@0 253 PostMessageTransferStructuredClone,
michael@0 254 PostMessageFreeTransferStructuredClone
michael@0 255 };
michael@0 256
michael@0 257 } // anonymous namespace
michael@0 258
michael@0 259 static PLDHashOperator
michael@0 260 PopulateMessagePortList(MessagePortBase* aKey, MessagePortBase* aValue, void* aClosure)
michael@0 261 {
michael@0 262 nsTArray<nsRefPtr<MessagePortBase> > *array =
michael@0 263 static_cast<nsTArray<nsRefPtr<MessagePortBase> > *>(aClosure);
michael@0 264
michael@0 265 array->AppendElement(aKey);
michael@0 266 return PL_DHASH_NEXT;
michael@0 267 }
michael@0 268
michael@0 269 NS_IMETHODIMP
michael@0 270 PostMessageRunnable::Run()
michael@0 271 {
michael@0 272 MOZ_ASSERT(mPort);
michael@0 273
michael@0 274 // Get the JSContext for the target window
michael@0 275 nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(mPort->GetOwner());
michael@0 276 NS_ENSURE_STATE(sgo);
michael@0 277 nsCOMPtr<nsIScriptContext> scriptContext = sgo->GetContext();
michael@0 278 AutoPushJSContext cx(scriptContext ? scriptContext->GetNativeContext()
michael@0 279 : nsContentUtils::GetSafeJSContext());
michael@0 280
michael@0 281 MOZ_ASSERT(cx);
michael@0 282
michael@0 283 // Deserialize the structured clone data
michael@0 284 JS::Rooted<JS::Value> messageData(cx);
michael@0 285 StructuredCloneInfo scInfo;
michael@0 286 scInfo.mEvent = this;
michael@0 287 scInfo.mPort = mPort;
michael@0 288
michael@0 289 if (!mBuffer.read(cx, &messageData, &kPostMessageCallbacks, &scInfo)) {
michael@0 290 return NS_ERROR_DOM_DATA_CLONE_ERR;
michael@0 291 }
michael@0 292
michael@0 293 // Create the event
michael@0 294 nsCOMPtr<mozilla::dom::EventTarget> eventTarget =
michael@0 295 do_QueryInterface(mPort->GetOwner());
michael@0 296 nsRefPtr<MessageEvent> event =
michael@0 297 new MessageEvent(eventTarget, nullptr, nullptr);
michael@0 298
michael@0 299 event->InitMessageEvent(NS_LITERAL_STRING("message"), false /* non-bubbling */,
michael@0 300 false /* cancelable */, messageData, EmptyString(),
michael@0 301 EmptyString(), nullptr);
michael@0 302 event->SetTrusted(true);
michael@0 303 event->SetSource(mPort);
michael@0 304
michael@0 305 nsTArray<nsRefPtr<MessagePortBase> > ports;
michael@0 306 scInfo.mPorts.EnumerateRead(PopulateMessagePortList, &ports);
michael@0 307 event->SetPorts(new MessagePortList(static_cast<dom::Event*>(event.get()), ports));
michael@0 308
michael@0 309 bool status;
michael@0 310 mPort->DispatchEvent(static_cast<dom::Event*>(event.get()), &status);
michael@0 311 return status ? NS_OK : NS_ERROR_FAILURE;
michael@0 312 }
michael@0 313
michael@0 314 MessagePortBase::MessagePortBase(nsPIDOMWindow* aWindow)
michael@0 315 : DOMEventTargetHelper(aWindow)
michael@0 316 {
michael@0 317 // SetIsDOMBinding() is called by DOMEventTargetHelper's ctor.
michael@0 318 }
michael@0 319
michael@0 320 MessagePortBase::MessagePortBase()
michael@0 321 {
michael@0 322 SetIsDOMBinding();
michael@0 323 }
michael@0 324
michael@0 325 NS_IMPL_CYCLE_COLLECTION_CLASS(MessagePort)
michael@0 326
michael@0 327 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MessagePort,
michael@0 328 DOMEventTargetHelper)
michael@0 329 NS_IMPL_CYCLE_COLLECTION_UNLINK(mEntangledPort)
michael@0 330
michael@0 331 // Custom unlink loop because this array contains nsRunnable objects
michael@0 332 // which are not cycle colleactable.
michael@0 333 while (!tmp->mMessageQueue.IsEmpty()) {
michael@0 334 NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageQueue[0]->mPort);
michael@0 335 NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageQueue[0]->mSupportsArray);
michael@0 336 tmp->mMessageQueue.RemoveElementAt(0);
michael@0 337 }
michael@0 338
michael@0 339 if (tmp->mDispatchRunnable) {
michael@0 340 NS_IMPL_CYCLE_COLLECTION_UNLINK(mDispatchRunnable->mPort);
michael@0 341 }
michael@0 342
michael@0 343 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
michael@0 344
michael@0 345 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MessagePort,
michael@0 346 DOMEventTargetHelper)
michael@0 347 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEntangledPort)
michael@0 348
michael@0 349 // Custom unlink loop because this array contains nsRunnable objects
michael@0 350 // which are not cycle colleactable.
michael@0 351 for (uint32_t i = 0, len = tmp->mMessageQueue.Length(); i < len; ++i) {
michael@0 352 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageQueue[i]->mPort);
michael@0 353 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageQueue[i]->mSupportsArray);
michael@0 354 }
michael@0 355
michael@0 356 if (tmp->mDispatchRunnable) {
michael@0 357 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDispatchRunnable->mPort);
michael@0 358 }
michael@0 359
michael@0 360 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
michael@0 361
michael@0 362 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MessagePort)
michael@0 363 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
michael@0 364
michael@0 365 NS_IMPL_ADDREF_INHERITED(MessagePort, DOMEventTargetHelper)
michael@0 366 NS_IMPL_RELEASE_INHERITED(MessagePort, DOMEventTargetHelper)
michael@0 367
michael@0 368 MessagePort::MessagePort(nsPIDOMWindow* aWindow)
michael@0 369 : MessagePortBase(aWindow)
michael@0 370 , mMessageQueueEnabled(false)
michael@0 371 {
michael@0 372 }
michael@0 373
michael@0 374 MessagePort::~MessagePort()
michael@0 375 {
michael@0 376 Close();
michael@0 377 }
michael@0 378
michael@0 379 JSObject*
michael@0 380 MessagePort::WrapObject(JSContext* aCx)
michael@0 381 {
michael@0 382 return MessagePortBinding::Wrap(aCx, this);
michael@0 383 }
michael@0 384
michael@0 385 void
michael@0 386 MessagePort::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
michael@0 387 const Optional<Sequence<JS::Value>>& aTransferable,
michael@0 388 ErrorResult& aRv)
michael@0 389 {
michael@0 390 nsRefPtr<PostMessageRunnable> event = new PostMessageRunnable();
michael@0 391
michael@0 392 // We *must* clone the data here, or the JS::Value could be modified
michael@0 393 // by script
michael@0 394 StructuredCloneInfo scInfo;
michael@0 395 scInfo.mEvent = event;
michael@0 396 scInfo.mPort = this;
michael@0 397
michael@0 398 JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
michael@0 399 if (aTransferable.WasPassed()) {
michael@0 400 const Sequence<JS::Value>& realTransferable = aTransferable.Value();
michael@0 401
michael@0 402 // The input sequence only comes from the generated bindings code, which
michael@0 403 // ensures it is rooted.
michael@0 404 JS::HandleValueArray elements =
michael@0 405 JS::HandleValueArray::fromMarkedLocation(realTransferable.Length(),
michael@0 406 realTransferable.Elements());
michael@0 407
michael@0 408 JSObject* array =
michael@0 409 JS_NewArrayObject(aCx, elements);
michael@0 410 if (!array) {
michael@0 411 aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
michael@0 412 return;
michael@0 413 }
michael@0 414 transferable.setObject(*array);
michael@0 415 }
michael@0 416
michael@0 417 if (!event->Buffer().write(aCx, aMessage, transferable,
michael@0 418 &kPostMessageCallbacks, &scInfo)) {
michael@0 419 aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
michael@0 420 return;
michael@0 421 }
michael@0 422
michael@0 423 if (!mEntangledPort) {
michael@0 424 return;
michael@0 425 }
michael@0 426
michael@0 427 mEntangledPort->mMessageQueue.AppendElement(event);
michael@0 428 mEntangledPort->Dispatch();
michael@0 429 }
michael@0 430
michael@0 431 void
michael@0 432 MessagePort::Start()
michael@0 433 {
michael@0 434 if (mMessageQueueEnabled) {
michael@0 435 return;
michael@0 436 }
michael@0 437
michael@0 438 mMessageQueueEnabled = true;
michael@0 439 Dispatch();
michael@0 440 }
michael@0 441
michael@0 442 void
michael@0 443 MessagePort::Dispatch()
michael@0 444 {
michael@0 445 if (!mMessageQueueEnabled || mMessageQueue.IsEmpty() || mDispatchRunnable) {
michael@0 446 return;
michael@0 447 }
michael@0 448
michael@0 449 nsRefPtr<PostMessageRunnable> event = mMessageQueue.ElementAt(0);
michael@0 450 mMessageQueue.RemoveElementAt(0);
michael@0 451
michael@0 452 event->Dispatch(this);
michael@0 453
michael@0 454 mDispatchRunnable = new DispatchEventRunnable(this);
michael@0 455 NS_DispatchToCurrentThread(mDispatchRunnable);
michael@0 456 }
michael@0 457
michael@0 458 void
michael@0 459 MessagePort::Close()
michael@0 460 {
michael@0 461 if (!mEntangledPort) {
michael@0 462 return;
michael@0 463 }
michael@0 464
michael@0 465 // This avoids loops.
michael@0 466 nsRefPtr<MessagePort> port = mEntangledPort;
michael@0 467 mEntangledPort = nullptr;
michael@0 468
michael@0 469 // Let's disentangle the 2 ports symmetrically.
michael@0 470 port->Close();
michael@0 471 }
michael@0 472
michael@0 473 EventHandlerNonNull*
michael@0 474 MessagePort::GetOnmessage()
michael@0 475 {
michael@0 476 if (NS_IsMainThread()) {
michael@0 477 return GetEventHandler(nsGkAtoms::onmessage, EmptyString());
michael@0 478 }
michael@0 479 return GetEventHandler(nullptr, NS_LITERAL_STRING("message"));
michael@0 480 }
michael@0 481
michael@0 482 void
michael@0 483 MessagePort::SetOnmessage(EventHandlerNonNull* aCallback)
michael@0 484 {
michael@0 485 if (NS_IsMainThread()) {
michael@0 486 SetEventHandler(nsGkAtoms::onmessage, EmptyString(), aCallback);
michael@0 487 } else {
michael@0 488 SetEventHandler(nullptr, NS_LITERAL_STRING("message"), aCallback);
michael@0 489 }
michael@0 490
michael@0 491 // When using onmessage, the call to start() is implied.
michael@0 492 Start();
michael@0 493 }
michael@0 494
michael@0 495 void
michael@0 496 MessagePort::Entangle(MessagePort* aMessagePort)
michael@0 497 {
michael@0 498 MOZ_ASSERT(aMessagePort);
michael@0 499 MOZ_ASSERT(aMessagePort != this);
michael@0 500
michael@0 501 Close();
michael@0 502
michael@0 503 mEntangledPort = aMessagePort;
michael@0 504 }
michael@0 505
michael@0 506 already_AddRefed<MessagePortBase>
michael@0 507 MessagePort::Clone()
michael@0 508 {
michael@0 509 nsRefPtr<MessagePort> newPort = new MessagePort(nullptr);
michael@0 510
michael@0 511 // Move all the events in the port message queue of original port.
michael@0 512 newPort->mMessageQueue.SwapElements(mMessageQueue);
michael@0 513
michael@0 514 if (mEntangledPort) {
michael@0 515 nsRefPtr<MessagePort> port = mEntangledPort;
michael@0 516 mEntangledPort = nullptr;
michael@0 517
michael@0 518 newPort->Entangle(port);
michael@0 519 port->Entangle(newPort);
michael@0 520 }
michael@0 521
michael@0 522 return newPort.forget();
michael@0 523 }
michael@0 524
michael@0 525 } // namespace dom
michael@0 526 } // namespace mozilla

mercurial