Bug 1449631 part 10. Devirtualize AddEventListener. r=smaug
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 05 Apr 2018 13:42:42 -0400
changeset 468098 a73566a5d08ec5568f1f65cdf322d0fe93f99e81
parent 468097 51fd57c6877773116ab44264dcb34938f1bdd6ab
child 468099 6cf7b2b773dbefb08a1ca8f0a63ad5d8194b2f94
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1449631
milestone61.0a1
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
Bug 1449631 part 10. Devirtualize AddEventListener. r=smaug The CanCallerAccess check in the "webidl" version of nsGlobalWindowOuter::AddEventListener was pointless, because bindings never call things on outer windows. MozReview-Commit-ID: 1CGMJ277bPu
dom/base/nsGlobalWindowInner.cpp
dom/base/nsGlobalWindowInner.h
dom/base/nsGlobalWindowOuter.cpp
dom/base/nsGlobalWindowOuter.h
dom/base/nsINode.cpp
dom/base/nsINode.h
dom/base/nsWindowRoot.cpp
dom/base/nsWindowRoot.h
dom/events/DOMEventTargetHelper.cpp
dom/events/DOMEventTargetHelper.h
dom/events/EventTarget.cpp
dom/events/EventTarget.h
dom/media/MediaDevices.cpp
dom/media/MediaDevices.h
dom/workers/WorkerScope.cpp
dom/workers/WorkerScope.h
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -4493,57 +4493,21 @@ nsGlobalWindowInner::DispatchEvent(Event
   bool retval = !aEvent.DefaultPrevented(aCallerType);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
   }
   return retval;
 }
 
 bool
-nsGlobalWindowInner::ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted)
-{
-  if (!aWantsUntrusted.IsNull()) {
-    return aWantsUntrusted.Value();
-  }
-
+nsGlobalWindowInner::ComputeDefaultWantsUntrusted(ErrorResult& aRv)
+{
   return !nsContentUtils::IsChromeDoc(mDoc);
 }
 
-nsresult
-nsGlobalWindowInner::AddEventListener(const nsAString& aType,
-                                      nsIDOMEventListener *aListener,
-                                      bool aUseCapture,
-                                      const Nullable<bool>& aWantsUntrusted)
-{
-  bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted);
-
-  EventListenerManager* manager = GetOrCreateListenerManager();
-  NS_ENSURE_STATE(manager);
-  manager->AddEventListener(aType, aListener, aUseCapture, wantsUntrusted);
-  return NS_OK;
-}
-
-void
-nsGlobalWindowInner::AddEventListener(const nsAString& aType,
-                                      EventListener* aListener,
-                                      const AddEventListenerOptionsOrBoolean& aOptions,
-                                      const Nullable<bool>& aWantsUntrusted,
-                                      ErrorResult& aRv)
-{
-  bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted);
-
-  EventListenerManager* manager = GetOrCreateListenerManager();
-  if (!manager) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return;
-  }
-
-  manager->AddEventListener(aType, aListener, aOptions, wantsUntrusted);
-}
-
 NS_IMETHODIMP
 nsGlobalWindowInner::AddSystemEventListener(const nsAString& aType,
                                             nsIDOMEventListener *aListener,
                                             bool aUseCapture,
                                             bool aWantsUntrusted,
                                             uint8_t aOptionalArgc)
 {
   NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
--- a/dom/base/nsGlobalWindowInner.h
+++ b/dom/base/nsGlobalWindowInner.h
@@ -319,30 +319,18 @@ public:
   NS_DECL_NSIDOMEVENTTARGET
 
   virtual mozilla::EventListenerManager*
     GetExistingListenerManager() const override;
 
   virtual mozilla::EventListenerManager*
     GetOrCreateListenerManager() override;
 
-  using mozilla::dom::EventTarget::AddEventListener;
-  virtual void AddEventListener(const nsAString& aType,
-                                mozilla::dom::EventListener* aListener,
-                                const mozilla::dom::AddEventListenerOptionsOrBoolean& aOptions,
-                                const mozilla::dom::Nullable<bool>& aWantsUntrusted,
-                                mozilla::ErrorResult& aRv) override;
-  virtual nsresult AddEventListener(const nsAString& aType,
-                                    nsIDOMEventListener* aListener,
-                                    bool aUseCapture,
-                                    const Nullable<bool>& aWantsUntrusted) override;
-  /**
-   * A helper to determine the wantsUntrusted value from the given Nullable<bool>.
-   */
-  bool ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted);
+  bool ComputeDefaultWantsUntrusted(mozilla::ErrorResult& aRv) final;
+
   virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindings() override;
 
   virtual nsIGlobalObject* GetOwnerGlobal() const override;
 
   EventTarget* GetTargetForDOMEvent() override;
   
   using mozilla::dom::EventTarget::DispatchEvent;
   bool DispatchEvent(mozilla::dom::Event& aEvent,
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -6461,41 +6461,23 @@ nsGlobalWindowOuter::GetOwnerGlobalForBi
 bool
 nsGlobalWindowOuter::DispatchEvent(Event& aEvent,
                                    CallerType aCallerType,
                                    ErrorResult& aRv)
 {
   FORWARD_TO_INNER(DispatchEvent, (aEvent, aCallerType, aRv), false);
 }
 
-nsresult
-nsGlobalWindowOuter::AddEventListener(const nsAString& aType,
-                                      nsIDOMEventListener *aListener,
-                                      bool aUseCapture,
-                                      const Nullable<bool>& aWantsUntrusted)
-{
-  FORWARD_TO_INNER_CREATE(AddEventListener,
-                          (aType, aListener, aUseCapture, aWantsUntrusted),
-                          NS_ERROR_UNEXPECTED);
-}
-
-void
-nsGlobalWindowOuter::AddEventListener(const nsAString& aType,
-                                      EventListener* aListener,
-                                      const AddEventListenerOptionsOrBoolean& aOptions,
-                                      const Nullable<bool>& aWantsUntrusted,
-                                      ErrorResult& aRv)
-{
-  if (mInnerWindow && !nsContentUtils::CanCallerAccess(mInnerWindow)) {
-    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
-    return;
-  }
-
-  FORWARD_TO_INNER_CREATE(AddEventListener,
-                          (aType, aListener, aOptions, aWantsUntrusted, aRv),);
+bool
+nsGlobalWindowOuter::ComputeDefaultWantsUntrusted(ErrorResult& aRv)
+{
+  // It's OK that we just return false here on failure to create an
+  // inner.  GetOrCreateListenerManager() will likewise fail, and then
+  // we won't be adding any listeners anyway.
+  FORWARD_TO_INNER_CREATE(ComputeDefaultWantsUntrusted, (aRv), false);
 }
 
 NS_IMETHODIMP
 nsGlobalWindowOuter::AddSystemEventListener(const nsAString& aType,
                                             nsIDOMEventListener *aListener,
                                             bool aUseCapture,
                                             bool aWantsUntrusted,
                                             uint8_t aOptionalArgc)
--- a/dom/base/nsGlobalWindowOuter.h
+++ b/dom/base/nsGlobalWindowOuter.h
@@ -276,26 +276,18 @@ public:
   NS_DECL_NSIDOMEVENTTARGET
 
   virtual mozilla::EventListenerManager*
     GetExistingListenerManager() const override;
 
   virtual mozilla::EventListenerManager*
     GetOrCreateListenerManager() override;
 
-  using mozilla::dom::EventTarget::AddEventListener;
-  virtual void AddEventListener(const nsAString& aType,
-                                mozilla::dom::EventListener* aListener,
-                                const mozilla::dom::AddEventListenerOptionsOrBoolean& aOptions,
-                                const mozilla::dom::Nullable<bool>& aWantsUntrusted,
-                                mozilla::ErrorResult& aRv) override;
-  virtual nsresult AddEventListener(const nsAString& aType,
-                                    nsIDOMEventListener* aListener,
-                                    bool aUseCapture,
-                                    const Nullable<bool>& aWantsUntrusted) override;
+  bool ComputeDefaultWantsUntrusted(mozilla::ErrorResult& aRv) final;
+
   virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindings() override;
 
   virtual nsIGlobalObject* GetOwnerGlobal() const override;
 
   EventTarget* GetTargetForEventTargetChain() override;
   
   using mozilla::dom::EventTarget::DispatchEvent;
   bool DispatchEvent(mozilla::dom::Event& aEvent,
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -1012,57 +1012,19 @@ nsINode::LookupNamespaceURI(const nsAStr
   if (!element ||
       NS_FAILED(element->LookupNamespaceURIInternal(aNamespacePrefix,
                                                     aNamespaceURI))) {
     SetDOMStringToNull(aNamespaceURI);
   }
 }
 
 bool
-nsINode::ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted)
-{
-  if (!aWantsUntrusted.IsNull()) {
-    return aWantsUntrusted.Value();
-  }
-
-  return !nsContentUtils::IsChromeDoc(OwnerDoc());
-}
-
-nsresult
-nsINode::AddEventListener(const nsAString& aType,
-                          nsIDOMEventListener *aListener,
-                          bool aUseCapture,
-                          const Nullable<bool>& aWantsUntrusted)
+nsINode::ComputeDefaultWantsUntrusted(ErrorResult& aRv)
 {
-  bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted);
-
-  EventListenerManager* listener_manager = GetOrCreateListenerManager();
-  NS_ENSURE_STATE(listener_manager);
-  listener_manager->AddEventListener(aType, aListener, aUseCapture,
-                                     wantsUntrusted);
-  return NS_OK;
-}
-
-void
-nsINode::AddEventListener(const nsAString& aType,
-                          EventListener* aListener,
-                          const AddEventListenerOptionsOrBoolean& aOptions,
-                          const Nullable<bool>& aWantsUntrusted,
-                          ErrorResult& aRv)
-{
-  bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted);
-
-  EventListenerManager* listener_manager = GetOrCreateListenerManager();
-  if (!listener_manager) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return;
-  }
-
-  listener_manager->AddEventListener(aType, aListener, aOptions,
-                                     wantsUntrusted);
+  return !nsContentUtils::IsChromeDoc(OwnerDoc());
 }
 
 NS_IMETHODIMP
 nsINode::AddSystemEventListener(const nsAString& aType,
                                 nsIDOMEventListener *aListener,
                                 bool aUseCapture,
                                 bool aWantsUntrusted,
                                 uint8_t aOptionalArgc)
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -1024,30 +1024,17 @@ public:
    */
   NS_DECL_NSIDOMEVENTTARGET
 
   virtual mozilla::EventListenerManager*
     GetExistingListenerManager() const override;
   virtual mozilla::EventListenerManager*
     GetOrCreateListenerManager() override;
 
-  using mozilla::dom::EventTarget::AddEventListener;
-  virtual void AddEventListener(const nsAString& aType,
-                                mozilla::dom::EventListener* aListener,
-                                const mozilla::dom::AddEventListenerOptionsOrBoolean& aOptions,
-                                const mozilla::dom::Nullable<bool>& aWantsUntrusted,
-                                mozilla::ErrorResult& aRv) override;
-  virtual nsresult AddEventListener(const nsAString& aType,
-                                    nsIDOMEventListener* aListener,
-                                    bool aUseCapture,
-                                    const Nullable<bool>& aWantsUntrusted) override;
-  /**
-   * A helper to determine the wantsUntrusted value from the given Nullable<bool>.
-   */
-  bool ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted);
+  bool ComputeDefaultWantsUntrusted(mozilla::ErrorResult& aRv) final;
   using nsIDOMEventTarget::AddSystemEventListener;
 
   virtual bool IsApzAware() const override;
 
   virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindings() override;
   virtual nsIGlobalObject* GetOwnerGlobal() const override;
 
   using mozilla::dom::EventTarget::DispatchEvent;
--- a/dom/base/nsWindowRoot.cpp
+++ b/dom/base/nsWindowRoot.cpp
@@ -80,52 +80,21 @@ nsWindowRoot::DispatchEvent(Event& aEven
   bool retval = !aEvent.DefaultPrevented(aCallerType);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
   }
   return retval;
 }
 
 bool
-nsWindowRoot::ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted)
+nsWindowRoot::ComputeDefaultWantsUntrusted(ErrorResult& aRv)
 {
-  return !aWantsUntrusted.IsNull() && aWantsUntrusted.Value();
-}
-
-nsresult
-nsWindowRoot::AddEventListener(const nsAString& aType,
-                               nsIDOMEventListener *aListener,
-                               bool aUseCapture,
-                               const Nullable<bool>& aWantsUntrusted)
-{
-  bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted);
-
-  EventListenerManager* elm = GetOrCreateListenerManager();
-  NS_ENSURE_STATE(elm);
-  elm->AddEventListener(aType, aListener, aUseCapture, wantsUntrusted);
-  return NS_OK;
+  return false;
 }
 
-void
-nsWindowRoot::AddEventListener(const nsAString& aType,
-                                EventListener* aListener,
-                                const AddEventListenerOptionsOrBoolean& aOptions,
-                                const Nullable<bool>& aWantsUntrusted,
-                                ErrorResult& aRv)
-{
-  bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted);
-  EventListenerManager* elm = GetOrCreateListenerManager();
-  if (!elm) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return;
-  }
-  elm->AddEventListener(aType, aListener, aOptions, wantsUntrusted);
-}
-
-
 NS_IMETHODIMP
 nsWindowRoot::AddSystemEventListener(const nsAString& aType,
                                      nsIDOMEventListener *aListener,
                                      bool aUseCapture,
                                      bool aWantsUntrusted,
                                      uint8_t aOptionalArgc)
 {
   NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
--- a/dom/base/nsWindowRoot.h
+++ b/dom/base/nsWindowRoot.h
@@ -27,29 +27,17 @@ public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIDOMEVENTTARGET
 
   virtual mozilla::EventListenerManager*
     GetExistingListenerManager() const override;
   virtual mozilla::EventListenerManager*
     GetOrCreateListenerManager() override;
 
-  virtual void AddEventListener(const nsAString& aType,
-                                mozilla::dom::EventListener* aListener,
-                                const mozilla::dom::AddEventListenerOptionsOrBoolean& aOptions,
-                                const mozilla::dom::Nullable<bool>& aWantsUntrusted,
-                                mozilla::ErrorResult& aRv) override;
-  virtual nsresult AddEventListener(const nsAString& aType,
-                                    nsIDOMEventListener* aListener,
-                                    bool aUseCapture,
-                                    const Nullable<bool>& aWantsUntrusted) override;
-  /**
-   * A helper to determine the wantsUntrusted value from the given Nullable<bool>.
-   */
-  bool ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted);
+  bool ComputeDefaultWantsUntrusted(mozilla::ErrorResult& aRv) final;
 
   bool DispatchEvent(mozilla::dom::Event& aEvent,
                      mozilla::dom::CallerType aCallerType,
                      mozilla::ErrorResult& aRv) override;
 
   void GetEventTargetParent(mozilla::EventChainPreVisitor& aVisitor) override;
 
   nsresult PostHandleEvent(mozilla::EventChainPostVisitor& aVisitor) override;
--- a/dom/events/DOMEventTargetHelper.cpp
+++ b/dom/events/DOMEventTargetHelper.cpp
@@ -169,71 +169,27 @@ DOMEventTargetHelper::GetDocumentIfCurre
   if (!win) {
     return nullptr;
   }
 
   return win->GetDoc();
 }
 
 bool
-DOMEventTargetHelper::ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted,
-                                            ErrorResult& aRv)
+DOMEventTargetHelper::ComputeDefaultWantsUntrusted(ErrorResult& aRv)
 {
-  if (!aWantsUntrusted.IsNull()) {
-    return aWantsUntrusted.Value();
-  }
-  
   bool wantsUntrusted;
   nsresult rv = WantsUntrusted(&wantsUntrusted);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return false;
   }
   return wantsUntrusted;
 }
 
-nsresult
-DOMEventTargetHelper::AddEventListener(const nsAString& aType,
-                                       nsIDOMEventListener* aListener,
-                                       bool aUseCapture,
-                                       const Nullable<bool>& aWantsUntrusted)
-{
-  ErrorResult rv;
-  bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted, rv);
-  if (rv.Failed()) {
-    return rv.StealNSResult();
-  }
-
-  EventListenerManager* elm = GetOrCreateListenerManager();
-  NS_ENSURE_STATE(elm);
-  elm->AddEventListener(aType, aListener, aUseCapture, wantsUntrusted);
-  return NS_OK;
-}
-
-void
-DOMEventTargetHelper::AddEventListener(const nsAString& aType,
-                                       EventListener* aListener,
-                                       const AddEventListenerOptionsOrBoolean& aOptions,
-                                       const Nullable<bool>& aWantsUntrusted,
-                                       ErrorResult& aRv)
-{
-  bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted, aRv);
-  if (aRv.Failed()) {
-    return;
-  }
-
-  EventListenerManager* elm = GetOrCreateListenerManager();
-  if (!elm) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return;
-  }
-
-  elm->AddEventListener(aType, aListener, aOptions, wantsUntrusted);
-}
-
 NS_IMETHODIMP
 DOMEventTargetHelper::AddSystemEventListener(const nsAString& aType,
                                              nsIDOMEventListener* aListener,
                                              bool aUseCapture,
                                              bool aWantsUntrusted,
                                              uint8_t aOptionalArgc)
 {
   NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
--- a/dom/events/DOMEventTargetHelper.h
+++ b/dom/events/DOMEventTargetHelper.h
@@ -68,31 +68,17 @@ public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(DOMEventTargetHelper)
 
   NS_DECL_NSIDOMEVENTTARGET
 
   virtual EventListenerManager* GetExistingListenerManager() const override;
   virtual EventListenerManager* GetOrCreateListenerManager() override;
 
-  using EventTarget::AddEventListener;
-  virtual void AddEventListener(const nsAString& aType,
-                                dom::EventListener* aListener,
-                                const dom::AddEventListenerOptionsOrBoolean& aOptions,
-                                const dom::Nullable<bool>& aWantsUntrusted,
-                                ErrorResult& aRv) override;
-  virtual nsresult AddEventListener(const nsAString& aType,
-                                    nsIDOMEventListener* aListener,
-                                    bool aUseCapture,
-                                    const Nullable<bool>& aWantsUntrusted) override;
-  /**
-   * A helper to determine the wantsUntrusted value from the given Nullable<bool>.
-   */
-  bool ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted,
-                             ErrorResult& aRv);
+  bool ComputeDefaultWantsUntrusted(ErrorResult& aRv) override;
 
   using EventTarget::DispatchEvent;
   bool DispatchEvent(dom::Event& aEvent, dom::CallerType aCallerType,
                      ErrorResult& aRv) override;
 
   void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
 
   nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) override;
--- a/dom/events/EventTarget.cpp
+++ b/dom/events/EventTarget.cpp
@@ -22,16 +22,71 @@ EventTarget::Constructor(const GlobalObj
   if (!global) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
   RefPtr<EventTarget> target = new ConstructibleEventTarget(global);
   return target.forget();
 }
 
+bool
+EventTarget::ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted,
+                                   ErrorResult& aRv)
+{
+  if (!aWantsUntrusted.IsNull()) {
+    return aWantsUntrusted.Value();
+  }
+
+  bool defaultWantsUntrusted = ComputeDefaultWantsUntrusted(aRv);
+  if (aRv.Failed()) {
+    return false;
+  }
+
+  return defaultWantsUntrusted;
+}
+
+void
+EventTarget::AddEventListener(const nsAString& aType,
+                              EventListener* aCallback,
+                              const AddEventListenerOptionsOrBoolean& aOptions,
+                              const Nullable<bool>& aWantsUntrusted,
+                              ErrorResult& aRv)
+{
+  bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted, aRv);
+  if (aRv.Failed()) {
+    return;
+  }
+
+  EventListenerManager* elm = GetOrCreateListenerManager();
+  if (!elm) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return;
+  }
+
+  elm->AddEventListener(aType, aCallback, aOptions, wantsUntrusted);
+}
+
+nsresult
+EventTarget::AddEventListener(const nsAString& aType,
+                              nsIDOMEventListener* aListener,
+                              bool aUseCapture,
+                              const Nullable<bool>& aWantsUntrusted)
+{
+  ErrorResult rv;
+  bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted, rv);
+  if (rv.Failed()) {
+    return rv.StealNSResult();
+  }
+
+  EventListenerManager* elm = GetOrCreateListenerManager();
+  NS_ENSURE_STATE(elm);
+  elm->AddEventListener(aType, aListener, aUseCapture, wantsUntrusted);
+  return NS_OK;
+}
+
 void
 EventTarget::RemoveEventListener(const nsAString& aType,
                                  EventListener* aListener,
                                  const EventListenerOptionsOrBoolean& aOptions,
                                  ErrorResult& aRv)
 {
   EventListenerManager* elm = GetExistingListenerManager();
   if (elm) {
--- a/dom/events/EventTarget.h
+++ b/dom/events/EventTarget.h
@@ -49,37 +49,37 @@ public:
   static EventTarget* From(nsIDOMEventTarget* aTarget)
   {
     return static_cast<EventTarget*>(aTarget);
   }
 
   // WebIDL API
   static already_AddRefed<EventTarget> Constructor(const GlobalObject& aGlobal,
                                                    ErrorResult& aRv);
-  virtual void AddEventListener(const nsAString& aType,
-                                EventListener* aCallback,
-                                const AddEventListenerOptionsOrBoolean& aOptions,
-                                const Nullable<bool>& aWantsUntrusted,
-                                ErrorResult& aRv) = 0;
+  void AddEventListener(const nsAString& aType,
+                        EventListener* aCallback,
+                        const AddEventListenerOptionsOrBoolean& aOptions,
+                        const Nullable<bool>& aWantsUntrusted,
+                        ErrorResult& aRv);
   void RemoveEventListener(const nsAString& aType,
                            EventListener* aCallback,
                            const EventListenerOptionsOrBoolean& aOptions,
                            ErrorResult& aRv);
 
 protected:
   /**
    * This method allows addition of event listeners represented by
    * nsIDOMEventListener, with almost the same semantics as the
    * standard AddEventListener.  The one difference is that it just
    * has a "use capture" boolean, not an EventListenerOptions.
    */
-  virtual nsresult AddEventListener(const nsAString& aType,
-                                    nsIDOMEventListener* aListener,
-                                    bool aUseCapture,
-                                    const Nullable<bool>& aWantsUntrusted) = 0;
+  nsresult AddEventListener(const nsAString& aType,
+                            nsIDOMEventListener* aListener,
+                            bool aUseCapture,
+                            const Nullable<bool>& aWantsUntrusted);
 
 public:
   /**
    * Helper methods to make the nsIDOMEventListener version of
    * AddEventListener simpler to call for consumers.
    */
   nsresult AddEventListener(const nsAString& aType,
                             nsIDOMEventListener* aListener,
@@ -263,16 +263,35 @@ public:
    */
   virtual nsresult PostHandleEvent(EventChainPostVisitor& aVisitor) = 0;
   
 protected:
   EventHandlerNonNull* GetEventHandler(nsAtom* aType,
                                        const nsAString& aTypeString);
   void SetEventHandler(nsAtom* aType, const nsAString& aTypeString,
                        EventHandlerNonNull* aHandler);
+
+  /**
+   * Hook for AddEventListener that allows it to compute the right
+   * wantsUntrusted boolean when one is not provided.  If this returns failure,
+   * the listener will not be added.
+   *
+   * This hook will NOT be called unless aWantsUntrusted is null in
+   * AddEventListener.  If you need to take action when event listeners are
+   * added, use EventListenerAdded.  Especially because not all event listener
+   * additions go through AddEventListener!
+   */
+  virtual bool ComputeDefaultWantsUntrusted(ErrorResult& aRv) = 0;
+
+  /**
+   * A method to compute the right wantsUntrusted value for AddEventListener.
+   * This will call the above hook as needed.
+   */
+  bool ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted,
+                             ErrorResult& aRv);
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(EventTarget, NS_EVENTTARGET_IID)
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_EventTarget_h_
--- a/dom/media/MediaDevices.cpp
+++ b/dom/media/MediaDevices.cpp
@@ -266,42 +266,21 @@ MediaDevices::SetOndevicechange(mozilla:
     SetEventHandler(nsGkAtoms::ondevicechange, EmptyString(), aCallback);
   } else {
     SetEventHandler(nullptr, NS_LITERAL_STRING("devicechange"), aCallback);
   }
 
   MediaManager::Get()->AddDeviceChangeCallback(this);
 }
 
-nsresult
-MediaDevices::AddEventListener(const nsAString& aType,
-                               nsIDOMEventListener* aListener,
-                               bool aUseCapture,
-                               const Nullable<bool>& aWantsUntrusted)
+void
+MediaDevices::EventListenerAdded(nsAtom* aType)
 {
   MediaManager::Get()->AddDeviceChangeCallback(this);
-
-  return DOMEventTargetHelper::AddEventListener(aType, aListener,
-                                                aUseCapture,
-                                                aWantsUntrusted);
-}
-
-void
-MediaDevices::AddEventListener(const nsAString& aType,
-                               EventListener* aListener,
-                               const AddEventListenerOptionsOrBoolean& aOptions,
-                               const Nullable<bool>& aWantsUntrusted,
-                               ErrorResult& aRv)
-{
-  MediaManager::Get()->AddDeviceChangeCallback(this);
-
-  return DOMEventTargetHelper::AddEventListener(aType, aListener,
-                                                aOptions,
-                                                aWantsUntrusted,
-                                                aRv);
+  DOMEventTargetHelper::EventListenerAdded(aType);
 }
 
 JSObject*
 MediaDevices::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return MediaDevicesBinding::Wrap(aCx, this, aGivenProto);
 }
 
--- a/dom/media/MediaDevices.h
+++ b/dom/media/MediaDevices.h
@@ -46,26 +46,18 @@ public:
   EnumerateDevices(CallerType aCallerType, ErrorResult &aRv);
 
   virtual void OnDeviceChange() override;
 
   mozilla::dom::EventHandlerNonNull* GetOndevicechange();
 
   void SetOndevicechange(mozilla::dom::EventHandlerNonNull* aCallback);
 
-  nsresult AddEventListener(const nsAString& aType,
-			    nsIDOMEventListener* aListener,
-			    bool aUseCapture,
-			    const Nullable<bool>& aWantsUntrusted) override;
-
-  virtual void AddEventListener(const nsAString& aType,
-                                dom::EventListener* aListener,
-                                const AddEventListenerOptionsOrBoolean& aOptions,
-                                const Nullable<bool>& aWantsUntrusted,
-                                ErrorResult& aRv) override;
+  void EventListenerAdded(nsAtom* aType) override;
+  using DOMEventTargetHelper::EventListenerAdded;
 
 private:
   class GumResolver;
   class EnumDevResolver;
   class GumRejecter;
 
   virtual ~MediaDevices();
   nsCOMPtr<nsITimer> mFuzzTimer;
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -783,41 +783,31 @@ ServiceWorkerGlobalScope::SetOnfetch(moz
       mWorkerPrivate->DispatchToMainThread(r.forget());
     }
     mWorkerPrivate->SetFetchHandlerWasAdded();
   }
   SetEventHandler(nullptr, NS_LITERAL_STRING("fetch"), aCallback);
 }
 
 void
-ServiceWorkerGlobalScope::AddEventListener(
-                          const nsAString& aType,
-                          dom::EventListener* aListener,
-                          const dom::AddEventListenerOptionsOrBoolean& aOptions,
-                          const dom::Nullable<bool>& aWantsUntrusted,
-                          ErrorResult& aRv)
+ServiceWorkerGlobalScope::EventListenerAdded(const nsAString& aType)
 {
   MOZ_ASSERT(mWorkerPrivate);
   mWorkerPrivate->AssertIsOnWorkerThread();
 
-  DOMEventTargetHelper::AddEventListener(aType, aListener, aOptions,
-                                         aWantsUntrusted, aRv);
-
   if (!aType.EqualsLiteral("fetch")) {
     return;
   }
 
   if (mWorkerPrivate->WorkerScriptExecutedSuccessfully()) {
     RefPtr<Runnable> r = new ReportFetchListenerWarningRunnable(mScope);
     mWorkerPrivate->DispatchToMainThread(r.forget());
   }
 
-  if (!aRv.Failed()) {
-    mWorkerPrivate->SetFetchHandlerWasAdded();
-  }
+  mWorkerPrivate->SetFetchHandlerWasAdded();
 }
 
 namespace {
 
 class SkipWaitingResultRunnable final : public WorkerRunnable
 {
   RefPtr<PromiseWorkerProxy> mPromiseProxy;
 
--- a/dom/workers/WorkerScope.h
+++ b/dom/workers/WorkerScope.h
@@ -341,23 +341,21 @@ public:
   IMPL_EVENT_HANDLER(pushsubscriptionchange)
 
   EventHandlerNonNull*
   GetOnfetch();
 
   void
   SetOnfetch(mozilla::dom::EventHandlerNonNull* aCallback);
 
-  using DOMEventTargetHelper::AddEventListener;
-  virtual void
-  AddEventListener(const nsAString& aType,
-                   dom::EventListener* aListener,
-                   const dom::AddEventListenerOptionsOrBoolean& aOptions,
-                   const dom::Nullable<bool>& aWantsUntrusted,
-                   ErrorResult& aRv) override;
+  // We only need to override the string version of EventListenerAdded, because
+  // the atom version should never be called on workers.  Until bug 1450167 is
+  // fixed, at least.
+  using DOMEventTargetHelper::EventListenerAdded;
+  void EventListenerAdded(const nsAString& aType) override;
 };
 
 class WorkerDebuggerGlobalScope final : public DOMEventTargetHelper,
                                         public nsIGlobalObject
 {
   WorkerPrivate* mWorkerPrivate;
   RefPtr<Console> mConsole;
   nsCOMPtr<nsISerialEventTarget> mSerialEventTarget;