Backed out 3 changesets (bug 1578355) for build bustage at build/src/dom/base/nsSyncLoadService.h:48:21. On a CLOSED TREE
authorDaniel Varga <dvarga@mozilla.com>
Fri, 20 Sep 2019 14:05:12 +0300
changeset 494269 0f81a8181f06935bb49c7ba1ffe5f853f5c6ca1d
parent 494268 b46946d6e446cf50fc2c3fcc62e2cb8ec84c4064
child 494270 fc785139655e3d22d681f1419bd4c80f93460f0e
push id114114
push userdluca@mozilla.com
push dateFri, 20 Sep 2019 22:00:08 +0000
treeherdermozilla-inbound@56e11fddf939 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1578355
milestone71.0a1
backs outd50ad759f1292661ed76fd5e78f85c4a6a148ebf
339ab54ca471854bdbfbb2f9eb6d7d70a6d2ece3
284299dac42cdec53b949781a2b739458a6c8a19
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 3 changesets (bug 1578355) for build bustage at build/src/dom/base/nsSyncLoadService.h:48:21. On a CLOSED TREE Backed out changeset d50ad759f129 (bug 1578355) Backed out changeset 339ab54ca471 (bug 1578355) Backed out changeset 284299dac42c (bug 1578355)
accessible/base/AccEvent.cpp
accessible/generic/Accessible.cpp
accessible/generic/DocAccessible.cpp
docshell/base/BrowsingContext.cpp
docshell/base/BrowsingContext.h
docshell/base/BrowsingContextFieldList.h
docshell/base/nsDocShell.cpp
dom/base/Document.cpp
dom/base/Document.h
dom/base/PopupBlocker.cpp
dom/base/UserActivation.cpp
dom/base/UserActivation.h
dom/base/moz.build
dom/base/nsContentPermissionHelper.cpp
dom/base/nsContentUtils.cpp
dom/base/nsDOMWindowUtils.cpp
dom/base/nsObjectLoadingContent.cpp
dom/base/test/useractivation/file_iframe_consume_user_activation.html
dom/base/test/useractivation/mochitest.ini
dom/base/test/useractivation/test_useractivation_transient_consuming.html
dom/canvas/CanvasUtils.cpp
dom/events/EventListenerManager.cpp
dom/events/EventStateManager.cpp
dom/events/EventStateManager.h
dom/events/IMEStateManager.cpp
dom/fetch/FetchDriver.cpp
dom/html/HTMLFormSubmission.h
dom/html/HTMLImageElement.cpp
dom/html/HTMLInputElement.cpp
dom/html/HTMLMediaElement.cpp
dom/ipc/BrowserParent.cpp
dom/ipc/UserActivationIPCUtils.h
dom/ipc/moz.build
dom/media/AutoplayPolicy.cpp
dom/media/MediaManager.cpp
dom/payments/PaymentRequest.cpp
dom/promise/Promise.cpp
dom/svg/SVGFEImageElement.cpp
dom/svg/SVGImageElement.cpp
dom/vr/VRDisplay.cpp
dom/webidl/Document.webidl
dom/xhr/XMLHttpRequestMainThread.cpp
layout/base/PresShell.cpp
layout/xul/nsMenuFrame.cpp
layout/xul/nsXULPopupManager.cpp
xpcom/base/CycleCollectedJSContext.cpp
--- a/accessible/base/AccEvent.cpp
+++ b/accessible/base/AccEvent.cpp
@@ -7,18 +7,18 @@
 #include "AccEvent.h"
 
 #include "nsAccUtils.h"
 #include "DocAccessible.h"
 #include "xpcAccEvents.h"
 #include "States.h"
 #include "xpcAccessibleDocument.h"
 
+#include "mozilla/EventStateManager.h"
 #include "mozilla/dom/Selection.h"
-#include "mozilla/dom/UserActivation.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 static_assert(static_cast<bool>(eNoUserInput) == false &&
                   static_cast<bool>(eFromUserInput) == true,
               "EIsFromUserInput cannot be casted to bool");
 
@@ -28,17 +28,17 @@ static_assert(static_cast<bool>(eNoUserI
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccEvent constructors
 
 AccEvent::AccEvent(uint32_t aEventType, Accessible* aAccessible,
                    EIsFromUserInput aIsFromUserInput, EEventRule aEventRule)
     : mEventType(aEventType), mEventRule(aEventRule), mAccessible(aAccessible) {
   if (aIsFromUserInput == eAutoDetect)
-    mIsFromUserInput = dom::UserActivation::IsHandlingUserInput();
+    mIsFromUserInput = EventStateManager::IsHandlingUserInput();
   else
     mIsFromUserInput = aIsFromUserInput == eFromUserInput ? true : false;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccEvent cycle collection
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(AccEvent)
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -64,30 +64,30 @@
 #include "nsIServiceManager.h"
 #include "nsWhitespaceTokenizer.h"
 #include "nsAttrName.h"
 #include "nsPersistentProperties.h"
 
 #include "mozilla/Assertions.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/ErrorResult.h"
+#include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/PresShell.h"
 #include "mozilla/Unused.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/StaticPrefs_ui.h"
 #include "mozilla/dom/CanvasRenderingContext2D.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
 #include "mozilla/dom/HTMLBodyElement.h"
 #include "mozilla/dom/KeyboardEventBinding.h"
 #include "mozilla/dom/TreeWalker.h"
-#include "mozilla/dom/UserActivation.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible: nsISupports and cycle collection
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(Accessible)
@@ -748,17 +748,17 @@ void Accessible::TakeFocus() const {
         focusContent = widgetElm;
         widget->SetCurrentItem(this);
       }
     }
   }
 
   nsFocusManager* fm = nsFocusManager::GetFocusManager();
   if (fm) {
-    dom::AutoHandlingUserInputStatePusher inputStatePusher(true);
+    AutoHandlingUserInputStatePusher inputStatePusher(true);
     // XXXbz: Can we actually have a non-element content here?
     RefPtr<Element> element =
         focusContent->IsElement() ? focusContent->AsElement() : nullptr;
     fm->SetFocus(element, 0);
   }
 }
 
 void Accessible::XULElmName(DocAccessible* aDocument, nsIContent* aElm,
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -34,25 +34,25 @@
 #include "nsViewManager.h"
 #include "nsIScrollableFrame.h"
 #include "nsUnicharUtils.h"
 #include "nsIURI.h"
 #include "nsIWebNavigation.h"
 #include "nsFocusManager.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Assertions.h"
+#include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/HTMLEditor.h"
 #include "mozilla/PresShell.h"
 #include "mozilla/TextEditor.h"
 #include "mozilla/dom/BrowserChild.h"
 #include "mozilla/dom/DocumentType.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/MutationEventBinding.h"
-#include "mozilla/dom/UserActivation.h"
 #include "HTMLElementAccessibles.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Static member initialization
 
@@ -282,17 +282,17 @@ Accessible* DocAccessible::FocusedChild(
   // be contained within the current document.
   return FocusMgr()->FocusedAccessible();
 }
 
 void DocAccessible::TakeFocus() const {
   // Focus the document.
   nsFocusManager* fm = nsFocusManager::GetFocusManager();
   RefPtr<dom::Element> newFocus;
-  dom::AutoHandlingUserInputStatePusher inputStatePusher(true);
+  AutoHandlingUserInputStatePusher inputStatePusher(true);
   fm->MoveFocus(mDocumentNode->GetWindow(), nullptr,
                 nsFocusManager::MOVEFOCUS_ROOT, 0, getter_AddRefs(newFocus));
 }
 
 // HyperTextAccessible method
 already_AddRefed<TextEditor> DocAccessible::GetEditor() const {
   // Check if document is editable (designMode="on" case). Otherwise check if
   // the html:body (for HTML document case) or document element is editable.
--- a/docshell/base/BrowsingContext.cpp
+++ b/docshell/base/BrowsingContext.cpp
@@ -12,17 +12,16 @@
 #include "mozilla/dom/BrowsingContextGroup.h"
 #include "mozilla/dom/BrowsingContextBinding.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Location.h"
 #include "mozilla/dom/LocationBinding.h"
 #include "mozilla/dom/StructuredCloneTags.h"
-#include "mozilla/dom/UserActivationIPCUtils.h"
 #include "mozilla/dom/WindowBinding.h"
 #include "mozilla/dom/WindowGlobalChild.h"
 #include "mozilla/dom/WindowGlobalParent.h"
 #include "mozilla/dom/WindowProxyHolder.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/HashTable.h"
 #include "mozilla/Logging.h"
@@ -692,65 +691,43 @@ JSObject* BrowsingContext::ReadStructure
     if (!GetOrCreateDOMReflector(aCx, context, &val) || !val.isObject()) {
       return nullptr;
     }
   }
   return val.toObjectOrNull();
 }
 
 void BrowsingContext::NotifyUserGestureActivation() {
-  SetUserActivationState(UserActivation::State::FullActivated);
+  SetIsActivatedByUserGesture(true);
 }
 
 void BrowsingContext::NotifyResetUserGestureActivation() {
-  SetUserActivationState(UserActivation::State::None);
-}
-
-bool BrowsingContext::HasBeenUserGestureActivated() {
-  return mUserActivationState != UserActivation::State::None;
+  SetIsActivatedByUserGesture(false);
 }
 
 bool BrowsingContext::HasValidTransientUserGestureActivation() {
   MOZ_ASSERT(mIsInProcess);
 
-  if (mUserActivationState != UserActivation::State::FullActivated) {
+  if (!mIsActivatedByUserGesture) {
     MOZ_ASSERT(mUserGestureStart.IsNull(),
                "mUserGestureStart should be null if the document hasn't ever "
                "been activated by user gesture");
     return false;
   }
 
   MOZ_ASSERT(!mUserGestureStart.IsNull(),
              "mUserGestureStart shouldn't be null if the document has ever "
              "been activated by user gesture");
   TimeDuration timeout = TimeDuration::FromMilliseconds(
       StaticPrefs::dom_user_activation_transient_timeout());
 
   return timeout <= TimeDuration() ||
          (TimeStamp::Now() - mUserGestureStart) <= timeout;
 }
 
-bool BrowsingContext::ConsumeTransientUserGestureActivation() {
-  MOZ_ASSERT(mIsInProcess);
-
-  if (!HasValidTransientUserGestureActivation()) {
-    return false;
-  }
-
-  BrowsingContext* top = Top();
-  top->PreOrderWalk([&](BrowsingContext* aContext) {
-    if (aContext->GetUserActivationState() ==
-        UserActivation::State::FullActivated) {
-      aContext->SetUserActivationState(UserActivation::State::HasBeenActivated);
-    }
-  });
-
-  return true;
-}
-
 NS_IMPL_CYCLE_COLLECTION_CLASS(BrowsingContext)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowsingContext)
   if (sBrowsingContexts) {
     sBrowsingContexts->Remove(tmp->Id());
   }
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell, mChildren, mParent, mGroup,
@@ -1086,30 +1063,28 @@ void BrowsingContext::StartDelayedAutopl
   if (!mDocShell) {
     return;
   }
   AUTOPLAY_LOG("%s : StartDelayedAutoplayMediaComponents for bc 0x%08" PRIx64,
                XRE_IsParentProcess() ? "Parent" : "Child", Id());
   mDocShell->StartDelayedAutoplayMediaComponents();
 }
 
-void BrowsingContext::DidSetUserActivationState() {
+void BrowsingContext::DidSetIsActivatedByUserGesture() {
   MOZ_ASSERT_IF(!mIsInProcess, mUserGestureStart.IsNull());
-  USER_ACTIVATION_LOG("Set user gesture activation %" PRIu8
-                      " for %s browsing context 0x%08" PRIx64,
-                      static_cast<uint8_t>(mUserActivationState),
-                      XRE_IsParentProcess() ? "Parent" : "Child", Id());
+  USER_ACTIVATION_LOG(
+      "Set user gesture activation %d for %s browsing context 0x%08" PRIx64,
+      mIsActivatedByUserGesture, XRE_IsParentProcess() ? "Parent" : "Child",
+      Id());
   if (mIsInProcess) {
     USER_ACTIVATION_LOG(
         "Set user gesture start time for %s browsing context 0x%08" PRIx64,
         XRE_IsParentProcess() ? "Parent" : "Child", Id());
     mUserGestureStart =
-        (mUserActivationState == UserActivation::State::FullActivated)
-            ? TimeStamp::Now()
-            : TimeStamp();
+        mIsActivatedByUserGesture ? TimeStamp::Now() : TimeStamp();
   }
 }
 
 void BrowsingContext::DidSetMuted() {
   MOZ_ASSERT(!mParent, "Set muted flag on non top-level context!");
   USER_ACTIVATION_LOG("Set audio muted %d for %s browsing context 0x%08" PRIx64,
                       mMuted, XRE_IsParentProcess() ? "Parent" : "Child", Id());
   PreOrderWalk([&](BrowsingContext* aContext) {
--- a/docshell/base/BrowsingContext.h
+++ b/docshell/base/BrowsingContext.h
@@ -8,17 +8,16 @@
 #define mozilla_dom_BrowsingContext_h
 
 #include "mozilla/Maybe.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/Tuple.h"
 #include "mozilla/WeakPtr.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/LocationBase.h"
-#include "mozilla/dom/UserActivation.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIDocShell.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsWrapperCache.h"
 #include "nsILoadInfo.h"
 
@@ -275,30 +274,21 @@ class BrowsingContext : public nsWrapper
   // by user gesture, and we would set the flag in the top level browsing
   // context.
   void NotifyUserGestureActivation();
 
   // This function would be called when we want to reset the user gesture
   // activation flag of the top level browsing context.
   void NotifyResetUserGestureActivation();
 
-  // Return true if its corresponding document has been activated by user
-  // gesture.
-  bool HasBeenUserGestureActivated();
-
   // Return true if its corresponding document has transient user gesture
   // activation and the transient user gesture activation haven't yet timed
   // out.
   bool HasValidTransientUserGestureActivation();
 
-  // Return true if the corresponding document has valid transient user gesture
-  // activation and the transient user gesture activation had been consumed
-  // successfully.
-  bool ConsumeTransientUserGestureActivation();
-
   // Return the window proxy object that corresponds to this browsing context.
   inline JSObject* GetWindowProxy() const { return mWindowProxy; }
   // Set the window proxy object that corresponds to this browsing context.
   void SetWindowProxy(JS::Handle<JSObject*> aWindowProxy) {
     mWindowProxy = aWindowProxy;
   }
 
   MOZ_DECLARE_WEAKREFERENCE_TYPENAME(BrowsingContext)
@@ -508,17 +498,18 @@ class BrowsingContext : public nsWrapper
   bool MaySetOpener(const uint64_t& aValue, ContentParent* aSource) {
     if (aValue != 0) {
       RefPtr<BrowsingContext> opener = Get(aValue);
       return opener && opener->Group() == Group();
     }
     return true;
   }
 
-  void DidSetUserActivationState();
+  // Ensure that we only set the flag on the top level browsing context.
+  void DidSetIsActivatedByUserGesture();
 
   // Ensure that we only set the flag on the top level browsingContext.
   // And then, we do a pre-order walk in the tree to refresh the
   // volume of all media elements.
   void DidSetMuted();
 
   // Type of BrowsingContent
   const Type mType;
--- a/docshell/base/BrowsingContextFieldList.h
+++ b/docshell/base/BrowsingContextFieldList.h
@@ -18,17 +18,17 @@ MOZ_BC_FIELD(OpenerPolicy, nsILoadInfo::
 // The current opener for this BrowsingContext. This is a weak reference, and
 // stored as the opener ID.
 MOZ_BC_FIELD(OpenerId, uint64_t)
 
 MOZ_BC_FIELD(OnePermittedSandboxedNavigatorId, uint64_t)
 
 MOZ_BC_FIELD(HadOriginalOpener, bool)
 
-// This field controls whether the browsing context is currently considered to
-// be activated by a gesture.
-MOZ_BC_FIELD(UserActivationState, UserActivation::State)
+// Toplevel browsing contexts only. This field controls whether the browsing
+// context is currently considered to be activated by a gesture.
+MOZ_BC_FIELD(IsActivatedByUserGesture, bool)
 
 // Hold the audio muted state and should be used
 // on top level browsing contexts only.
 MOZ_BC_FIELD(Muted, bool)
 
 #undef MOZ_BC_FIELD
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -61,17 +61,16 @@
 #include "mozilla/dom/ScreenOrientation.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/ServiceWorkerInterceptController.h"
 #include "mozilla/dom/ServiceWorkerUtils.h"
 #include "mozilla/dom/SessionStorageManager.h"
 #include "mozilla/dom/BrowserChild.h"
 #include "mozilla/dom/TabGroup.h"
 #include "mozilla/dom/ToJSValue.h"
-#include "mozilla/dom/UserActivation.h"
 #include "mozilla/dom/ChildSHistory.h"
 #include "mozilla/dom/nsCSPContext.h"
 #include "mozilla/dom/LoadURIOptionsBinding.h"
 
 #include "mozilla/net/DocumentChannelChild.h"
 #include "mozilla/net/UrlClassifierFeatureFactory.h"
 #include "ReferrerInfo.h"
 
@@ -13043,17 +13042,17 @@ nsresult nsDocShell::OnLeaveLink() {
     rv = browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_LINK,
                                   EmptyString().get());
   }
   return rv;
 }
 
 bool nsDocShell::ShouldBlockLoadingForBackButton() {
   if (!(mLoadType & LOAD_CMD_HISTORY) ||
-      UserActivation::IsHandlingUserInput() ||
+      EventStateManager::IsHandlingUserInput() ||
       !Preferences::GetBool("accessibility.blockjsredirection")) {
     return false;
   }
 
   bool canGoForward = false;
   GetCanGoForward(&canGoForward);
   return canGoForward;
 }
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -108,17 +108,16 @@
 #include "mozilla/dom/TreeOrderedArrayInlines.h"
 #include "mozilla/dom/ResizeObserver.h"
 #include "mozilla/dom/ResizeObserverController.h"
 #include "mozilla/dom/ServiceWorkerContainer.h"
 #include "mozilla/dom/ScriptLoader.h"
 #include "mozilla/dom/ShadowIncludingTreeIterator.h"
 #include "mozilla/dom/StyleSheetList.h"
 #include "mozilla/dom/SVGUseElement.h"
-#include "mozilla/dom/UserActivation.h"
 #include "mozilla/net/CookieSettings.h"
 #include "nsGenericHTMLElement.h"
 #include "mozilla/dom/CDATASection.h"
 #include "mozilla/dom/ProcessingInstruction.h"
 #include "mozilla/dom/PostMessageEvent.h"
 #include "nsDOMString.h"
 #include "nsNodeUtils.h"
 #include "nsLayoutUtils.h"  // for GetFrameForPoint
@@ -14018,17 +14017,17 @@ void Document::RequestPointerLock(Elemen
     return;
   }
 
   if (const char* msg = GetPointerLockError(aElement, pointerLockedElement)) {
     DispatchPointerLockError(this, msg);
     return;
   }
 
-  bool userInputOrSystemCaller = UserActivation::IsHandlingUserInput() ||
+  bool userInputOrSystemCaller = EventStateManager::IsHandlingUserInput() ||
                                  aCallerType == CallerType::System;
   nsCOMPtr<nsIRunnable> request =
       new PointerLockRequest(aElement, userInputOrSystemCaller);
   Dispatch(TaskCategory::Other, request.forget());
 }
 
 bool Document::SetPointerLock(Element* aElement, StyleCursorKind aCursorStyle) {
   MOZ_ASSERT(!aElement || aElement->OwnerDoc() == this,
@@ -14531,22 +14530,23 @@ void Document::SetCssUseCounterBits() {
     auto id = nsCSSPropertyID(i);
     if (Servo_IsPropertyIdRecordedInUseCounter(mStyleUseCounters.get(), id)) {
       SetUseCounter(nsCSSProps::UseCounterFor(id));
     }
   }
 
   for (size_t i = 0; i < size_t(CountedUnknownProperty::Count); ++i) {
     if (Servo_IsUnknownPropertyRecordedInUseCounter(
-            mStyleUseCounters.get(), CountedUnknownProperty(i))) {
+          mStyleUseCounters.get(), CountedUnknownProperty(i))) {
       SetUseCounter(UseCounter(eUseCounter_FirstCountedUnknownProperty + i));
     }
   }
 }
 
+
 void Document::PropagateUseCountersToPage() {
   if (mDisplayDocument) {
     // If we are a resource document, we won't have a docshell and so we won't
     // record any page use counters on this document.  Instead, we should
     // forward it up to the document that loaded us.
     MOZ_ASSERT(!mDocumentContainer);
     return PropagateUseCounters(mDisplayDocument);
   }
@@ -15009,38 +15009,33 @@ void Document::NotifyUserGestureActivati
   for (RefPtr<BrowsingContext> bc = GetBrowsingContext(); bc;
        bc = bc->GetParent()) {
     bc->NotifyUserGestureActivation();
   }
 }
 
 bool Document::HasBeenUserGestureActivated() {
   RefPtr<BrowsingContext> bc = GetBrowsingContext();
-  return bc && bc->HasBeenUserGestureActivated();
+  return bc ? bc->GetIsActivatedByUserGesture() : false;
 }
 
 void Document::ClearUserGestureActivation() {
   if (RefPtr<BrowsingContext> bc = GetBrowsingContext()) {
     bc = bc->Top();
     bc->PreOrderWalk([&](BrowsingContext* aContext) {
       aContext->NotifyResetUserGestureActivation();
     });
   }
 }
 
 bool Document::HasValidTransientUserGestureActivation() {
   RefPtr<BrowsingContext> bc = GetBrowsingContext();
   return bc && bc->HasValidTransientUserGestureActivation();
 }
 
-bool Document::ConsumeTransientUserGestureActivation() {
-  RefPtr<BrowsingContext> bc = GetBrowsingContext();
-  return bc && bc->ConsumeTransientUserGestureActivation();
-}
-
 void Document::SetDocTreeHadAudibleMedia() {
   Document* topLevelDoc = GetTopLevelContentDocument();
   if (!topLevelDoc) {
     return;
   }
 
   topLevelDoc->mDocTreeHadAudibleMedia = true;
 }
@@ -15625,17 +15620,17 @@ already_AddRefed<mozilla::dom::Promise> 
   // Step 7. If the sub frame's parent frame is not the top frame, reject.
   Document* parent = GetInProcessParentDocument();
   if (parent && !parent->IsTopLevelContentDocument()) {
     promise->MaybeRejectWithUndefined();
     return promise.forget();
   }
 
   // Step 8. If the browser is not processing a user gesture, reject.
-  if (!UserActivation::IsHandlingUserInput()) {
+  if (!EventStateManager::IsHandlingUserInput()) {
     promise->MaybeRejectWithUndefined();
     return promise.forget();
   }
 
   // Step 9. Check any additional rules that the browser has.
   //         Examples: Whitelists, blacklists, on-device classification,
   //         user settings, anti-clickjacking heuristics, or prompting the
   //         user for explicit permission. Reject if some rule is not fulfilled.
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -3880,19 +3880,16 @@ class Document : public nsINode,
   // Return true if NotifyUserGestureActivation() has been called on any
   // document in the document tree.
   bool HasBeenUserGestureActivated();
 
   // Return true if there is transient user gesture activation and it hasn't yet
   // timed out.
   bool HasValidTransientUserGestureActivation();
 
-  // Return true.
-  bool ConsumeTransientUserGestureActivation();
-
   BrowsingContext* GetBrowsingContext() const;
 
   // This document is a WebExtension page, it might be a background page, a
   // popup, a visible tab, a visible iframe ...e.t.c.
   bool IsExtensionPage() const;
 
   bool HasScriptsBlockedBySandbox();
 
--- a/dom/base/PopupBlocker.cpp
+++ b/dom/base/PopupBlocker.cpp
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/PopupBlocker.h"
-#include "mozilla/dom/UserActivation.h"
-#include "mozilla/MouseEvents.h"
+#include "mozilla/EventStateManager.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/StaticPrefs_dom.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/TimeStamp.h"
 #include "nsXULPopupManager.h"
 #include "nsIPermissionManager.h"
 
 namespace mozilla {
@@ -181,18 +180,18 @@ PopupBlocker::PopupControlState PopupBlo
       return PopupBlocker::openAllowed;
     }
   }
 
   switch (aEvent->mClass) {
     case eBasicEventClass:
       // For these following events only allow popups if they're
       // triggered while handling user input. See
-      // UserActivation::IsUserInteractionEvent() for details.
-      if (UserActivation::IsHandlingUserInput()) {
+      // EventStateManager::IsUserInteractionEvent() for details.
+      if (EventStateManager::IsHandlingUserInput()) {
         abuse = PopupBlocker::openBlocked;
         switch (aEvent->mMessage) {
           case eFormSelect:
             if (PopupAllowedForEvent("select")) {
               abuse = PopupBlocker::openControlled;
             }
             break;
           case eFormChange:
@@ -203,35 +202,35 @@ PopupBlocker::PopupControlState PopupBlo
           default:
             break;
         }
       }
       break;
     case eEditorInputEventClass:
       // For this following event only allow popups if it's triggered
       // while handling user input. See
-      // UserActivation::IsUserInteractionEvent() for details.
-      if (UserActivation::IsHandlingUserInput()) {
+      // EventStateManager::IsUserInteractionEvent() for details.
+      if (EventStateManager::IsHandlingUserInput()) {
         abuse = PopupBlocker::openBlocked;
         switch (aEvent->mMessage) {
           case eEditorInput:
             if (PopupAllowedForEvent("input")) {
               abuse = PopupBlocker::openControlled;
             }
             break;
           default:
             break;
         }
       }
       break;
     case eInputEventClass:
       // For this following event only allow popups if it's triggered
       // while handling user input. See
-      // UserActivation::IsUserInteractionEvent() for details.
-      if (UserActivation::IsHandlingUserInput()) {
+      // EventStateManager::IsUserInteractionEvent() for details.
+      if (EventStateManager::IsHandlingUserInput()) {
         abuse = PopupBlocker::openBlocked;
         switch (aEvent->mMessage) {
           case eFormChange:
             if (PopupAllowedForEvent("change")) {
               abuse = PopupBlocker::openControlled;
             }
             break;
           case eXULCommand:
@@ -366,18 +365,18 @@ PopupBlocker::PopupControlState PopupBlo
           default:
             break;
         }
       }
       break;
     case eFormEventClass:
       // For these following events only allow popups if they're
       // triggered while handling user input. See
-      // UserActivation::IsUserInteractionEvent() for details.
-      if (UserActivation::IsHandlingUserInput()) {
+      // EventStateManager::IsUserInteractionEvent() for details.
+      if (EventStateManager::IsHandlingUserInput()) {
         abuse = PopupBlocker::openBlocked;
         switch (aEvent->mMessage) {
           case eFormSubmit:
             if (PopupAllowedForEvent("submit")) {
               abuse = PopupBlocker::openControlled;
             }
             break;
           case eFormReset:
deleted file mode 100644
--- a/dom/base/UserActivation.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/dom/UserActivation.h"
-
-#include "mozilla/TextEvents.h"
-
-namespace mozilla {
-namespace dom {
-
-namespace {
-
-// The current depth of user and keyboard inputs. sUserInputEventDepth
-// is the number of any user input events, page load events and mouse over
-// events.  sUserKeyboardEventDepth is the number of keyboard input events.
-// Incremented whenever we start handling a user input, decremented when we
-// have finished handling a user input. This depth is *not* reset in case
-// of nested event loops.
-static int32_t sUserInputEventDepth = 0;
-static int32_t sUserKeyboardEventDepth = 0;
-
-// Time at which we began handling user input. Reset to the epoch
-// once we have finished handling user input.
-static TimeStamp sHandlingInputStart;
-
-// Time at which we began handling the latest user input. Not reset
-// at the end of the input.
-static TimeStamp sLatestUserInputStart;
-
-}  // namespace
-
-/* static */
-bool UserActivation::IsHandlingUserInput() { return sUserInputEventDepth > 0; }
-
-/* static */
-bool UserActivation::IsHandlingKeyboardInput() {
-  return sUserKeyboardEventDepth > 0;
-}
-
-/* static */
-bool UserActivation::IsUserInteractionEvent(const WidgetEvent* aEvent) {
-  if (!aEvent->IsTrusted()) {
-    return false;
-  }
-
-  switch (aEvent->mMessage) {
-    // eKeyboardEventClass
-    case eKeyPress:
-    case eKeyDown:
-    case eKeyUp:
-      // Not all keyboard events are treated as user input, so that popups
-      // can't be opened, fullscreen mode can't be started, etc at
-      // unexpected time.
-      return aEvent->AsKeyboardEvent()->CanTreatAsUserInput();
-    // eBasicEventClass
-    case eFormChange:
-    // eMouseEventClass
-    case eMouseClick:
-    case eMouseDown:
-    case eMouseUp:
-    // ePointerEventClass
-    case ePointerDown:
-    case ePointerUp:
-    // eTouchEventClass
-    case eTouchStart:
-    case eTouchEnd:
-      return true;
-    default:
-      return false;
-  }
-}
-
-/* static */
-void UserActivation::StartHandlingUserInput(EventMessage aMessage) {
-  ++sUserInputEventDepth;
-  if (sUserInputEventDepth == 1) {
-    sLatestUserInputStart = sHandlingInputStart = TimeStamp::Now();
-  }
-  if (WidgetEvent::IsKeyEventMessage(aMessage)) {
-    ++sUserKeyboardEventDepth;
-  }
-}
-
-/* static */
-void UserActivation::StopHandlingUserInput(EventMessage aMessage) {
-  --sUserInputEventDepth;
-  if (sUserInputEventDepth == 0) {
-    sHandlingInputStart = TimeStamp();
-  }
-  if (WidgetEvent::IsKeyEventMessage(aMessage)) {
-    --sUserKeyboardEventDepth;
-  }
-}
-
-/* static */
-TimeStamp UserActivation::GetHandlingInputStart() {
-  return sHandlingInputStart;
-}
-
-/* static */
-TimeStamp UserActivation::LatestUserInputStart() {
-  return sLatestUserInputStart;
-}
-
-//-----------------------------------------------------------------------------
-// mozilla::dom::AutoHandlingUserInputStatePusher
-//-----------------------------------------------------------------------------
-
-AutoHandlingUserInputStatePusher::AutoHandlingUserInputStatePusher(
-    bool aIsHandlingUserInput, WidgetEvent* aEvent)
-    : mMessage(aEvent ? aEvent->mMessage : eVoidEvent),
-      mIsHandlingUserInput(aIsHandlingUserInput) {
-  if (!aIsHandlingUserInput) {
-    return;
-  }
-  UserActivation::StartHandlingUserInput(mMessage);
-}
-
-AutoHandlingUserInputStatePusher::~AutoHandlingUserInputStatePusher() {
-  if (!mIsHandlingUserInput) {
-    return;
-  }
-  UserActivation::StopHandlingUserInput(mMessage);
-}
-
-}  // namespace dom
-}  // namespace mozilla
deleted file mode 100644
--- a/dom/base/UserActivation.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_UserAcitvation_h
-#define mozilla_dom_UserAcitvation_h
-
-#include "mozilla/EventForwards.h"
-
-namespace mozilla {
-namespace dom {
-
-class UserActivation final {
- public:
-  enum class State : uint8_t {
-    // Not activated.
-    None,
-    // It is considered as has-been-activated, but not transient-activated given
-    // that it is being consumed.
-    HasBeenActivated,
-    // It is considered as has-been-activated, and also transient-activated if
-    // haven't timed out.
-    FullActivated,
-    EndGuard_
-  };
-
-  /**
-   * Returns true if the current code is being executed as a result of
-   * user input or keyboard input.  The former includes anything that is
-   * initiated by user, with the exception of page load events or mouse
-   * over events.  And the latter returns true when one of the user inputs
-   * is an input from keyboard.  If these methods are called from asynchronously
-   * executed code, such as during layout reflows, it will return false.
-   */
-  static bool IsHandlingUserInput();
-  static bool IsHandlingKeyboardInput();
-
-  /**
-   * Returns true if the event is considered as user interaction event. I.e.,
-   * enough obvious input to allow to open popup, etc. Otherwise, returns false.
-   */
-  static bool IsUserInteractionEvent(const WidgetEvent* aEvent);
-
-  /**
-   * StartHandlingUserInput() is called when we start to handle a user input.
-   * StopHandlingUserInput() is called when we finish handling a user input.
-   * If the caller knows which input event caused that, it should set
-   * aMessage to the event message.  Otherwise, set eVoidEvent.
-   * Note that StopHandlingUserInput() caller should call it with exactly same
-   * event message as its corresponding StartHandlingUserInput() call because
-   * these methods may count the number of specific event message.
-   */
-  static void StartHandlingUserInput(EventMessage aMessage);
-  static void StopHandlingUserInput(EventMessage aMessage);
-
-  static TimeStamp GetHandlingInputStart();
-
-  /**
-   * Get the timestamp at which the latest user input was handled.
-   *
-   * Guaranteed to be monotonic. Until the first user input, return
-   * the epoch.
-   */
-  static TimeStamp LatestUserInputStart();
-};
-
-/**
- * This class is used while processing real user input. During this time, popups
- * are allowed. For mousedown events, mouse capturing is also permitted.
- */
-class MOZ_RAII AutoHandlingUserInputStatePusher final {
- public:
-  explicit AutoHandlingUserInputStatePusher(bool aIsHandlingUserInput,
-                                            WidgetEvent* aEvent = nullptr);
-  ~AutoHandlingUserInputStatePusher();
-
- protected:
-  EventMessage mMessage;
-  bool mIsHandlingUserInput;
-};
-
-}  // namespace dom
-}  // namespace mozilla
-
-#endif  // mozilla_dom_UserAcitvation_h
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -240,17 +240,16 @@ EXPORTS.mozilla.dom += [
     'Timeout.h',
     'TimeoutHandler.h',
     'TimeoutManager.h',
     'TreeIterator.h',
     'TreeOrderedArray.h',
     'TreeOrderedArrayInlines.h',
     'TreeWalker.h',
     'UIDirectionManager.h',
-    'UserActivation.h',
     'ViewportMetaData.h',
     'VisualViewport.h',
     'WindowOrientationObserver.h',
     'WindowProxyHolder.h',
 ]
 
 if CONFIG['FUZZING']:
     EXPORTS.mozilla.dom += [
@@ -412,17 +411,16 @@ UNIFIED_SOURCES += [
     'ThirdPartyUtil.cpp',
     'Timeout.cpp',
     'TimeoutBudgetManager.cpp',
     'TimeoutExecutor.cpp',
     'TimeoutHandler.cpp',
     'TimeoutManager.cpp',
     'TreeWalker.cpp',
     'UIDirectionManager.cpp',
-    'UserActivation.cpp',
     'ViewportMetaData.cpp',
     'VisualViewport.cpp',
     'WindowDestroyedEvent.cpp',
     'WindowNamedPropertiesHandler.cpp',
     'WindowOrientationObserver.cpp',
     'XPathGenerator.cpp',
 ]
 
--- a/dom/base/nsContentPermissionHelper.cpp
+++ b/dom/base/nsContentPermissionHelper.cpp
@@ -2,29 +2,29 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <map>
 #include "nsCOMPtr.h"
 #include "nsIPrincipal.h"
-#include "mozilla/dom/BrowserChild.h"
-#include "mozilla/dom/BrowserParent.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/PContentPermission.h"
 #include "mozilla/dom/Performance.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/PContentPermissionRequestParent.h"
 #include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/dom/UserActivation.h"
+#include "mozilla/dom/BrowserChild.h"
+#include "mozilla/dom/BrowserParent.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/EventStateManager.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Unused.h"
 #include "nsComponentManagerUtils.h"
 #include "nsArrayUtils.h"
 #include "nsIMutableArray.h"
 #include "nsContentPermissionHelper.h"
 #include "nsJSUtils.h"
 #include "nsISupportsPrimitives.h"
@@ -546,17 +546,17 @@ ContentPermissionRequestBase::ContentPer
     nsIPrincipal* aPrincipal, nsPIDOMWindowInner* aWindow,
     const nsACString& aPrefName, const nsACString& aType)
     : mPrincipal(aPrincipal),
       mTopLevelPrincipal(aWindow ? ::GetTopLevelPrincipal(aWindow) : nullptr),
       mWindow(aWindow),
       mRequester(aWindow ? new nsContentPermissionRequester(aWindow) : nullptr),
       mPrefName(aPrefName),
       mType(aType),
-      mIsHandlingUserInput(UserActivation::IsHandlingUserInput()),
+      mIsHandlingUserInput(EventStateManager::IsHandlingUserInput()),
       mUserHadInteractedWithDocument(false),
       mDocumentDOMContentLoadedTimestamp(0) {
   if (!aWindow) {
     return;
   }
 
   Document* doc = aWindow->GetExtantDoc();
   if (!doc) {
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -73,17 +73,16 @@
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/BrowserBridgeChild.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/BrowserParent.h"
 #include "mozilla/dom/Text.h"
 #include "mozilla/dom/TouchEvent.h"
 #include "mozilla/dom/ShadowRoot.h"
 #include "mozilla/dom/XULCommandEvent.h"
-#include "mozilla/dom/UserActivation.h"
 #include "mozilla/dom/WorkerCommon.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/net/CookieSettings.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/gfx/DataSurfaceHelpers.h"
 #include "mozilla/HTMLEditor.h"
@@ -5069,17 +5068,17 @@ void nsContentUtils::TriggerLink(nsICont
       fileName.SetIsVoid(true);  // No actionable download attribute was found.
     }
 
     nsCOMPtr<nsIPrincipal> triggeringPrincipal = aContent->NodePrincipal();
     nsCOMPtr<nsIContentSecurityPolicy> csp = aContent->GetCsp();
 
     nsDocShell::Cast(docShell)->OnLinkClick(
         aContent, aLinkURI, fileName.IsVoid() ? aTargetSpec : EmptyString(),
-        fileName, nullptr, nullptr, UserActivation::IsHandlingUserInput(),
+        fileName, nullptr, nullptr, EventStateManager::IsHandlingUserInput(),
         aIsTrusted, triggeringPrincipal, csp);
   }
 }
 
 /* static */
 void nsContentUtils::GetLinkLocation(Element* aElement,
                                      nsString& aLocationString) {
   nsCOMPtr<nsIURI> hrefURI = aElement->GetHrefURI();
@@ -6389,26 +6388,27 @@ bool nsContentUtils::ChannelShouldInheri
 /* static */
 const char* nsContentUtils::CheckRequestFullscreenAllowed(
     CallerType aCallerType) {
   if (!StaticPrefs::full_screen_api_allow_trusted_requests_only() ||
       aCallerType == CallerType::System) {
     return nullptr;
   }
 
-  if (!UserActivation::IsHandlingUserInput()) {
+  if (!EventStateManager::IsHandlingUserInput()) {
     return "FullscreenDeniedNotInputDriven";
   }
 
   // If more time has elapsed since the user input than is specified by the
   // dom.event.handling-user-input-time-limit pref (default 1 second),
   // disallow fullscreen
   TimeDuration timeout = HandlingUserInputTimeout();
   if (timeout > TimeDuration(nullptr) &&
-      (TimeStamp::Now() - UserActivation::GetHandlingInputStart()) > timeout) {
+      (TimeStamp::Now() - EventStateManager::GetHandlingInputStart()) >
+          timeout) {
     return "FullscreenDeniedNotInputDriven";
   }
 
   // Entering full-screen on mouse mouse event is only allowed with left mouse
   // button
   if (StaticPrefs::full_screen_api_mouse_event_allow_left_button_only() &&
       (EventStateManager::sCurrentMouseBtn == MouseButton::eMiddle ||
        EventStateManager::sCurrentMouseBtn == MouseButton::eRight)) {
@@ -6416,17 +6416,17 @@ const char* nsContentUtils::CheckRequest
   }
 
   return nullptr;
 }
 
 /* static */
 bool nsContentUtils::IsCutCopyAllowed(nsIPrincipal* aSubjectPrincipal) {
   if (StaticPrefs::dom_allow_cut_copy() &&
-      UserActivation::IsHandlingUserInput()) {
+      EventStateManager::IsHandlingUserInput()) {
     return true;
   }
 
   return PrincipalHasPermission(aSubjectPrincipal, nsGkAtoms::clipboardWrite);
 }
 
 /* static */
 bool nsContentUtils::HaveEqualPrincipals(Document* aDoc1, Document* aDoc2) {
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -17,17 +17,16 @@
 #include "nsFrameManager.h"
 #include "nsRefreshDriver.h"
 #include "mozilla/dom/Animation.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/BlobBinding.h"
 #include "mozilla/dom/DocumentInlines.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/Touch.h"
-#include "mozilla/dom/UserActivation.h"
 #include "mozilla/PendingAnimationTracker.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsFrame.h"
 #include "mozilla/layers/ShadowLayers.h"
 #include "mozilla/layers/APZCCallbackHelper.h"
 #include "ClientLayerManager.h"
 #include "nsQueryObject.h"
 #include "CubebDeviceEnumerator.h"
@@ -38,16 +37,17 @@
 
 #include "nsIFrame.h"
 #include "nsIWidget.h"
 #include "nsCharsetSource.h"
 #include "nsJSEnvironment.h"
 #include "nsJSUtils.h"
 
 #include "mozilla/ChaosMode.h"
+#include "mozilla/EventStateManager.h"
 #include "mozilla/MiscEvents.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/PresShell.h"
 #include "mozilla/StaticPrefs_layout.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/TextEventDispatcher.h"
 #include "mozilla/TouchEvents.h"
 
@@ -3235,25 +3235,25 @@ nsDOMWindowUtils::RemoveSheetUsingURIStr
   nsresult rv = NS_NewURI(getter_AddRefs(uri), aSheetURI);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return RemoveSheet(uri, aSheetType);
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetIsHandlingUserInput(bool* aHandlingUserInput) {
-  *aHandlingUserInput = UserActivation::IsHandlingUserInput();
+  *aHandlingUserInput = EventStateManager::IsHandlingUserInput();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetMillisSinceLastUserInput(
     double* aMillisSinceLastUserInput) {
-  TimeStamp lastInput = UserActivation::LatestUserInputStart();
+  TimeStamp lastInput = EventStateManager::LatestUserInputStart();
   if (lastInput.IsNull()) {
     *aMillisSinceLastUserInput = -1.0f;
     return NS_OK;
   }
 
   *aMillisSinceLastUserInput = (TimeStamp::Now() - lastInput).ToMilliseconds();
   return NS_OK;
 }
@@ -3554,17 +3554,17 @@ class HandlingUserInputHelper final : pu
   bool mDestructCalled;
 };
 
 NS_IMPL_ISUPPORTS(HandlingUserInputHelper, nsIJSRAIIHelper)
 
 HandlingUserInputHelper::HandlingUserInputHelper(bool aHandlingUserInput)
     : mHandlingUserInput(aHandlingUserInput), mDestructCalled(false) {
   if (aHandlingUserInput) {
-    UserActivation::StartHandlingUserInput(eVoidEvent);
+    EventStateManager::StartHandlingUserInput(eVoidEvent);
   }
 }
 
 HandlingUserInputHelper::~HandlingUserInputHelper() {
   // We assert, but just in case, make sure we notify the ESM.
   MOZ_ASSERT(mDestructCalled);
   if (!mDestructCalled) {
     Destruct();
@@ -3574,17 +3574,17 @@ HandlingUserInputHelper::~HandlingUserIn
 NS_IMETHODIMP
 HandlingUserInputHelper::Destruct() {
   if (NS_WARN_IF(mDestructCalled)) {
     return NS_ERROR_FAILURE;
   }
 
   mDestructCalled = true;
   if (mHandlingUserInput) {
-    UserActivation::StopHandlingUserInput(eVoidEvent);
+    EventStateManager::StopHandlingUserInput(eVoidEvent);
   }
 
   return NS_OK;
 }
 
 }  // unnamed namespace
 
 NS_IMETHODIMP
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -77,24 +77,24 @@
 #include "mozilla/Components.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/PluginCrashedEvent.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/EventDispatcher.h"
+#include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/widget/IMEData.h"
 #include "mozilla/IntegerPrintfMacros.h"
 #include "mozilla/dom/HTMLObjectElementBinding.h"
 #include "mozilla/dom/HTMLEmbedElement.h"
 #include "mozilla/dom/HTMLObjectElement.h"
-#include "mozilla/dom/UserActivation.h"
 #include "mozilla/net/UrlClassifierFeatureFactory.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/PresShell.h"
 #include "nsChannelClassifier.h"
 #include "nsFocusManager.h"
 #include "ReferrerInfo.h"
 
 #ifdef XP_WIN
@@ -2325,17 +2325,17 @@ nsresult nsObjectLoadingContent::OpenCha
 
     // Set the initiator type
     nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(httpChan));
     if (timedChannel) {
       timedChannel->SetInitiatorType(thisContent->LocalName());
     }
 
     nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(httpChan));
-    if (cos && UserActivation::IsHandlingUserInput()) {
+    if (cos && EventStateManager::IsHandlingUserInput()) {
       cos->AddClassFlags(nsIClassOfService::UrgentStart);
     }
   }
 
   nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(chan);
   if (scriptChannel) {
     // Allow execution against our context if the principals match
     scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL);
deleted file mode 100644
--- a/dom/base/test/useractivation/file_iframe_consume_user_activation.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <title>user activated iframe</title>
-</head>
-<body>
-<script>
-onload = function() {
-  SpecialPowers.wrap(document).notifyUserGestureActivation();
-  SpecialPowers.wrap(document).consumeTransientUserGestureActivation();
-  parent.postMessage("done", "*");
-}
-</script>
-</body>
-</html>
\ No newline at end of file
--- a/dom/base/test/useractivation/mochitest.ini
+++ b/dom/base/test/useractivation/mochitest.ini
@@ -1,9 +1,7 @@
 [DEFAULT]
 support-files =
   file_empty.html
   file_iframe_user_activated.html
-  file_iframe_consume_user_activation.html
 
 [test_useractivation_has_been_activated.html]
 [test_useractivation_transient.html]
-[test_useractivation_transient_consuming.html]
deleted file mode 100644
--- a/dom/base/test/useractivation/test_useractivation_transient_consuming.html
+++ /dev/null
@@ -1,140 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>User activation test: consume transient flag</title>
-  <script src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script src="/tests/SimpleTest/EventUtils.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
-<iframe></iframe>
-<iframe></iframe>
-<script>
-
-SimpleTest.requestFlakyTimeout("Timeouts are needed to test transient user_activation");
-
-let timeout = SpecialPowers.getIntPref("dom.user_activation.transient.timeout") + 1000;
-
-function waitForEvent(aTarget, aEvent, aCallback) {
-  return new Promise((aResolve) => {
-    aTarget.addEventListener(aEvent, function listener(event) {
-      aCallback(event);
-      aResolve();
-    }, { once: true });
-  });
-}
-
-add_task(async function checkInitialStatus() {
-  ok(!SpecialPowers.wrap(document).consumeTransientUserGestureActivation(),
-     "consume transient-user-activation on top-level document");
-  ok(!SpecialPowers.wrap(frames[0].document).consumeTransientUserGestureActivation(),
-     "consume transient-user-activation on first iframe");
-  ok(!SpecialPowers.wrap(frames[1].document).consumeTransientUserGestureActivation(),
-     "consume transient-user-activation on second iframe");
-});
-
-add_task(async function consumeTransientUserActivation() {
-  // Trigger user activation on the first iframe.
-  SpecialPowers.wrap(frames[0].document).notifyUserGestureActivation();
-
-  // Try to consume transient user activation.
-  ok(!SpecialPowers.wrap(frames[1].document).consumeTransientUserGestureActivation(),
-     "consume transient-user-activation on second iframe");
-  ok(SpecialPowers.wrap(frames[0].document).consumeTransientUserGestureActivation(),
-     "consume transient-user-activation on first iframe");
-  // Consuming a transient-user-activation should affect all tree.
-  ok(!SpecialPowers.wrap(document).consumeTransientUserGestureActivation(),
-     "consume transient-user-activation on top-level document");
-
-  // Check has-valid-transient-user-activation
-  ok(!SpecialPowers.wrap(document).hasValidTransientUserGestureActivation,
-     "check has-valid-transient-user-activation on the top-level document");
-  ok(!SpecialPowers.wrap(frames[0].document).hasValidTransientUserGestureActivation,
-     "check has-valid-transient-user-activation on the first iframe");
-  ok(!SpecialPowers.wrap(frames[1].document).hasValidTransientUserGestureActivation,
-     "check has-valid-transient-user-activation on the second iframe");
-
-  // Should not affect has-been-user-activated
-  ok(SpecialPowers.wrap(document).hasBeenUserGestureActivated,
-     "check has-been-user-activated on the top-level document");
-  ok(SpecialPowers.wrap(frames[0].document).hasBeenUserGestureActivated,
-     "check has-been-user-activated on the first iframe");
-  ok(!SpecialPowers.wrap(frames[1].document).hasBeenUserGestureActivated,
-     "check has-been-user-activated on the second iframe");
-});
-
-add_task(async function consumeTransientUserActivationTimeout() {
-  // Trigger user activation on the first iframe.
-  SpecialPowers.wrap(frames[0].document).notifyUserGestureActivation();
-
-  // Should not able to consume successfully after timeout.
-  await new Promise((aResolve) => {
-    setTimeout(() => {
-      ok(!SpecialPowers.wrap(document).consumeTransientUserGestureActivation(),
-         "consume transient-user-activation on top-level document");
-      ok(!SpecialPowers.wrap(frames[0].document).consumeTransientUserGestureActivation(),
-         "consume transient-user-activation on first iframe");
-      ok(!SpecialPowers.wrap(frames[1].document).consumeTransientUserGestureActivation(),
-         "consume transient-user-activation on second iframe");
-      aResolve();
-    }, timeout);
-  });
-
-  // Trigger user activation again.
-  SpecialPowers.wrap(frames[0].document).notifyUserGestureActivation();
-
-  // Try to consume transient user activation.
-  ok(!SpecialPowers.wrap(frames[1].document).consumeTransientUserGestureActivation(),
-     "consume transient-user-activation on second iframe");
-  ok(SpecialPowers.wrap(frames[0].document).consumeTransientUserGestureActivation(),
-     "consume transient-user-activation on first iframe");
-  // Consuming a transient-user-activation should affect all tree.
-  ok(!SpecialPowers.wrap(document).consumeTransientUserGestureActivation(),
-     "consume transient-user-activation on top-level document");
-});
-
-add_task(async function iframeNavigation() {
-  // Trigger user activation on the first iframe.
-  SpecialPowers.wrap(frames[0].document).notifyUserGestureActivation();
-
-  // Navigate away from current page.
-  frames[0].frameElement.src = "file_empty.html";
-  await waitForEvent(frames[0].frameElement, "load", () => {});
-
-  // Try to consume transient user activation.
-  ok(!SpecialPowers.wrap(frames[1].document).consumeTransientUserGestureActivation(),
-     "consume transient-user-activation on second iframe");
-  ok(!SpecialPowers.wrap(frames[0].document).consumeTransientUserGestureActivation(),
-     "consume transient-user-activation on first iframe");
-  ok(SpecialPowers.wrap(document).consumeTransientUserGestureActivation(),
-     "consume transient-user-activation on top-level document");
-});
-
-add_task(async function triggerUserActivationOnCrossOriginFrame() {
-  // Reset the activation flag.
-  SpecialPowers.wrap(document).clearUserGestureActivation();
-
-  // load cross-origin test page on iframe.
-  frames[0].frameElement.src = "https://example.com/tests/dom/base/test/useractivation/file_iframe_consume_user_activation.html";
-  await waitForEvent(window, "message", (event) => {
-    if (event.data === "done") {
-      ok(!SpecialPowers.wrap(document).consumeTransientUserGestureActivation(),
-         "consume transient-user-activation on top-level document");
-      ok(!SpecialPowers.wrap(document).hasValidTransientUserGestureActivation,
-         "check has-valid-transient-user-activation on the top-level document");
-      ok(!SpecialPowers.wrap(frames[1].document).hasValidTransientUserGestureActivation,
-         "check has-valid-transient-user-activation on the second iframe");
-    } else {
-      ok(false, "receive unexpected message: " + event.data);
-    }
-  });
-});
-
-add_task(async function endTests() {
-  // Reset the activation flag in order not to interfere following test in the
-  // verify mode which would run the test using same document couple times.
-  SpecialPowers.wrap(document).clearUserGestureActivation();
-});
-
-</script>
-</body>
--- a/dom/canvas/CanvasUtils.cpp
+++ b/dom/canvas/CanvasUtils.cpp
@@ -6,19 +6,19 @@
 #include <stdlib.h>
 #include <stdarg.h>
 
 #include "nsIServiceManager.h"
 
 #include "nsIConsoleService.h"
 #include "nsICanvasRenderingContextInternal.h"
 #include "nsIHTMLCollection.h"
+#include "mozilla/dom/HTMLCanvasElement.h"
 #include "mozilla/dom/BrowserChild.h"
-#include "mozilla/dom/HTMLCanvasElement.h"
-#include "mozilla/dom/UserActivation.h"
+#include "mozilla/EventStateManager.h"
 #include "mozilla/StaticPrefs_privacy.h"
 #include "nsIPrincipal.h"
 
 #include "nsGfxCIID.h"
 
 #include "nsTArray.h"
 
 #include "CanvasUtils.h"
@@ -137,17 +137,17 @@ bool IsImageExtractionAllowed(Document* 
 
   // At this point, permission is unknown
   // (nsIPermissionManager::UNKNOWN_ACTION).
 
   // Check if the request is in response to user input
   bool isAutoBlockCanvas =
       StaticPrefs::
           privacy_resistFingerprinting_autoDeclineNoUserInputCanvasPrompts() &&
-      !UserActivation::IsHandlingUserInput();
+      !EventStateManager::IsHandlingUserInput();
 
   if (isAutoBlockCanvas) {
     nsAutoString message;
     message.AppendPrintf(
         "Blocked %s from extracting canvas data because no user input was "
         "detected.",
         docURISpec.get());
     nsContentUtils::ReportToConsoleNonLocalized(
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -25,17 +25,16 @@
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/EventTargetBinding.h"
 #include "mozilla/dom/LoadedScript.h"
 #include "mozilla/dom/PopupBlocker.h"
 #include "mozilla/dom/ScriptLoader.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/TouchEvent.h"
-#include "mozilla/dom/UserActivation.h"
 #include "mozilla/TimelineConsumers.h"
 #include "mozilla/EventTimelineMarker.h"
 #include "mozilla/TimeStamp.h"
 
 #include "EventListenerService.h"
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "nsDOMCID.h"
@@ -1131,18 +1130,18 @@ void EventListenerManager::HandleEventIn
     // Assume that if only aEventStatus claims that the event has already been
     // consumed, the consumer is default event handler.
     aEvent->PreventDefault();
   }
 
   Maybe<AutoHandlingUserInputStatePusher> userInputStatePusher;
   Maybe<AutoPopupStatePusher> popupStatePusher;
   if (mIsMainThreadELM) {
-    userInputStatePusher.emplace(UserActivation::IsUserInteractionEvent(aEvent),
-                                 aEvent);
+    userInputStatePusher.emplace(
+        EventStateManager::IsUserInteractionEvent(aEvent), aEvent);
     popupStatePusher.emplace(
         PopupBlocker::GetEventPopupControlState(aEvent, *aDOMEvent));
   }
 
   bool hasListener = false;
   bool hasListenerForCurrentGroup = false;
   bool usingLegacyMessage = false;
   bool hasRemovedListener = false;
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -23,17 +23,16 @@
 #include "mozilla/dom/DragEvent.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/FrameLoaderBinding.h"
 #include "mozilla/dom/MouseEventBinding.h"
 #include "mozilla/dom/BrowserChild.h"
 #include "mozilla/dom/BrowserParent.h"
 #include "mozilla/dom/UIEvent.h"
 #include "mozilla/dom/UIEventBinding.h"
-#include "mozilla/dom/UserActivation.h"
 #include "mozilla/dom/WheelEventBinding.h"
 #include "mozilla/StaticPrefs_dom.h"
 #include "mozilla/StaticPrefs_layout.h"
 #include "mozilla/StaticPrefs_mousewheel.h"
 #include "mozilla/StaticPrefs_ui.h"
 #include "mozilla/StaticPrefs_zoom.h"
 
 #include "ContentEventHandler.h"
@@ -195,16 +194,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
 NS_INTERFACE_MAP_END
 
 /******************************************************************/
 /* mozilla::EventStateManager                                     */
 /******************************************************************/
 
 static uint32_t sESMInstanceCount = 0;
 
+int32_t EventStateManager::sUserInputEventDepth = 0;
+int32_t EventStateManager::sUserKeyboardEventDepth = 0;
 bool EventStateManager::sNormalLMouseEventInProcess = false;
 int16_t EventStateManager::sCurrentMouseBtn = MouseButton::eNotPressed;
 EventStateManager* EventStateManager::sActiveESM = nullptr;
 Document* EventStateManager::sMouseOverDocument = nullptr;
 AutoWeakFrame EventStateManager::sLastDragOverFrame = nullptr;
 LayoutDeviceIntPoint EventStateManager::sPreLockPoint =
     LayoutDeviceIntPoint(0, 0);
 LayoutDeviceIntPoint EventStateManager::sLastRefPoint = kInvalidRefPoint;
@@ -212,16 +213,18 @@ CSSIntPoint EventStateManager::sLastScre
 LayoutDeviceIntPoint EventStateManager::sSynthCenteringPoint = kInvalidRefPoint;
 CSSIntPoint EventStateManager::sLastClientPoint = CSSIntPoint(0, 0);
 bool EventStateManager::sIsPointerLocked = false;
 // Reference to the pointer locked element.
 nsWeakPtr EventStateManager::sPointerLockedElement;
 // Reference to the document which requested pointer lock.
 nsWeakPtr EventStateManager::sPointerLockedDoc;
 nsCOMPtr<nsIContent> EventStateManager::sDragOverContent = nullptr;
+TimeStamp EventStateManager::sLatestUserInputStart;
+TimeStamp EventStateManager::sHandlingInputStart;
 
 EventStateManager::WheelPrefs* EventStateManager::WheelPrefs::sInstance =
     nullptr;
 bool EventStateManager::WheelPrefs::sWheelEventsEnabledOnPlugins = true;
 bool EventStateManager::WheelPrefs::sIsAutoDirEnabled = false;
 bool EventStateManager::WheelPrefs::sHonoursRootForAutoDir = false;
 EventStateManager::DeltaAccumulator*
     EventStateManager::DeltaAccumulator::sInstance = nullptr;
@@ -4081,16 +4084,81 @@ class MOZ_STACK_CLASS ESMEventCB : publi
                            &aVisitor.mEventStatus);
       }
     }
   }
 
   nsCOMPtr<nsIContent> mTarget;
 };
 
+/*static*/
+bool EventStateManager::IsUserInteractionEvent(const WidgetEvent* aEvent) {
+  if (!aEvent->IsTrusted()) {
+    return false;
+  }
+
+  switch (aEvent->mMessage) {
+    // eKeyboardEventClass
+    case eKeyPress:
+    case eKeyDown:
+    case eKeyUp:
+      // Not all keyboard events are treated as user input, so that popups
+      // can't be opened, fullscreen mode can't be started, etc at
+      // unexpected time.
+      return aEvent->AsKeyboardEvent()->CanTreatAsUserInput();
+    // eBasicEventClass
+    case eFormChange:
+    // eMouseEventClass
+    case eMouseClick:
+    case eMouseDown:
+    case eMouseUp:
+    // ePointerEventClass
+    case ePointerDown:
+    case ePointerUp:
+    // eTouchEventClass
+    case eTouchStart:
+    case eTouchEnd:
+      return true;
+    default:
+      return false;
+  }
+}
+
+/*static*/
+bool EventStateManager::IsHandlingUserInput() {
+  return sUserInputEventDepth > 0;
+}
+
+/*static*/
+bool EventStateManager::IsHandlingKeyboardInput() {
+  return sUserKeyboardEventDepth > 0;
+}
+
+/*static*/
+void EventStateManager::StartHandlingUserInput(EventMessage aMessage) {
+  ++sUserInputEventDepth;
+  if (sUserInputEventDepth == 1) {
+    sLatestUserInputStart = sHandlingInputStart = TimeStamp::Now();
+  }
+  if (WidgetEvent::IsKeyEventMessage(aMessage)) {
+    ++sUserKeyboardEventDepth;
+  }
+}
+
+/*static*/
+void EventStateManager::StopHandlingUserInput(EventMessage aMessage) {
+  --sUserInputEventDepth;
+  if (sUserInputEventDepth == 0) {
+    sHandlingInputStart = TimeStamp();
+  }
+  if (WidgetEvent::IsKeyEventMessage(aMessage)) {
+    --sUserKeyboardEventDepth;
+  }
+}
+
 static void CreateMouseOrPointerWidgetEvent(
     WidgetMouseEvent* aMouseEvent, EventMessage aMessage,
     nsIContent* aRelatedContent, nsAutoPtr<WidgetMouseEvent>& aNewEvent) {
   WidgetPointerEvent* sourcePointer = aMouseEvent->AsPointerEvent();
   if (sourcePointer) {
     AUTO_PROFILER_LABEL("CreateMouseOrPointerWidgetEvent", OTHER);
 
     nsAutoPtr<WidgetPointerEvent> newPointerEvent;
@@ -6273,9 +6341,30 @@ void EventStateManager::Prefs::Init() {
                                "accessibility.accesskeycausesactivation",
                                sKeyCausesActivation);
   Preferences::AddBoolVarCache(&sClickHoldContextMenu,
                                "ui.click_hold_context_menus",
                                sClickHoldContextMenu);
   sPrefsAlreadyCached = true;
 }
 
+/******************************************************************/
+/* mozilla::AutoHandlingUserInputStatePusher                      */
+/******************************************************************/
+
+AutoHandlingUserInputStatePusher::AutoHandlingUserInputStatePusher(
+    bool aIsHandlingUserInput, WidgetEvent* aEvent)
+    : mMessage(aEvent ? aEvent->mMessage : eVoidEvent),
+      mIsHandlingUserInput(aIsHandlingUserInput) {
+  if (!aIsHandlingUserInput) {
+    return;
+  }
+  EventStateManager::StartHandlingUserInput(mMessage);
+}
+
+AutoHandlingUserInputStatePusher::~AutoHandlingUserInputStatePusher() {
+  if (!mIsHandlingUserInput) {
+    return;
+  }
+  EventStateManager::StopHandlingUserInput(mMessage);
+}
+
 }  // namespace mozilla
--- a/dom/events/EventStateManager.h
+++ b/dom/events/EventStateManager.h
@@ -247,16 +247,55 @@ class EventStateManager : public nsSuppo
    * Checks if the current mouse over element matches the given
    * Element (which has a remote frame), and if so, notifies
    * the BrowserParent of the mouse enter.
    * Called when we reconstruct the BrowserParent and need to
    * recompute state on the new object.
    */
   void RecomputeMouseEnterStateForRemoteFrame(Element& aElement);
 
+  /**
+   * Returns true if the event is considered as user interaction event. I.e.,
+   * enough obvious input to allow to open popup, etc. Otherwise, returns false.
+   */
+  static bool IsUserInteractionEvent(const WidgetEvent* aEvent);
+
+  /**
+   * StartHandlingUserInput() is called when we start to handle a user input.
+   * StopHandlingUserInput() is called when we finish handling a user input.
+   * If the caller knows which input event caused that, it should set
+   * aMessage to the event message.  Otherwise, set eVoidEvent.
+   * Note that StopHandlingUserInput() caller should call it with exactly same
+   * event message as its corresponding StartHandlingUserInput() call because
+   * these methods may count the number of specific event message.
+   */
+  static void StartHandlingUserInput(EventMessage aMessage);
+  static void StopHandlingUserInput(EventMessage aMessage);
+
+  static TimeStamp GetHandlingInputStart() { return sHandlingInputStart; }
+
+  /**
+   * Returns true if the current code is being executed as a result of
+   * user input or keyboard input.  The former includes anything that is
+   * initiated by user, with the exception of page load events or mouse
+   * over events.  And the latter returns true when one of the user inputs
+   * is an input from keyboard.  If these methods are called from asynchronously
+   * executed code, such as during layout reflows, it will return false.
+   */
+  static bool IsHandlingUserInput();
+  static bool IsHandlingKeyboardInput();
+
+  /**
+   * Get the timestamp at which the latest user input was handled.
+   *
+   * Guaranteed to be monotonic. Until the first user input, return
+   * the epoch.
+   */
+  static TimeStamp LatestUserInputStart() { return sLatestUserInputStart; }
+
   nsPresContext* GetPresContext() { return mPresContext; }
 
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(EventStateManager, nsIObserver)
 
   static dom::Document* sMouseOverDocument;
 
   static EventStateManager* GetActiveEventStateManager() { return sActiveESM; }
 
@@ -1211,25 +1250,42 @@ class EventStateManager : public nsSuppo
   uint32_t mLClickCount;
   uint32_t mMClickCount;
   uint32_t mRClickCount;
 
   bool mInTouchDrag;
 
   bool m_haveShutdown;
 
+  // Time at which we began handling user input. Reset to the epoch
+  // once we have finished handling user input.
+  static TimeStamp sHandlingInputStart;
+
+  // Time at which we began handling the latest user input. Not reset
+  // at the end of the input.
+  static TimeStamp sLatestUserInputStart;
+
   RefPtr<OverOutElementsWrapper> mMouseEnterLeaveHelper;
   nsRefPtrHashtable<nsUint32HashKey, OverOutElementsWrapper>
       mPointersEnterLeaveHelper;
 
  public:
   static nsresult UpdateUserActivityTimer(void);
   // Array for accesskey support
   nsCOMArray<nsIContent> mAccessKeys;
 
+  // The current depth of user and keyboard inputs. sUserInputEventDepth
+  // is the number of any user input events, page load events and mouse over
+  // events.  sUserKeyboardEventDepth is the number of keyboard input events.
+  // Incremented whenever we start handling a user input, decremented when we
+  // have finished handling a user input. This depth is *not* reset in case
+  // of nested event loops.
+  static int32_t sUserInputEventDepth;
+  static int32_t sUserKeyboardEventDepth;
+
   static bool sNormalLMouseEventInProcess;
   static int16_t sCurrentMouseBtn;
 
   static EventStateManager* sActiveESM;
 
   static void ClearGlobalActiveContent(EventStateManager* aClearer);
 
   // Functions used for click hold context menus
@@ -1239,16 +1295,31 @@ class EventStateManager : public nsSuppo
   void KillClickHoldTimer();
   void FireContextClick();
 
   MOZ_CAN_RUN_SCRIPT static void SetPointerLock(nsIWidget* aWidget,
                                                 nsIContent* aElement);
   static void sClickHoldCallback(nsITimer* aTimer, void* aESM);
 };
 
+/**
+ * This class is used while processing real user input. During this time, popups
+ * are allowed. For mousedown events, mouse capturing is also permitted.
+ */
+class MOZ_RAII AutoHandlingUserInputStatePusher final {
+ public:
+  explicit AutoHandlingUserInputStatePusher(bool aIsHandlingUserInput,
+                                            WidgetEvent* aEvent = nullptr);
+  ~AutoHandlingUserInputStatePusher();
+
+ protected:
+  EventMessage mMessage;
+  bool mIsHandlingUserInput;
+};
+
 }  // namespace mozilla
 
 // Click and double-click events need to be handled even for content that
 // has no frame. This is required for Web compatibility.
 #define NS_EVENT_NEEDS_FRAME(event)               \
   (!(event)->HasPluginActivationEventMessage() && \
    (event)->mMessage != eMouseClick &&            \
    (event)->mMessage != eMouseDoubleClick &&      \
--- a/dom/events/IMEStateManager.cpp
+++ b/dom/events/IMEStateManager.cpp
@@ -16,21 +16,20 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/PresShell.h"
 #include "mozilla/StaticPrefs_dom.h"
 #include "mozilla/TextComposition.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/ToString.h"
 #include "mozilla/Unused.h"
 #include "mozilla/dom/BrowserBridgeChild.h"
-#include "mozilla/dom/BrowserParent.h"
 #include "mozilla/dom/HTMLFormElement.h"
 #include "mozilla/dom/HTMLTextAreaElement.h"
 #include "mozilla/dom/MouseEventBinding.h"
-#include "mozilla/dom/UserActivation.h"
+#include "mozilla/dom/BrowserParent.h"
 
 #include "HTMLInputElement.h"
 #include "IMEContentObserver.h"
 
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "nsFocusManager.h"
 #include "nsIContent.h"
@@ -1313,19 +1312,19 @@ void IMEStateManager::SetIMEState(const 
   //     of the process type.
   if (aAction.mCause == InputContextAction::CAUSE_UNKNOWN &&
       !XRE_IsContentProcess()) {
     aAction.mCause = InputContextAction::CAUSE_UNKNOWN_CHROME;
   }
 
   if ((aAction.mCause == InputContextAction::CAUSE_UNKNOWN ||
        aAction.mCause == InputContextAction::CAUSE_UNKNOWN_CHROME) &&
-      UserActivation::IsHandlingUserInput()) {
+      EventStateManager::IsHandlingUserInput()) {
     aAction.mCause =
-        UserActivation::IsHandlingKeyboardInput()
+        EventStateManager::IsHandlingKeyboardInput()
             ? InputContextAction::CAUSE_UNKNOWN_DURING_KEYBOARD_INPUT
             : InputContextAction::CAUSE_UNKNOWN_DURING_NON_KEYBOARD_INPUT;
   }
 
   SetInputContext(aWidget, context, aAction);
 }
 
 // static
--- a/dom/fetch/FetchDriver.cpp
+++ b/dom/fetch/FetchDriver.cpp
@@ -28,19 +28,19 @@
 #include "nsProxyRelease.h"
 #include "nsStreamUtils.h"
 #include "nsStringStream.h"
 #include "nsHttpChannel.h"
 
 #include "mozilla/dom/BlobURLProtocolHandler.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/PerformanceStorage.h"
-#include "mozilla/dom/UserActivation.h"
 #include "mozilla/dom/WorkerCommon.h"
 #include "mozilla/net/NeckoChannelParams.h"
+#include "mozilla/EventStateManager.h"
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
 #include "mozilla/StaticPrefs_browser.h"
 #include "mozilla/StaticPrefs_network.h"
 #include "mozilla/StaticPrefs_privacy.h"
 #include "mozilla/Unused.h"
 
 #include "Fetch.h"
 #include "FetchUtil.h"
@@ -549,17 +549,17 @@ nsresult FetchDriver::HttpFetch(
     MOZ_ASSERT(!notificationCallbacks);
   }
 #endif
   chan->SetNotificationCallbacks(this);
 
   nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(chan));
   // Mark channel as urgent-start if the Fetch is triggered by user input
   // events.
-  if (cos && UserActivation::IsHandlingUserInput()) {
+  if (cos && EventStateManager::IsHandlingUserInput()) {
     cos->AddClassFlags(nsIClassOfService::UrgentStart);
   }
 
   // Step 3.5 begins "HTTP network or cache fetch".
   // HTTP network or cache fetch
   // ---------------------------
   // Step 1 "Let HTTPRequest..." The channel is the HTTPRequest.
   nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(chan);
--- a/dom/html/HTMLFormSubmission.h
+++ b/dom/html/HTMLFormSubmission.h
@@ -4,17 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_HTMLFormSubmission_h
 #define mozilla_dom_HTMLFormSubmission_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/Element.h"
-#include "mozilla/dom/UserActivation.h"
+#include "mozilla/EventStateManager.h"
 #include "nsCOMPtr.h"
 #include "mozilla/Encoding.h"
 #include "nsString.h"
 
 class nsIURI;
 class nsIInputStream;
 class nsGenericHTMLElement;
 class nsIMultiplexInputStream;
@@ -119,17 +119,17 @@ class HTMLFormSubmission {
    */
   HTMLFormSubmission(nsIURI* aActionURL, const nsAString& aTarget,
                      mozilla::NotNull<const mozilla::Encoding*> aEncoding,
                      Element* aOriginatingElement)
       : mActionURL(aActionURL),
         mTarget(aTarget),
         mEncoding(aEncoding),
         mOriginatingElement(aOriginatingElement),
-        mInitiatedFromUserInput(UserActivation::IsHandlingUserInput()) {
+        mInitiatedFromUserInput(EventStateManager::IsHandlingUserInput()) {
     MOZ_COUNT_CTOR(HTMLFormSubmission);
   }
 
   // The action url.
   nsCOMPtr<nsIURI> mActionURL;
 
   // The target.
   nsString mTarget;
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -22,17 +22,16 @@
 #include "nsContainerFrame.h"
 #include "nsNodeInfoManager.h"
 #include "mozilla/MouseEvents.h"
 #include "nsContentPolicyUtils.h"
 #include "nsIDOMWindow.h"
 #include "nsFocusManager.h"
 #include "mozilla/dom/HTMLFormElement.h"
 #include "mozilla/dom/MutationEventBinding.h"
-#include "mozilla/dom/UserActivation.h"
 #include "nsAttrValueOrString.h"
 #include "imgLoader.h"
 #include "Image.h"
 
 // Responsive images!
 #include "mozilla/dom/HTMLSourceElement.h"
 #include "mozilla/dom/ResponsiveImageSelector.h"
 
@@ -312,41 +311,41 @@ nsresult HTMLImageElement::AfterSetAttr(
 
   // Handle src/srcset updates. If aNotify is false, we are coming from the
   // parser or some such place; we'll get bound after all the attributes have
   // been set, so we'll do the image load from BindToTree.
 
   if (aName == nsGkAtoms::src && aNameSpaceID == kNameSpaceID_None && !aValue) {
     // Mark channel as urgent-start before load image if the image load is
     // initaiated by a user interaction.
-    mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput();
+    mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
     // SetAttr handles setting src since it needs to catch img.src =
     // img.src, so we only need to handle the unset case
     if (InResponsiveMode()) {
       if (mResponsiveSelector && mResponsiveSelector->Content() == this) {
         mResponsiveSelector->SetDefaultSource(VoidString());
       }
       QueueImageLoadTask(true);
     } else {
       // Bug 1076583 - We still behave synchronously in the non-responsive case
       CancelImageRequests(aNotify);
     }
   } else if (aName == nsGkAtoms::srcset && aNameSpaceID == kNameSpaceID_None) {
     // Mark channel as urgent-start before load image if the image load is
     // initaiated by a user interaction.
-    mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput();
+    mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
     mSrcsetTriggeringPrincipal = aMaybeScriptedPrincipal;
 
     PictureSourceSrcsetChanged(this, attrVal.String(), aNotify);
   } else if (aName == nsGkAtoms::sizes && aNameSpaceID == kNameSpaceID_None) {
     // Mark channel as urgent-start before load image if the image load is
     // initaiated by a user interaction.
-    mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput();
+    mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
     PictureSourceSizesChanged(this, attrVal.String(), aNotify);
   } else if (aName == nsGkAtoms::decoding &&
              aNameSpaceID == kNameSpaceID_None) {
     // Request sync or async image decoding.
     SetSyncDecodingHint(
         aValue && static_cast<ImageDecodingType>(aValue->GetEnumValue()) ==
                       ImageDecodingType::Sync);
@@ -379,17 +378,17 @@ void HTMLImageElement::AfterMaybeChangeA
   // If we are in responsive mode, we drop the forced reload behavior,
   // but still trigger a image load task for img.src = img.src per
   // spec.
   //
   // Both cases handle unsetting src in AfterSetAttr
   if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::src) {
     // Mark channel as urgent-start before load image if the image load is
     // initaiated by a user interaction.
-    mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput();
+    mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
     mSrcTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal(
         this, aValue.String(), aMaybeScriptedPrincipal);
 
     if (InResponsiveMode()) {
       if (mResponsiveSelector && mResponsiveSelector->Content() == this) {
         mResponsiveSelector->SetDefaultSource(aValue.String(),
                                               mSrcTriggeringPrincipal);
@@ -442,17 +441,17 @@ void HTMLImageElement::AfterMaybeChangeA
   }
 
   // Because we load image synchronously in non-responsive-mode, we need to do
   // reload after the attribute has been set if the reload is triggerred by
   // cross origin changing.
   if (forceReload) {
     // Mark channel as urgent-start before load image if the image load is
     // initaiated by a user interaction.
-    mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput();
+    mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
     if (InResponsiveMode()) {
       // per spec, full selection runs when this changes, even though
       // it doesn't directly affect the source selection
       QueueImageLoadTask(true);
     } else if (OwnerDoc()->ShouldLoadImages()) {
       // Bug 1076583 - We still use the older synchronous algorithm in
       // non-responsive mode. Force a new load of the image with the
@@ -514,33 +513,33 @@ nsresult HTMLImageElement::BindToTree(Bi
   if (HaveSrcsetOrInPicture()) {
     if (IsInComposedDoc() && !mInDocResponsiveContent) {
       aContext.OwnerDoc().AddResponsiveContent(this);
       mInDocResponsiveContent = true;
     }
 
     // Mark channel as urgent-start before load image if the image load is
     // initaiated by a user interaction.
-    mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput();
+    mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
     // Run selection algorithm when an img element is inserted into a document
     // in order to react to changes in the environment. See note of
     // https://html.spec.whatwg.org/multipage/embedded-content.html#img-environment-changes
     QueueImageLoadTask(false);
   } else if (!InResponsiveMode() &&
              HasAttr(kNameSpaceID_None, nsGkAtoms::src)) {
     // We skip loading when our attributes were set from parser land,
     // so trigger a aForce=false load now to check if things changed.
     // This isn't necessary for responsive mode, since creating the
     // image load task is asynchronous we don't need to take special
     // care to avoid doing so when being filled by the parser.
 
     // Mark channel as urgent-start before load image if the image load is
     // initaiated by a user interaction.
-    mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput();
+    mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
     // We still act synchronously for the non-responsive case (Bug
     // 1076583), but still need to delay if it is unsafe to run
     // script.
 
     // If loading is temporarily disabled, don't even launch MaybeLoadImage.
     // Otherwise MaybeLoadImage may run later when someone has reenabled
     // loading.
@@ -718,17 +717,17 @@ nsresult HTMLImageElement::CopyInnerTo(H
     // doing the image load because we passed in false for aNotify.  But we
     // really do want it to do the load, so set it up to happen once the cloning
     // reaches a stable state.
     if (!aDest->InResponsiveMode() &&
         aDest->HasAttr(kNameSpaceID_None, nsGkAtoms::src) &&
         aDest->OwnerDoc()->ShouldLoadImages()) {
       // Mark channel as urgent-start before load image if the image load is
       // initaiated by a user interaction.
-      mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput();
+      mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
       nsContentUtils::AddScriptRunner(NewRunnableMethod<bool>(
           "dom::HTMLImageElement::MaybeLoadImage", aDest,
           &HTMLImageElement::MaybeLoadImage, false));
     }
   }
 
   return NS_OK;
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -10,17 +10,16 @@
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/dom/Date.h"
 #include "mozilla/dom/Directory.h"
 #include "mozilla/dom/DocumentOrShadowRoot.h"
 #include "mozilla/dom/HTMLFormSubmission.h"
 #include "mozilla/dom/FileSystemUtils.h"
 #include "mozilla/dom/GetFilesHelper.h"
-#include "mozilla/dom/UserActivation.h"
 #include "mozilla/dom/WheelEventBinding.h"
 #include "mozilla/PresShell.h"
 #include "mozilla/StaticPrefs_dom.h"
 #include "mozilla/TextUtils.h"
 #include "nsAttrValueInlines.h"
 #include "nsCRTGlue.h"
 #include "nsQueryObject.h"
 
@@ -1194,17 +1193,17 @@ nsresult HTMLInputElement::AfterSetAttr(
     if (aName == nsGkAtoms::src) {
       mSrcTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal(
           this, aValue ? aValue->GetStringValue() : EmptyString(),
           aSubjectPrincipal);
       if (aNotify && mType == NS_FORM_INPUT_IMAGE) {
         if (aValue) {
           // Mark channel as urgent-start before load image if the image load is
           // initiated by a user interaction.
-          mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput();
+          mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
           LoadImage(aValue->GetStringValue(), true, aNotify,
                     eImageLoadType_Normal, mSrcTriggeringPrincipal);
         } else {
           // Null value means the attr got unset; drop the image
           CancelImageRequests(aNotify);
         }
       }
@@ -4320,17 +4319,17 @@ nsresult HTMLInputElement::BindToTree(Bi
   nsImageLoadingContent::BindToTree(aContext, aParent);
 
   if (mType == NS_FORM_INPUT_IMAGE) {
     // Our base URI may have changed; claim that our URI changed, and the
     // nsImageLoadingContent will decide whether a new image load is warranted.
     if (HasAttr(kNameSpaceID_None, nsGkAtoms::src)) {
       // Mark channel as urgent-start before load image if the image load is
       // initaiated by a user interaction.
-      mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput();
+      mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
       nsContentUtils::AddScriptRunner(
           NewRunnableMethod("dom::HTMLInputElement::MaybeLoadImage", this,
                             &HTMLInputElement::MaybeLoadImage));
     }
   }
 
   // Add radio to document if we don't have a form already (if we do it's
@@ -4592,17 +4591,17 @@ void HTMLInputElement::HandleTypeChange(
   } else if (mType == NS_FORM_INPUT_IMAGE) {
     if (aNotify) {
       // We just got switched to be an image input; we should see
       // whether we have an image to load;
       nsAutoString src;
       if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
         // Mark channel as urgent-start before load image if the image load is
         // initaiated by a user interaction.
-        mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput();
+        mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
         LoadImage(src, false, aNotify, eImageLoadType_Normal,
                   mSrcTriggeringPrincipal);
       }
     }
 
     // And we should update our mapped attribute mapping function.
     mAttrs.UpdateMappedAttrRuleMapper(*this);
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -45,16 +45,17 @@
 #include "VideoOutput.h"
 #include "VideoStreamTrack.h"
 #include "base/basictypes.h"
 #include "jsapi.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/EMEUtils.h"
 #include "mozilla/EventDispatcher.h"
+#include "mozilla/EventStateManager.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/NotNull.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/PresShell.h"
 #include "mozilla/Sprintf.h"
 #include "mozilla/StaticPrefs_media.h"
 #include "mozilla/Telemetry.h"
@@ -68,17 +69,16 @@
 #include "mozilla/dom/HTMLSourceElement.h"
 #include "mozilla/dom/HTMLVideoElement.h"
 #include "mozilla/dom/MediaEncryptedEvent.h"
 #include "mozilla/dom/MediaErrorBinding.h"
 #include "mozilla/dom/MediaSource.h"
 #include "mozilla/dom/PlayPromise.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/TextTrack.h"
-#include "mozilla/dom/UserActivation.h"
 #include "mozilla/dom/VideoPlaybackQuality.h"
 #include "mozilla/dom/VideoTrack.h"
 #include "mozilla/dom/VideoTrackList.h"
 #include "mozilla/dom/WakeLock.h"
 #include "mozilla/dom/power/PowerManagerService.h"
 #include "mozilla/net/UrlClassifierFeatureFactory.h"
 #include "nsAttrValueInlines.h"
 #include "nsContentPolicyUtils.h"
@@ -2169,17 +2169,17 @@ static nsCString DocumentOrigin(Document
 
 void HTMLMediaElement::Load() {
   LOG(LogLevel::Debug,
       ("%p Load() hasSrcAttrStream=%d hasSrcAttr=%d hasSourceChildren=%d "
        "handlingInput=%d hasAutoplayAttr=%d IsAllowedToPlay=%d "
        "ownerDoc=%p (%s) ownerDocUserActivated=%d "
        "muted=%d volume=%f",
        this, !!mSrcAttrStream, HasAttr(kNameSpaceID_None, nsGkAtoms::src),
-       HasSourceChildren(this), UserActivation::IsHandlingUserInput(),
+       HasSourceChildren(this), EventStateManager::IsHandlingUserInput(),
        HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay),
        AutoplayPolicy::IsAllowedToPlay(*this), OwnerDoc(),
        DocumentOrigin(OwnerDoc()).get(),
        OwnerDoc() ? OwnerDoc()->HasBeenUserGestureActivated() : 0, mMuted,
        mVolume));
 
   if (mIsRunningLoadMethod) {
     return;
@@ -2196,17 +2196,17 @@ void HTMLMediaElement::DoLoad() {
     LOG(LogLevel::Debug, ("%p Media not allowed", this));
     return;
   }
 
   if (mIsRunningLoadMethod) {
     return;
   }
 
-  if (UserActivation::IsHandlingUserInput()) {
+  if (EventStateManager::IsHandlingUserInput()) {
     // Detect if user has interacted with element so that play will not be
     // blocked when initiated by a script. This enables sites to capture user
     // intent to play by calling load() in the click handler of a "catalog
     // view" of a gallery of videos.
     mIsBlessed = true;
     // Mark the channel as urgent-start when autopaly so that it will play the
     // media from src after loading enough resource.
     if (HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay)) {
@@ -2906,17 +2906,17 @@ void HTMLMediaElement::Seek(double aTime
   MOZ_ASSERT(!mozilla::IsNaN(aTime));
 
   // Seeking step1, Set the media element's show poster flag to false.
   // https://html.spec.whatwg.org/multipage/media.html#dom-media-seek
   mShowPoster = false;
 
   // Detect if user has interacted with element by seeking so that
   // play will not be blocked when initiated by a script.
-  if (UserActivation::IsHandlingUserInput()) {
+  if (EventStateManager::IsHandlingUserInput()) {
     mIsBlessed = true;
   }
 
   StopSuspendingAfterFirstFrame();
 
   if (mSrcAttrStream) {
     // do nothing since media streams have an empty Seekable range.
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
@@ -3875,17 +3875,17 @@ already_AddRefed<Promise> HTMLMediaEleme
   if (AudioChannelAgentBlockedPlay()) {
     LOG(LogLevel::Debug, ("%p play blocked by AudioChannelAgent.", this));
     promise->MaybeReject(NS_ERROR_DOM_MEDIA_NOT_ALLOWED_ERR);
     return promise.forget();
   }
 
   UpdateHadAudibleAutoplayState();
 
-  const bool handlingUserInput = UserActivation::IsHandlingUserInput();
+  const bool handlingUserInput = EventStateManager::IsHandlingUserInput();
   mPendingPlayPromises.AppendElement(promise);
 
   if (AutoplayPolicy::IsAllowedToPlay(*this)) {
     AUTOPLAY_LOG("allow MediaElement %p to play", this);
     mAllowedToPlayPromise.ResolveIfExists(true, __func__);
     PlayInternal(handlingUserInput);
     UpdateCustomPolicyAfterPlayed();
   } else {
--- a/dom/ipc/BrowserParent.cpp
+++ b/dom/ipc/BrowserParent.cpp
@@ -22,17 +22,16 @@
 #include "mozilla/dom/indexedDB/ActorsParent.h"
 #include "mozilla/dom/PaymentRequestParent.h"
 #include "mozilla/dom/BrowserBridgeParent.h"
 #include "mozilla/dom/RemoteDragStartData.h"
 #include "mozilla/dom/RemoteWebProgress.h"
 #include "mozilla/dom/RemoteWebProgressRequest.h"
 #include "mozilla/dom/SessionStoreUtils.h"
 #include "mozilla/dom/SessionStoreUtilsBinding.h"
-#include "mozilla/dom/UserActivation.h"
 #include "mozilla/EventStateManager.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/DataSurfaceHelpers.h"
 #include "mozilla/gfx/GPUProcessManager.h"
 #include "mozilla/Hal.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/layers/AsyncDragMetrics.h"
deleted file mode 100644
--- a/dom/ipc/UserActivationIPCUtils.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_useractivation_ipc_utils_h__
-#define mozilla_dom_useractivation_ipc_utils_h__
-
-#include "ipc/IPCMessageUtils.h"
-
-// Undo X11/X.h's definition of None
-#undef None
-
-#include "mozilla/dom/UserActivation.h"
-
-namespace IPC {
-
-template <>
-struct ParamTraits<mozilla::dom::UserActivation::State>
-    : public ContiguousEnumSerializer<
-          mozilla::dom::UserActivation::State,
-          mozilla::dom::UserActivation::State::None,
-          mozilla::dom::UserActivation::State::EndGuard_> {};
-
-}  // namespace IPC
-
-#endif  // mozilla_dom_useractivation_ipc_utils_h__
--- a/dom/ipc/moz.build
+++ b/dom/ipc/moz.build
@@ -61,17 +61,16 @@ EXPORTS.mozilla.dom += [
     'ReferrerInfoUtils.h',
     'RemoteBrowser.h',
     'RemoteWebProgress.h',
     'RemoteWebProgressRequest.h',
     'TabContext.h',
     'TabMessageUtils.h',
     'URLClassifierChild.h',
     'URLClassifierParent.h',
-    'UserActivationIPCUtils.h',
     'WindowGlobalActor.h',
     'WindowGlobalChild.h',
     'WindowGlobalParent.h',
 ]
 
 EXPORTS.mozilla += [
     'PreallocatedProcessManager.h',
     'ProcessHangMonitor.h',
--- a/dom/media/AutoplayPolicy.cpp
+++ b/dom/media/AutoplayPolicy.cpp
@@ -1,23 +1,23 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "AutoplayPolicy.h"
 
+#include "mozilla/EventStateManager.h"
 #include "mozilla/Logging.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/AudioContext.h"
 #include "mozilla/dom/FeaturePolicyUtils.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/dom/HTMLMediaElementBinding.h"
-#include "mozilla/dom/UserActivation.h"
 #include "nsGlobalWindowInner.h"
 #include "nsIAutoplay.h"
 #include "nsContentUtils.h"
 #include "mozilla/dom/Document.h"
 #include "MediaManager.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsPIDOMWindow.h"
@@ -170,17 +170,17 @@ bool AutoplayPolicy::WouldBeAllowedToPla
 bool AutoplayPolicy::WouldBeAllowedToPlayIfAutoplayDisabled(
     const AudioContext& aContext) {
   return IsAudioContextAllowedToPlay(aContext);
 }
 
 static bool IsAllowedToPlayByBlockingModel(const HTMLMediaElement& aElement) {
   if (!StaticPrefs::media_autoplay_enabled_user_gestures_needed()) {
     // If element is blessed, it would always be allowed to play().
-    return aElement.IsBlessed() || UserActivation::IsHandlingUserInput();
+    return aElement.IsBlessed() || EventStateManager::IsHandlingUserInput();
   }
   return IsWindowAllowedToPlay(aElement.OwnerDoc()->GetInnerWindow());
 }
 
 static bool IsAllowedToPlayInternal(const HTMLMediaElement& aElement) {
   Document* approver = ApproverDocOf(*aElement.OwnerDoc());
 
   bool isInaudible = IsMediaElementInaudible(aElement);
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -31,31 +31,31 @@
 #include "nsICryptoHash.h"
 #include "nsICryptoHMAC.h"
 #include "nsIKeyModule.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsIInputStream.h"
 #include "nsILineInputStream.h"
 #include "nsIWeakReferenceUtils.h"
 #include "nsPIDOMWindow.h"
+#include "mozilla/EventStateManager.h"
 #include "mozilla/MozPromise.h"
 #include "mozilla/NullPrincipal.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Types.h"
 #include "mozilla/PeerIdentity.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/FeaturePolicyUtils.h"
 #include "mozilla/dom/File.h"
-#include "mozilla/dom/MediaDevices.h"
 #include "mozilla/dom/MediaStreamBinding.h"
 #include "mozilla/dom/MediaStreamTrackBinding.h"
 #include "mozilla/dom/GetUserMediaRequestBinding.h"
 #include "mozilla/dom/Promise.h"
-#include "mozilla/dom/UserActivation.h"
+#include "mozilla/dom/MediaDevices.h"
 #include "mozilla/Base64.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/media/MediaChild.h"
 #include "mozilla/media/MediaTaskUtils.h"
 #include "MediaTrackConstraints.h"
 #include "VideoStreamTrack.h"
 #include "VideoUtils.h"
 #include "ThreadSafeRefcountingWithMainThreadDestruction.h"
@@ -191,17 +191,16 @@ using dom::MediaTrackConstraints;
 using dom::MediaTrackConstraintSet;
 using dom::MediaTrackSettings;
 using dom::MozGetUserMediaDevicesSuccessCallback;
 using dom::OwningBooleanOrMediaTrackConstraints;
 using dom::OwningStringOrStringSequence;
 using dom::OwningStringOrStringSequenceOrConstrainDOMStringParameters;
 using dom::Promise;
 using dom::Sequence;
-using dom::UserActivation;
 using media::NewRunnableFrom;
 using media::NewTaskFrom;
 using media::Refcountable;
 
 static Atomic<bool> sHasShutdown;
 
 struct DeviceState {
   DeviceState(RefPtr<MediaDevice> aDevice,
@@ -521,17 +520,17 @@ class GetUserMediaWindowListener {
         mgr->GetWindowListener(mWindowID);
 
     if (!windowListener) {
       nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
       auto* globalWindow = nsGlobalWindowInner::GetInnerWindowWithId(mWindowID);
       if (globalWindow) {
         auto req = MakeRefPtr<GetUserMediaRequest>(
             globalWindow, VoidString(), VoidString(),
-            UserActivation::IsHandlingUserInput());
+            EventStateManager::IsHandlingUserInput());
         obs->NotifyObservers(req, "recording-device-stopped", nullptr);
       }
       return;
     }
 
     MOZ_ASSERT(windowListener == this,
                "There should only be one window listener per window ID");
 
@@ -583,17 +582,17 @@ class GetUserMediaWindowListener {
         }
       }
 
       if (revokeVideoPermission) {
         nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
         auto* window = nsGlobalWindowInner::GetInnerWindowWithId(mWindowID);
         auto req = MakeRefPtr<GetUserMediaRequest>(
             window, removedRawId, removedSourceType,
-            UserActivation::IsHandlingUserInput());
+            EventStateManager::IsHandlingUserInput());
         obs->NotifyObservers(req, "recording-device-stopped", nullptr);
       }
     }
 
     if (MediaDevice* removedDevice = aListener->GetAudioDevice()) {
       bool revokeAudioPermission = true;
       nsString removedRawId;
       nsString removedSourceType;
@@ -610,17 +609,17 @@ class GetUserMediaWindowListener {
         }
       }
 
       if (revokeAudioPermission) {
         nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
         auto* window = nsGlobalWindowInner::GetInnerWindowWithId(mWindowID);
         auto req = MakeRefPtr<GetUserMediaRequest>(
             window, removedRawId, removedSourceType,
-            UserActivation::IsHandlingUserInput());
+            EventStateManager::IsHandlingUserInput());
         obs->NotifyObservers(req, "recording-device-stopped", nullptr);
       }
     }
     if (mInactiveListeners.Length() == 0 && mActiveListeners.Length() == 0) {
       LOG("GUMWindowListener %p Removed last SourceListener. Cleaning up.",
           this);
       RemoveAll();
     }
@@ -2377,17 +2376,17 @@ RefPtr<MediaManager::StreamPromise> Medi
     return StreamPromise::CreateAndReject(
         MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError), __func__);
   }
   bool isChrome = (aCallerType == CallerType::System);
   bool privileged =
       isChrome ||
       Preferences::GetBool("media.navigator.permission.disabled", false);
   bool isSecure = aWindow->IsSecureContext();
-  bool isHandlingUserInput = UserActivation::IsHandlingUserInput();
+  bool isHandlingUserInput = EventStateManager::IsHandlingUserInput();
   nsCString host;
   nsresult rv = docURI->GetHost(host);
 
   nsCOMPtr<nsIPrincipal> principal =
       nsGlobalWindowInner::Cast(aWindow)->GetPrincipal();
   if (NS_WARN_IF(!principal)) {
     return StreamPromise::CreateAndReject(
         MakeRefPtr<MediaMgrError>(MediaMgrError::Name::SecurityError),
--- a/dom/payments/PaymentRequest.cpp
+++ b/dom/payments/PaymentRequest.cpp
@@ -6,19 +6,19 @@
 
 #include "BasicCardPayment.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/FeaturePolicyUtils.h"
 #include "mozilla/dom/PaymentRequest.h"
 #include "mozilla/dom/PaymentRequestChild.h"
 #include "mozilla/dom/PaymentRequestManager.h"
 #include "mozilla/dom/RootedDictionary.h"
-#include "mozilla/dom/UserActivation.h"
 #include "mozilla/intl/LocaleService.h"
 #include "mozilla/intl/MozLocale.h"
+#include "mozilla/EventStateManager.h"
 #include "mozilla/StaticPrefs_dom.h"
 #include "nsContentUtils.h"
 #include "nsIScriptError.h"
 #include "nsIURLParser.h"
 #include "nsNetCID.h"
 #include "mozilla/dom/MerchantValidationEvent.h"
 #include "PaymentResponse.h"
 
@@ -696,17 +696,17 @@ already_AddRefed<Promise> PaymentRequest
     aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
     return nullptr;
   }
 
   nsIGlobalObject* global = GetOwnerGlobal();
   nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(global);
   Document* doc = win->GetExtantDoc();
 
-  if (!UserActivation::IsHandlingUserInput()) {
+  if (!EventStateManager::IsHandlingUserInput()) {
     nsString msg = NS_LITERAL_STRING(
         "User activation is now required to call PaymentRequest.show()");
     nsContentUtils::ReportToConsoleNonLocalized(
         msg, nsIScriptError::warningFlag, NS_LITERAL_CSTRING("Security"), doc);
     if (StaticPrefs::dom_payments_request_user_interaction_required()) {
       aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
       return nullptr;
     }
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -6,28 +6,28 @@
 
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/Promise-inl.h"
 
 #include "js/Debug.h"
 
 #include "mozilla/Atomics.h"
 #include "mozilla/CycleCollectedJSContext.h"
+#include "mozilla/EventStateManager.h"
 #include "mozilla/OwningNonNull.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ResultExtensions.h"
 #include "mozilla/Unused.h"
 
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/DOMExceptionBinding.h"
 #include "mozilla/dom/MediaStreamError.h"
 #include "mozilla/dom/PromiseBinding.h"
 #include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/dom/UserActivation.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/WorkerRunnable.h"
 #include "mozilla/dom/WorkerRef.h"
 
 #include "jsfriendapi.h"
 #include "js/StructuredClone.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
@@ -98,17 +98,17 @@ already_AddRefed<Promise> Promise::Creat
   if (aRv.Failed()) {
     return nullptr;
   }
   return p.forget();
 }
 
 bool Promise::MaybePropagateUserInputEventHandling() {
   JS::PromiseUserInputEventHandlingState state =
-      UserActivation::IsHandlingUserInput()
+      EventStateManager::IsHandlingUserInput()
           ? JS::PromiseUserInputEventHandlingState::HadUserInteractionAtCreation
           : JS::PromiseUserInputEventHandlingState::
                 DidntHaveUserInteractionAtCreation;
   JS::Rooted<JSObject*> p(RootingCx(), mPromiseObj);
   return JS::SetPromiseUserInputEventHandlingState(p, state);
 }
 
 // static
--- a/dom/svg/SVGFEImageElement.cpp
+++ b/dom/svg/SVGFEImageElement.cpp
@@ -1,20 +1,20 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/SVGFEImageElement.h"
 
+#include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/dom/SVGFEImageElementBinding.h"
 #include "mozilla/dom/SVGFilterElement.h"
-#include "mozilla/dom/UserActivation.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/RefPtr.h"
 #include "nsContentUtils.h"
 #include "nsLayoutUtils.h"
 #include "nsSVGUtils.h"
 #include "nsNetUtil.h"
 #include "SVGObserverUtils.h"
 #include "imgIContainer.h"
@@ -79,17 +79,17 @@ nsresult SVGFEImageElement::LoadSVGImage
     if (NS_SUCCEEDED(hrefAsURI->Equals(baseURI, &isEqual)) && isEqual) {
       // Image URI matches our URI exactly! Bail out.
       return NS_OK;
     }
   }
 
   // Mark channel as urgent-start before load image if the image load is
   // initaiated by a user interaction.
-  mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput();
+  mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
   return LoadImage(href, aForce, aNotify, eImageLoadType_Normal);
 }
 
 //----------------------------------------------------------------------
 // EventTarget methods:
 
 void SVGFEImageElement::AsyncEventRunning(AsyncEventDispatcher* aEvent) {
   nsImageLoadingContent::AsyncEventRunning(aEvent);
--- a/dom/svg/SVGImageElement.cpp
+++ b/dom/svg/SVGImageElement.cpp
@@ -2,25 +2,25 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/SVGImageElement.h"
 
 #include "mozilla/ArrayUtils.h"
+#include "mozilla/EventStateManager.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/gfx/2D.h"
 #include "nsCOMPtr.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "imgINotificationObserver.h"
 #include "mozilla/dom/SVGImageElementBinding.h"
 #include "mozilla/dom/SVGLengthBinding.h"
-#include "mozilla/dom/UserActivation.h"
 #include "nsContentUtils.h"
 #include "SVGGeometryProperty.h"
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(Image)
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
@@ -137,17 +137,17 @@ nsresult SVGImageElement::LoadSVGImage(b
     mStringAttributes[XLINK_HREF].GetAnimValue(href, this);
   }
   href.Trim(" \t\n\r");
 
   if (baseURI && !href.IsEmpty()) NS_MakeAbsoluteURI(href, href, baseURI);
 
   // Mark channel as urgent-start before load image if the image load is
   // initaiated by a user interaction.
-  mUseUrgentStartForChannel = UserActivation::IsHandlingUserInput();
+  mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
   return LoadImage(href, aForce, aNotify, eImageLoadType_Normal);
 }
 
 //----------------------------------------------------------------------
 // EventTarget methods:
 
 void SVGImageElement::AsyncEventRunning(AsyncEventDispatcher* aEvent) {
--- a/dom/vr/VRDisplay.cpp
+++ b/dom/vr/VRDisplay.cpp
@@ -4,21 +4,21 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsWrapperCache.h"
 
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ElementBinding.h"
 #include "mozilla/dom/Promise.h"
-#include "mozilla/dom/UserActivation.h"
 #include "mozilla/dom/VRDisplay.h"
+#include "mozilla/HoldDropJSObjects.h"
 #include "mozilla/dom/VRDisplayBinding.h"
-#include "mozilla/HoldDropJSObjects.h"
 #include "mozilla/Base64.h"
+#include "mozilla/EventStateManager.h"
 #include "mozilla/StaticPrefs_dom.h"
 #include "mozilla/gfx/DataSurfaceHelpers.h"
 #include "Navigator.h"
 #include "gfxUtils.h"
 #include "gfxVR.h"
 #include "VRDisplayClient.h"
 #include "VRManagerChild.h"
 #include "VRDisplayPresentation.h"
@@ -456,17 +456,17 @@ already_AddRefed<Promise> VRDisplay::Req
 
   RefPtr<Promise> promise = Promise::Create(global, aRv);
   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
 
   bool isChromePresentation = aCallerType == CallerType::System;
   uint32_t presentationGroup =
       isChromePresentation ? gfx::kVRGroupChrome : gfx::kVRGroupContent;
 
-  if (!UserActivation::IsHandlingUserInput() && !isChromePresentation &&
+  if (!EventStateManager::IsHandlingUserInput() && !isChromePresentation &&
       !IsHandlingVRNavigationEvent() && StaticPrefs::dom_vr_require_gesture() &&
       !IsPresenting()) {
     // The WebVR API states that if called outside of a user gesture, the
     // promise must be rejected.  We allow VR presentations to start within
     // trusted events such as vrdisplayactivate, which triggers in response to
     // HMD proximity sensors and when navigating within a VR presentation.
     // This user gesture requirement is not enforced for chrome/system code.
     promise->MaybeRejectWithUndefined();
--- a/dom/webidl/Document.webidl
+++ b/dom/webidl/Document.webidl
@@ -569,18 +569,16 @@ partial interface Document {
   void notifyUserGestureActivation();
   // For testing only.
   [ChromeOnly]
   void clearUserGestureActivation();
   [ChromeOnly]
   readonly attribute boolean hasBeenUserGestureActivated;
   [ChromeOnly]
   readonly attribute boolean hasValidTransientUserGestureActivation;
-  [ChromeOnly]
-  boolean consumeTransientUserGestureActivation();
 };
 
 // Extension to give chrome JS the ability to set an event handler which is
 // called with certain events that happened while events were suppressed in the
 // document or one of its subdocuments.
 partial interface Document {
   [ChromeOnly]
   void setSuppressedEventListener(EventListener? aListener);
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -19,23 +19,23 @@
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/FileBinding.h"
 #include "mozilla/dom/FileCreatorHelper.h"
 #include "mozilla/dom/FetchUtil.h"
 #include "mozilla/dom/FormData.h"
 #include "mozilla/dom/MutableBlobStorage.h"
 #include "mozilla/dom/XMLDocument.h"
 #include "mozilla/dom/URLSearchParams.h"
-#include "mozilla/dom/UserActivation.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PromiseNativeHandler.h"
 #include "mozilla/dom/WorkerError.h"
 #include "mozilla/Encoding.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
+#include "mozilla/EventStateManager.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/LoadContext.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/StaticPrefs_dom.h"
 #include "mozilla/StaticPrefs_network.h"
 #include "mozilla/StaticPrefs_privacy.h"
 #include "mozilla/dom/ProgressEvent.h"
 #include "nsIJARChannel.h"
@@ -2554,17 +2554,17 @@ nsresult XMLHttpRequestMainThread::Initi
   // We never let XHR be blocked by head CSS/JS loads to avoid potential
   // deadlock where server generation of CSS/JS requires an XHR signal.
   nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(mChannel));
   if (cos) {
     cos->AddClassFlags(nsIClassOfService::Unblocked);
 
     // Mark channel as urgent-start if the XHR is triggered by user input
     // events.
-    if (UserActivation::IsHandlingUserInput()) {
+    if (EventStateManager::IsHandlingUserInput()) {
       cos->AddClassFlags(nsIClassOfService::UrgentStart);
     }
   }
 
   // Disable Necko-internal response timeouts.
   nsCOMPtr<nsIHttpChannelInternal> internalHttpChannel(
       do_QueryInterface(mChannel));
   if (internalHttpChannel) {
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -49,17 +49,16 @@
 #include "nsIContent.h"
 #include "mozilla/dom/BrowserBridgeChild.h"
 #include "mozilla/dom/BrowsingContext.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/PointerEventHandler.h"
 #include "mozilla/dom/PopupBlocker.h"
 #include "mozilla/dom/Document.h"
 #include "mozilla/dom/DocumentInlines.h"
-#include "mozilla/dom/UserActivation.h"
 #include "nsAnimationManager.h"
 #include "nsNameSpaceManager.h"  // for Pref-related rule management (bugs 22963,20760,31816)
 #include "nsFrame.h"
 #include "FrameLayerBuilder.h"
 #include "nsViewManager.h"
 #include "nsView.h"
 #include "nsCRTGlue.h"
 #include "prinrval.h"
@@ -7753,17 +7752,17 @@ nsresult PresShell::EventHandler::Handle
     return NS_OK;
   }
 
   // We finished preparing to dispatch the event.  So, let's record the
   // performance.
   RecordEventPreparationPerformance(aEvent);
 
   AutoHandlingUserInputStatePusher userInpStatePusher(
-      UserActivation::IsUserInteractionEvent(aEvent), aEvent);
+      EventStateManager::IsUserInteractionEvent(aEvent), aEvent);
   AutoEventHandler eventHandler(aEvent, GetDocument());
   AutoPopupStatePusher popupStatePusher(
       PopupBlocker::GetEventPopupControlState(aEvent));
 
   // FIXME. If the event was reused, we need to clear the old target,
   // bug 329430
   aEvent->mTarget = nullptr;
 
--- a/layout/xul/nsMenuFrame.cpp
+++ b/layout/xul/nsMenuFrame.cpp
@@ -29,26 +29,26 @@
 #include "nsIStringBundle.h"
 #include "nsContentUtils.h"
 #include "nsDisplayList.h"
 #include "nsIReflowCallback.h"
 #include "nsISound.h"
 #include "nsIDOMXULMenuListElement.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/EventDispatcher.h"
+#include "mozilla/EventStateManager.h"
 #include "mozilla/Likely.h"
 #include "mozilla/LookAndFeel.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/PresShell.h"
 #include "mozilla/Services.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"
-#include "mozilla/dom/UserActivation.h"
 #include <algorithm>
 
 using namespace mozilla;
 
 #define NS_MENU_POPUP_LIST_INDEX 0
 
 #if defined(XP_WIN)
 #  define NSCONTEXTMENUISMOUSEUP 1
@@ -1110,17 +1110,17 @@ void nsMenuFrame::CreateMenuCommandEvent
     control = inputEvent->IsControl();
     alt = inputEvent->IsAlt();
     meta = inputEvent->IsMeta();
   }
 
   // Because the command event is firing asynchronously, a flag is needed to
   // indicate whether user input is being handled. This ensures that a popup
   // window won't get blocked.
-  bool userinput = UserActivation::IsHandlingUserInput();
+  bool userinput = EventStateManager::IsHandlingUserInput();
 
   mDelayedMenuCommandEvent =
       new nsXULMenuCommandEvent(mContent->AsElement(), isTrusted, shift,
                                 control, alt, meta, userinput, aFlipChecked);
 }
 
 void nsMenuFrame::PassMenuCommandEventToPopupManager() {
   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
--- a/layout/xul/nsXULPopupManager.cpp
+++ b/layout/xul/nsXULPopupManager.cpp
@@ -36,18 +36,18 @@
 #include "mozilla/dom/DocumentInlines.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"  // for Event
 #include "mozilla/dom/HTMLSlotElement.h"
 #include "mozilla/dom/KeyboardEvent.h"
 #include "mozilla/dom/KeyboardEventBinding.h"
 #include "mozilla/dom/MouseEvent.h"
 #include "mozilla/dom/UIEvent.h"
-#include "mozilla/dom/UserActivation.h"
 #include "mozilla/EventDispatcher.h"
+#include "mozilla/EventStateManager.h"
 #include "mozilla/LookAndFeel.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/PresShell.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPrefs_xul.h"
 #include "mozilla/widget/nsAutoRollup.h"
 
 using namespace mozilla;
--- a/xpcom/base/CycleCollectedJSContext.cpp
+++ b/xpcom/base/CycleCollectedJSContext.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/CycleCollectedJSContext.h"
 #include <algorithm>
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/CycleCollectedJSRuntime.h"
+#include "mozilla/EventStateManager.h"
 #include "mozilla/Move.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Sprintf.h"
 #include "mozilla/StaticPrefs_dom.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/TimelineConsumers.h"
 #include "mozilla/TimelineMarker.h"
 #include "mozilla/Unused.h"
@@ -22,17 +23,16 @@
 #include "mozilla/dom/DOMJSClass.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/ProfileTimelineMarkerBinding.h"
 #include "mozilla/dom/PromiseBinding.h"
 #include "mozilla/dom/PromiseDebugging.h"
 #include "mozilla/dom/PromiseRejectionEvent.h"
 #include "mozilla/dom/PromiseRejectionEventBinding.h"
 #include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/dom/UserActivation.h"
 #include "jsapi.h"
 #include "js/Debug.h"
 #include "js/GCAPI.h"
 #include "js/Utility.h"
 #include "nsContentUtils.h"
 #include "nsCycleCollectionNoteRootCallback.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsCycleCollector.h"