dom/workers/MessagePort.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     4  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "MessagePort.h"
     8 #include "mozilla/EventDispatcher.h"
     9 #include "mozilla/dom/MessagePortBinding.h"
    10 #include "nsIDOMEvent.h"
    12 #include "SharedWorker.h"
    13 #include "WorkerPrivate.h"
    14 #include "WorkerRunnable.h"
    16 using mozilla::dom::EventHandlerNonNull;
    17 using mozilla::dom::MessagePortBase;
    18 using mozilla::dom::Optional;
    19 using mozilla::dom::Sequence;
    20 using namespace mozilla;
    22 USING_WORKERS_NAMESPACE
    24 namespace {
    26 class DelayedEventRunnable MOZ_FINAL : public WorkerRunnable
    27 {
    28   nsRefPtr<MessagePort> mMessagePort;
    29   nsTArray<nsCOMPtr<nsIDOMEvent>> mEvents;
    31 public:
    32   DelayedEventRunnable(WorkerPrivate* aWorkerPrivate,
    33                        TargetAndBusyBehavior aBehavior,
    34                        MessagePort* aMessagePort,
    35                        nsTArray<nsCOMPtr<nsIDOMEvent>>& aEvents)
    36   : WorkerRunnable(aWorkerPrivate, aBehavior), mMessagePort(aMessagePort)
    37   {
    38     AssertIsOnMainThread();
    39     MOZ_ASSERT(aMessagePort);
    40     MOZ_ASSERT(aEvents.Length());
    42     mEvents.SwapElements(aEvents);
    43   }
    45   bool
    46   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate);
    47 };
    49 } // anonymous namespace
    51 MessagePort::MessagePort(nsPIDOMWindow* aWindow, SharedWorker* aSharedWorker,
    52                          uint64_t aSerial)
    53 : MessagePortBase(aWindow), mSharedWorker(aSharedWorker),
    54   mWorkerPrivate(nullptr), mSerial(aSerial), mStarted(false)
    55 {
    56   AssertIsOnMainThread();
    57   MOZ_ASSERT(aSharedWorker);
    58   SetIsDOMBinding();
    59 }
    61 MessagePort::MessagePort(WorkerPrivate* aWorkerPrivate, uint64_t aSerial)
    62 : mWorkerPrivate(aWorkerPrivate), mSerial(aSerial), mStarted(false)
    63 {
    64   aWorkerPrivate->AssertIsOnWorkerThread();
    65   SetIsDOMBinding();
    66 }
    68 MessagePort::~MessagePort()
    69 {
    70   Close();
    71 }
    73 void
    74 MessagePort::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
    75                             const Optional<Sequence<JS::Value>>& aTransferable,
    76                             ErrorResult& aRv)
    77 {
    78   AssertCorrectThread();
    80   if (IsClosed()) {
    81     aRv = NS_ERROR_DOM_INVALID_STATE_ERR;
    82     return;
    83   }
    85   if (mSharedWorker) {
    86     mSharedWorker->PostMessage(aCx, aMessage, aTransferable, aRv);
    87   }
    88   else {
    89     mWorkerPrivate->PostMessageToParentMessagePort(aCx, Serial(), aMessage,
    90                                                    aTransferable, aRv);
    91   }
    92 }
    94 void
    95 MessagePort::Start()
    96 {
    97   AssertCorrectThread();
    99   if (IsClosed()) {
   100     NS_WARNING("Called start() after calling close()!");
   101     return;
   102   }
   104   if (mStarted) {
   105     return;
   106   }
   108   mStarted = true;
   110   if (!mQueuedEvents.IsEmpty()) {
   111     WorkerPrivate* workerPrivate;
   112     WorkerRunnable::TargetAndBusyBehavior behavior;
   114     if (mWorkerPrivate) {
   115       workerPrivate = mWorkerPrivate;
   116       behavior = WorkerRunnable::WorkerThreadModifyBusyCount;
   117     }
   118     else {
   119       workerPrivate = mSharedWorker->GetWorkerPrivate();
   120       MOZ_ASSERT(workerPrivate);
   122       behavior = WorkerRunnable::ParentThreadUnchangedBusyCount;
   123     }
   125     nsRefPtr<DelayedEventRunnable> runnable =
   126       new DelayedEventRunnable(workerPrivate, behavior, this, mQueuedEvents);
   127     runnable->Dispatch(nullptr);
   128   }
   129 }
   131 void
   132 MessagePort::Close()
   133 {
   134   AssertCorrectThread();
   136   if (!IsClosed()) {
   137     CloseInternal();
   138   }
   139 }
   141 void
   142 MessagePort::QueueEvent(nsIDOMEvent* aEvent)
   143 {
   144   AssertCorrectThread();
   145   MOZ_ASSERT(aEvent);
   146   MOZ_ASSERT(!IsClosed());
   147   MOZ_ASSERT(!mStarted);
   149   mQueuedEvents.AppendElement(aEvent);
   150 }
   152 EventHandlerNonNull*
   153 MessagePort::GetOnmessage()
   154 {
   155   AssertCorrectThread();
   157   return NS_IsMainThread() ? GetEventHandler(nsGkAtoms::onmessage, EmptyString())
   158                            : GetEventHandler(nullptr, NS_LITERAL_STRING("message"));
   159 }
   161 void
   162 MessagePort::SetOnmessage(EventHandlerNonNull* aCallback)
   163 {
   164   AssertCorrectThread();
   166   if (NS_IsMainThread()) {
   167     SetEventHandler(nsGkAtoms::onmessage, EmptyString(), aCallback);
   168   }
   169   else {
   170     SetEventHandler(nullptr, NS_LITERAL_STRING("message"), aCallback);
   171   }
   173   Start();
   174 }
   176 already_AddRefed<MessagePortBase>
   177 MessagePort::Clone()
   178 {
   179   NS_WARNING("Haven't implemented structured clone for these ports yet!");
   180   return nullptr;
   181 }
   183 void
   184 MessagePort::CloseInternal()
   185 {
   186   AssertCorrectThread();
   187   MOZ_ASSERT(!IsClosed());
   188   MOZ_ASSERT_IF(mStarted, mQueuedEvents.IsEmpty());
   190   NS_WARN_IF_FALSE(mStarted, "Called close() before start()!");
   192   if (!mStarted) {
   193     mQueuedEvents.Clear();
   194   }
   196   mSharedWorker = nullptr;
   197   mWorkerPrivate = nullptr;
   198 }
   200 #ifdef DEBUG
   201 void
   202 MessagePort::AssertCorrectThread() const
   203 {
   204   if (IsClosed()) {
   205     return; // Can't assert anything if we nulled out our pointers.
   206   }
   208   MOZ_ASSERT((mSharedWorker || mWorkerPrivate) &&
   209              !(mSharedWorker && mWorkerPrivate));
   211   if (mSharedWorker) {
   212     AssertIsOnMainThread();
   213   }
   214   else {
   215     mWorkerPrivate->AssertIsOnWorkerThread();
   216   }
   217 }
   218 #endif
   220 NS_IMPL_ADDREF_INHERITED(mozilla::dom::workers::MessagePort, DOMEventTargetHelper)
   221 NS_IMPL_RELEASE_INHERITED(mozilla::dom::workers::MessagePort, DOMEventTargetHelper)
   223 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MessagePort)
   224 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
   226 NS_IMPL_CYCLE_COLLECTION_CLASS(MessagePort)
   228 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MessagePort,
   229                                                   DOMEventTargetHelper)
   230   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSharedWorker)
   231   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mQueuedEvents)
   232 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
   234 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MessagePort,
   235                                                 DOMEventTargetHelper)
   236   tmp->Close();
   237 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
   239 JSObject*
   240 MessagePort::WrapObject(JSContext* aCx)
   241 {
   242   AssertCorrectThread();
   244   return MessagePortBinding::Wrap(aCx, this);
   245 }
   247 nsresult
   248 MessagePort::PreHandleEvent(EventChainPreVisitor& aVisitor)
   249 {
   250   AssertCorrectThread();
   252   nsIDOMEvent*& event = aVisitor.mDOMEvent;
   254   if (event) {
   255     bool preventDispatch = false;
   257     if (IsClosed()) {
   258       preventDispatch = true;
   259     } else if (NS_IsMainThread() && mSharedWorker->IsSuspended()) {
   260       mSharedWorker->QueueEvent(event);
   261       preventDispatch = true;
   262     } else if (!mStarted) {
   263       QueueEvent(event);
   264       preventDispatch = true;
   265     }
   267     if (preventDispatch) {
   268       aVisitor.mCanHandle = false;
   269       aVisitor.mParentTarget = nullptr;
   270       return NS_OK;
   271     }
   272   }
   274   return DOMEventTargetHelper::PreHandleEvent(aVisitor);
   275 }
   277 bool
   278 DelayedEventRunnable::WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
   279 {
   280   MOZ_ASSERT(mMessagePort);
   281   mMessagePort->AssertCorrectThread();
   282   MOZ_ASSERT(mEvents.Length());
   284   bool ignored;
   285   for (uint32_t i = 0; i < mEvents.Length(); i++) {
   286     mMessagePort->DispatchEvent(mEvents[i], &ignored);
   287   }
   289   return true;
   290 }

mercurial