tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

AsyncEventDispatcher.cpp (5621B)


      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 "mozilla/AsyncEventDispatcher.h"
      8 
      9 #include "mozilla/BasicEvents.h"
     10 #include "mozilla/EventDispatcher.h"
     11 #include "mozilla/dom/DocumentInlines.h"
     12 #include "mozilla/dom/Event.h"
     13 #include "mozilla/dom/EventTarget.h"
     14 #include "nsContentUtils.h"
     15 
     16 namespace mozilla {
     17 
     18 using namespace dom;
     19 
     20 /******************************************************************************
     21 * mozilla::AsyncEventDispatcher
     22 ******************************************************************************/
     23 
     24 AsyncEventDispatcher::AsyncEventDispatcher(EventTarget* aTarget,
     25                                           WidgetEvent& aEvent)
     26    : CancelableRunnable("AsyncEventDispatcher"),
     27      mTarget(aTarget),
     28      mEventMessage(eUnidentifiedEvent) {
     29  MOZ_ASSERT(mTarget);
     30  RefPtr<Event> event =
     31      EventDispatcher::CreateEvent(aTarget, nullptr, &aEvent, u""_ns);
     32  mEvent = std::move(event);
     33  mEventType.SetIsVoid(true);
     34  NS_ASSERTION(mEvent, "Should never fail to create an event");
     35  mEvent->DuplicatePrivateData();
     36  mEvent->SetTrusted(aEvent.IsTrusted());
     37 }
     38 
     39 NS_IMETHODIMP
     40 AsyncEventDispatcher::Run() {
     41  if (mCanceled) {
     42    return NS_OK;
     43  }
     44  nsINode* node = nsINode::FromEventTargetOrNull(mTarget);
     45  if (mCheckStillInDoc) {
     46    MOZ_ASSERT(node);
     47    if (!node->IsInComposedDoc()) {
     48      return NS_OK;
     49    }
     50  }
     51  mTarget->AsyncEventRunning(this);
     52  if (mEventMessage != eUnidentifiedEvent) {
     53    MOZ_ASSERT(mComposed == Composed::eDefault);
     54    return nsContentUtils::DispatchTrustedEvent<WidgetEvent>(
     55        node->OwnerDoc(), mTarget, mEventMessage, mCanBubble, Cancelable::eNo,
     56        nullptr /* aDefaultAction */, mOnlyChromeDispatch);
     57  }
     58  // MOZ_KnownLives because this instance shouldn't be touched while running.
     59  if (mEvent) {
     60    DispatchEventOnTarget(MOZ_KnownLive(mTarget), MOZ_KnownLive(mEvent),
     61                          mOnlyChromeDispatch, mComposed);
     62  } else {
     63    DispatchEventOnTarget(MOZ_KnownLive(mTarget), mEventType, mCanBubble,
     64                          mOnlyChromeDispatch, mComposed);
     65  }
     66  return NS_OK;
     67 }
     68 
     69 // static
     70 void AsyncEventDispatcher::DispatchEventOnTarget(
     71    EventTarget* aTarget, const nsAString& aEventType, CanBubble aCanBubble,
     72    ChromeOnlyDispatch aOnlyChromeDispatch, Composed aComposed) {
     73  RefPtr<Event> event = NS_NewDOMEvent(aTarget, nullptr, nullptr);
     74  event->InitEvent(aEventType, aCanBubble, Cancelable::eNo);
     75  event->SetTrusted(true);
     76  DispatchEventOnTarget(aTarget, event, aOnlyChromeDispatch, aComposed);
     77 }
     78 
     79 // static
     80 void AsyncEventDispatcher::DispatchEventOnTarget(
     81    EventTarget* aTarget, Event* aEvent, ChromeOnlyDispatch aOnlyChromeDispatch,
     82    Composed aComposed) {
     83  if (aComposed != Composed::eDefault) {
     84    aEvent->WidgetEventPtr()->mFlags.mComposed = aComposed == Composed::eYes;
     85  }
     86  if (aOnlyChromeDispatch == ChromeOnlyDispatch::eYes) {
     87    MOZ_ASSERT(aEvent->IsTrusted());
     88    aEvent->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
     89  }
     90  aTarget->DispatchEvent(*aEvent);
     91 }
     92 
     93 nsresult AsyncEventDispatcher::Cancel() {
     94  mCanceled = true;
     95  return NS_OK;
     96 }
     97 
     98 nsresult AsyncEventDispatcher::PostDOMEvent() {
     99  RefPtr<AsyncEventDispatcher> ensureDeletionWhenFailing = this;
    100  return NS_DispatchToCurrentThread(ensureDeletionWhenFailing.forget());
    101 }
    102 
    103 void AsyncEventDispatcher::RunDOMEventWhenSafe() {
    104  RefPtr<AsyncEventDispatcher> ensureDeletionWhenFailing = this;
    105  nsContentUtils::AddScriptRunner(ensureDeletionWhenFailing.forget());
    106 }
    107 
    108 // static
    109 void AsyncEventDispatcher::RunDOMEventWhenSafe(
    110    EventTarget& aTarget, const nsAString& aEventType, CanBubble aCanBubble,
    111    ChromeOnlyDispatch aOnlyChromeDispatch /* = ChromeOnlyDispatch::eNo */,
    112    Composed aComposed /* = Composed::eDefault */) {
    113  if (nsContentUtils::IsSafeToRunScript()) {
    114    OwningNonNull<EventTarget> target = aTarget;
    115    DispatchEventOnTarget(target, aEventType, aCanBubble, aOnlyChromeDispatch,
    116                          aComposed);
    117    return;
    118  }
    119  (new AsyncEventDispatcher(&aTarget, aEventType, aCanBubble,
    120                            aOnlyChromeDispatch, aComposed))
    121      ->RunDOMEventWhenSafe();
    122 }
    123 
    124 void AsyncEventDispatcher::RunDOMEventWhenSafe(
    125    EventTarget& aTarget, Event& aEvent,
    126    ChromeOnlyDispatch aOnlyChromeDispatch /* = ChromeOnlyDispatch::eNo */) {
    127  if (nsContentUtils::IsSafeToRunScript()) {
    128    DispatchEventOnTarget(&aTarget, &aEvent, aOnlyChromeDispatch,
    129                          Composed::eDefault);
    130    return;
    131  }
    132  (new AsyncEventDispatcher(&aTarget, do_AddRef(&aEvent), aOnlyChromeDispatch))
    133      ->RunDOMEventWhenSafe();
    134 }
    135 
    136 // static
    137 nsresult AsyncEventDispatcher::RunDOMEventWhenSafe(
    138    nsINode& aTarget, WidgetEvent& aEvent,
    139    nsEventStatus* aEventStatus /* = nullptr */) {
    140  if (nsContentUtils::IsSafeToRunScript()) {
    141    // MOZ_KnownLive due to bug 1832202
    142    nsPresContext* presContext = aTarget.OwnerDoc()->GetPresContext();
    143    return EventDispatcher::Dispatch(MOZ_KnownLive(&aTarget),
    144                                     MOZ_KnownLive(presContext), &aEvent,
    145                                     nullptr, aEventStatus);
    146  }
    147  (new AsyncEventDispatcher(&aTarget, aEvent))->RunDOMEventWhenSafe();
    148  return NS_OK;
    149 }
    150 
    151 void AsyncEventDispatcher::RequireNodeInDocument() {
    152  MOZ_ASSERT(mTarget);
    153  MOZ_ASSERT(mTarget->IsNode());
    154  mCheckStillInDoc = true;
    155 }
    156 
    157 }  // namespace mozilla