Bug 1317990. Remove Event::IsChrome in favor of passing CallerType arguments. r=smaug,bkelly
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 16 Nov 2016 14:10:22 -0500
changeset 322855 482ed3f75e5b92aaeffd4471a28e4be8399e7084
parent 322854 a1d6693a7f5b965462208d53058e9925e35aeafe
child 322856 f9f88713123dd3486daa5e71559f64e5131050f8
push id30961
push userkwierso@gmail.com
push dateThu, 17 Nov 2016 01:08:03 +0000
treeherdermozilla-central@c27117f67fa3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, bkelly
bugs1317990
milestone53.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 1317990. Remove Event::IsChrome in favor of passing CallerType arguments. r=smaug,bkelly
dom/bindings/Bindings.conf
dom/events/Event.cpp
dom/events/Event.h
dom/events/EventTarget.cpp
dom/events/EventTarget.h
dom/webidl/Event.webidl
dom/webidl/EventTarget.webidl
dom/workers/ServiceWorkerEvents.cpp
dom/workers/ServiceWorkerEvents.h
dom/workers/ServiceWorkerPrivate.cpp
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -284,29 +284,28 @@ DOMInterfaces = {
 
 'DynamicsCompressorNode': {
     'binaryNames': {
         'release': 'getRelease'
     },
 },
 
 'Event': {
-    'implicitJSContext': [ 'defaultPrevented', 'preventDefault' ],
+    'implicitJSContext': [ 'preventDefault' ],
 },
 
 'EventTarget': {
     # When we get rid of hasXPConnectImpls, we can get rid of the
     # couldBeDOMBinding stuff in GetOrCreateDOMReflector.
     #
     # We can also get rid of the UnwrapArg bits in
     # the dom QueryInterface (in BindingUtils.cpp) at that point.
     'hasXPConnectImpls': True,
     'concrete': False,
     'jsImplParent': 'mozilla::DOMEventTargetHelper',
-    'implicitJSContext': [ 'dispatchEvent' ]
 },
 
 'Exception': {
     'headerFile': 'mozilla/dom/DOMException.h',
     'binaryNames': {
         'message': 'messageMoz',
     },
     'implicitJSContext': [ '__stringifier', 'filename', 'lineNumber', 'stack' ],
--- a/dom/events/Event.cpp
+++ b/dom/events/Event.cpp
@@ -241,24 +241,16 @@ Event::WrapObject(JSContext* aCx, JS::Ha
 }
 
 JSObject*
 Event::WrapObjectInternal(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return EventBinding::Wrap(aCx, this, aGivenProto);
 }
 
-bool
-Event::IsChrome(JSContext* aCx) const
-{
-  return mIsMainThreadEvent ?
-    xpc::AccessCheck::isChrome(js::GetContextCompartment(aCx)) :
-    mozilla::dom::workers::IsCurrentThreadRunningChromeWorker();
-}
-
 // nsIDOMEventInterface
 NS_IMETHODIMP
 Event::GetType(nsAString& aType)
 {
   if (!mIsMainThreadEvent || !mEvent->mSpecifiedEventTypeString.IsEmpty()) {
     aType = mEvent->mSpecifiedEventTypeString;
     return NS_OK;
   }
@@ -499,25 +491,23 @@ Event::PreventDefault()
 {
   // This method is called only from C++ code which must handle default action
   // of this event.  So, pass true always.
   PreventDefaultInternal(true);
   return NS_OK;
 }
 
 void
-Event::PreventDefault(JSContext* aCx)
+Event::PreventDefault(JSContext* aCx, CallerType aCallerType)
 {
-  MOZ_ASSERT(aCx, "JS context must be specified");
-
   // Note that at handling default action, another event may be dispatched.
   // Then, JS in content mey be call preventDefault()
   // even in the event is in system event group.  Therefore, don't refer
   // mInSystemGroup here.
-  PreventDefaultInternal(IsChrome(aCx));
+  PreventDefaultInternal(aCallerType == CallerType::System);
 }
 
 void
 Event::PreventDefaultInternal(bool aCalledByDefaultHandler)
 {
   if (!mEvent->mFlags.mCancelable) {
     return;
   }
@@ -1060,31 +1050,30 @@ Event::GetEventName(EventMessage aEventT
   // create and that are not user defined events since this function and
   // SetEventType are incomplete.  (But fixing that requires fixing the
   // arrays in nsEventListenerManager too, since the events for which
   // this is a problem generally *are* created by Event.)
   return nullptr;
 }
 
 bool
-Event::DefaultPrevented(JSContext* aCx) const
+Event::DefaultPrevented(CallerType aCallerType) const
 {
-  MOZ_ASSERT(aCx, "JS context must be specified");
-
   NS_ENSURE_TRUE(mEvent, false);
 
   // If preventDefault() has never been called, just return false.
   if (!mEvent->DefaultPrevented()) {
     return false;
   }
 
   // If preventDefault() has been called by content, return true.  Otherwise,
   // i.e., preventDefault() has been called by chrome, return true only when
   // this is called by chrome.
-  return mEvent->DefaultPreventedByContent() || IsChrome(aCx);
+  return mEvent->DefaultPreventedByContent() ||
+         aCallerType == CallerType::System;
 }
 
 double
 Event::TimeStamp() const
 {
   if (!sReturnHighResTimeStamp) {
     return static_cast<double>(mEvent->mTime);
   }
--- a/dom/events/Event.h
+++ b/dom/events/Event.h
@@ -10,16 +10,17 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/BasicEvents.h"
 #include "nsIDOMEvent.h"
 #include "nsISupports.h"
 #include "nsCOMPtr.h"
 #include "nsPIDOMWindow.h"
 #include "nsPoint.h"
 #include "nsCycleCollectionParticipant.h"
+#include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/EventBinding.h"
 #include "nsIScriptGlobalObject.h"
 #include "Units.h"
 #include "js/TypeDecls.h"
 #include "nsIGlobalObject.h"
 
 class nsIContent;
 class nsIDOMEventTarget;
@@ -173,26 +174,26 @@ public:
   bool Composed() const
   {
     return mEvent->mFlags.mComposed;
   }
 
   // xpidl implementation
   // void PreventDefault();
 
-  // You MUST NOT call PreventDefaultJ(JSContext*) from C++ code.  A call of
-  // this method always sets Event.defaultPrevented true for web contents.
-  // If default action handler calls this, web applications meet wrong
+  // You MUST NOT call PreventDefault(JSContext*, CallerType) from C++ code.  A
+  // call of this method always sets Event.defaultPrevented true for web
+  // contents.  If default action handler calls this, web applications see wrong
   // defaultPrevented value.
-  virtual void PreventDefault(JSContext* aCx);
+  virtual void PreventDefault(JSContext* aCx, CallerType aCallerType);
 
-  // You MUST NOT call DefaultPrevented(JSContext*) from C++ code.  This may
+  // You MUST NOT call DefaultPrevented(CallerType) from C++ code.  This may
   // return false even if PreventDefault() has been called.
-  // See comments in its implementation for the detail.
-  bool DefaultPrevented(JSContext* aCx) const;
+  // See comments in its implementation for the details.
+  bool DefaultPrevented(CallerType aCallerType) const;
 
   bool DefaultPrevented() const
   {
     return mEvent->DefaultPrevented();
   }
 
   bool DefaultPreventedByChrome() const
   {
@@ -268,22 +269,16 @@ protected:
     mWantsPopupControlCheck = aCheck;
   }
 
   bool GetWantsPopupControlCheck()
   {
     return IsTrusted() && mWantsPopupControlCheck;
   }
 
-  /**
-   * IsChrome() returns true if aCx is chrome context or the event is created
-   * in chrome's thread.  Otherwise, false.
-   */
-  bool IsChrome(JSContext* aCx) const;
-
   void SetComposed(bool aComposed)
   {
     mEvent->SetComposed(aComposed);
   }
 
   mozilla::WidgetEvent*       mEvent;
   RefPtr<nsPresContext>     mPresContext;
   nsCOMPtr<EventTarget>       mExplicitOriginalTarget;
@@ -358,17 +353,17 @@ private:
   bool mOriginalWantsPopupControlCheck;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #define NS_FORWARD_TO_EVENT \
   NS_FORWARD_NSIDOMEVENT(Event::) \
-  virtual void PreventDefault(JSContext* aCx) override { Event::PreventDefault(aCx); }
+  virtual void PreventDefault(JSContext* aCx, CallerType aCallerType) override { Event::PreventDefault(aCx, aCallerType); }
 
 #define NS_FORWARD_NSIDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION(_to) \
   NS_IMETHOD GetType(nsAString& aType) override { return _to GetType(aType); } \
   NS_IMETHOD GetTarget(nsIDOMEventTarget** aTarget) override { return _to GetTarget(aTarget); } \
   NS_IMETHOD GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget) override { return _to GetCurrentTarget(aCurrentTarget); } \
   NS_IMETHOD GetEventPhase(uint16_t* aEventPhase) override { return _to GetEventPhase(aEventPhase); } \
   NS_IMETHOD GetBubbles(bool* aBubbles) override { return _to GetBubbles(aBubbles); } \
   NS_IMETHOD GetCancelable(bool* aCancelable) override { return _to GetCancelable(aCancelable); } \
@@ -387,17 +382,17 @@ private:
   NS_IMETHOD_(bool) IsDispatchStopped(void) override { return _to IsDispatchStopped(); } \
   NS_IMETHOD_(WidgetEvent*) WidgetEventPtr(void) override { return _to WidgetEventPtr(); } \
   NS_IMETHOD_(void) SetTrusted(bool aTrusted) override { _to SetTrusted(aTrusted); } \
   NS_IMETHOD_(void) SetOwner(EventTarget* aOwner) override { _to SetOwner(aOwner); } \
   NS_IMETHOD_(Event*) InternalDOMEvent() override { return _to InternalDOMEvent(); }
 
 #define NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION \
   NS_FORWARD_NSIDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION(Event::) \
-  virtual void PreventDefault(JSContext* aCx) override { Event::PreventDefault(aCx); }
+  virtual void PreventDefault(JSContext* aCx, CallerType aCallerType) override { Event::PreventDefault(aCx, aCallerType); }
 
 inline nsISupports*
 ToSupports(mozilla::dom::Event* e)
 {
   return static_cast<nsIDOMEvent*>(e);
 }
 
 inline nsISupports*
--- a/dom/events/EventTarget.cpp
+++ b/dom/events/EventTarget.cpp
@@ -60,19 +60,19 @@ EventTarget::SetEventHandler(nsIAtom* aT
 bool
 EventTarget::IsApzAware() const
 {
   EventListenerManager* elm = GetExistingListenerManager();
   return elm && elm->HasApzAwareListeners();
 }
 
 bool
-EventTarget::DispatchEvent(JSContext* aCx,
-                           Event& aEvent,
+EventTarget::DispatchEvent(Event& aEvent,
+                           CallerType aCallerType,
                            ErrorResult& aRv)
 {
   bool result = false;
   aRv = DispatchEvent(&aEvent, &result);
-  return !aEvent.DefaultPrevented(aCx);
+  return !aEvent.DefaultPrevented(aCallerType);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/events/EventTarget.h
+++ b/dom/events/EventTarget.h
@@ -2,16 +2,17 @@
 /* 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_EventTarget_h_
 #define mozilla_dom_EventTarget_h_
 
+#include "mozilla/dom/BindingDeclarations.h"
 #include "nsIDOMEventTarget.h"
 #include "nsWrapperCache.h"
 #include "nsIAtom.h"
 
 class nsPIDOMWindowOuter;
 class nsIGlobalObject;
 
 namespace mozilla {
@@ -49,17 +50,17 @@ public:
                                 EventListener* aCallback,
                                 const AddEventListenerOptionsOrBoolean& aOptions,
                                 const Nullable<bool>& aWantsUntrusted,
                                 ErrorResult& aRv) = 0;
   virtual void RemoveEventListener(const nsAString& aType,
                                    EventListener* aCallback,
                                    const EventListenerOptionsOrBoolean& aOptions,
                                    ErrorResult& aRv);
-  bool DispatchEvent(JSContext* aCx, Event& aEvent, ErrorResult& aRv);
+  bool DispatchEvent(Event& aEvent, CallerType aCallerType, ErrorResult& aRv);
 
   // Note, this takes the type in onfoo form!
   EventHandlerNonNull* GetEventHandler(const nsAString& aType)
   {
     nsCOMPtr<nsIAtom> type = NS_Atomize(aType);
     return GetEventHandler(type, EmptyString());
   }
 
--- a/dom/webidl/Event.webidl
+++ b/dom/webidl/Event.webidl
@@ -29,18 +29,19 @@ interface Event {
 
   void stopPropagation();
   void stopImmediatePropagation();
 
   [Pure]
   readonly attribute boolean bubbles;
   [Pure]
   readonly attribute boolean cancelable;
+  [NeedsCallerType]
   void preventDefault();
-  [Pure]
+  [Pure, NeedsCallerType]
   readonly attribute boolean defaultPrevented;
   [ChromeOnly, Pure]
   readonly attribute boolean defaultPreventedByChrome;
   [ChromeOnly, Pure]
   readonly attribute boolean defaultPreventedByContent;
   [Pure]
   readonly attribute boolean composed;
 
--- a/dom/webidl/EventTarget.webidl
+++ b/dom/webidl/EventTarget.webidl
@@ -33,17 +33,17 @@ interface EventTarget {
   void addEventListener(DOMString type,
                         EventListener? listener,
                         optional (AddEventListenerOptions or boolean) options,
                         optional boolean? wantsUntrusted = null);
   [Throws]
   void removeEventListener(DOMString type,
                            EventListener? listener,
                            optional (EventListenerOptions or boolean) options);
-  [Throws]
+  [Throws, NeedsCallerType]
   boolean dispatchEvent(Event event);
 };
 
 // Mozilla extensions for use by JS-implemented event targets to
 // implement on* properties.
 partial interface EventTarget {
   // The use of [TreatNonCallableAsNull] here is a bit of a hack: it just makes
   // the codegen check whether the type involved is either
--- a/dom/workers/ServiceWorkerEvents.cpp
+++ b/dom/workers/ServiceWorkerEvents.cpp
@@ -768,32 +768,34 @@ FetchEvent::RespondWith(JSContext* aCx, 
   aArg.AppendNativeHandler(handler);
 
   // Append directly to the lifecycle promises array.  Don't call WaitUntil()
   // because that will lead to double-reporting any errors.
   mPromises.AppendElement(&aArg);
 }
 
 void
-FetchEvent::PreventDefault(JSContext* aCx)
+FetchEvent::PreventDefault(JSContext* aCx, CallerType aCallerType)
 {
   MOZ_ASSERT(aCx);
+  MOZ_ASSERT(aCallerType != CallerType::System,
+             "Since when do we support system-principal service workers?");
 
   if (mPreventDefaultScriptSpec.IsEmpty()) {
     // Note when the FetchEvent might have been canceled by script, but don't
     // actually log the location until we are sure it matters.  This is
     // determined in ServiceWorkerPrivate.cpp.  We only remember the first
     // call to preventDefault() as its the most likely to have actually canceled
     // the event.
     nsJSUtils::GetCallingLocation(aCx, mPreventDefaultScriptSpec,
                                   &mPreventDefaultLineNumber,
                                   &mPreventDefaultColumnNumber);
   }
 
-  Event::PreventDefault(aCx);
+  Event::PreventDefault(aCx, aCallerType);
 }
 
 void
 FetchEvent::ReportCanceled()
 {
   MOZ_ASSERT(!mPreventDefaultScriptSpec.IsEmpty());
 
   RefPtr<InternalRequest> ir = mRequest->GetInternalRequest();
--- a/dom/workers/ServiceWorkerEvents.h
+++ b/dom/workers/ServiceWorkerEvents.h
@@ -118,17 +118,17 @@ protected:
   explicit FetchEvent(EventTarget* aOwner);
   ~FetchEvent();
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FetchEvent, ExtendableEvent)
 
   // Note, we cannot use NS_FORWARD_TO_EVENT because we want a different
-  // PreventDefault(JSContext*) override.
+  // PreventDefault(JSContext*, CallerType) override.
   NS_FORWARD_NSIDOMEVENT(Event::)
 
   virtual JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override
   {
     return FetchEventBinding::Wrap(aCx, this, aGivenProto);
   }
 
   void PostInit(nsMainThreadPtrHandle<nsIInterceptedChannel>& aChannel,
@@ -171,17 +171,17 @@ public:
 
   already_AddRefed<Promise>
   ForwardTo(const nsAString& aUrl);
 
   already_AddRefed<Promise>
   Default();
 
   void
-  PreventDefault(JSContext* aCx) override;
+  PreventDefault(JSContext* aCx, CallerType aCallerType) override;
 
   void
   ReportCanceled();
 };
 
 class PushMessageData final : public nsISupports,
                               public nsWrapperCache
 {
--- a/dom/workers/ServiceWorkerPrivate.cpp
+++ b/dom/workers/ServiceWorkerPrivate.cpp
@@ -1533,17 +1533,19 @@ private:
 
     event->PostInit(mInterceptedChannel, mRegistration, mScriptSpec);
     event->SetTrusted(true);
 
     RefPtr<EventTarget> target = do_QueryObject(aWorkerPrivate->GlobalScope());
     nsresult rv2 = target->DispatchDOMEvent(nullptr, event, nullptr, nullptr);
     if (NS_WARN_IF(NS_FAILED(rv2)) || !event->WaitToRespond()) {
       nsCOMPtr<nsIRunnable> runnable;
-      if (event->DefaultPrevented(aCx)) {
+      MOZ_ASSERT(!aWorkerPrivate->UsesSystemPrincipal(),
+                 "We don't support system-principal serviceworkers");
+      if (event->DefaultPrevented(CallerType::NonSystem)) {
         event->ReportCanceled();
       } else if (event->WidgetEventPtr()->mFlags.mExceptionWasRaised) {
         // Exception logged via the WorkerPrivate ErrorReporter
       } else {
         runnable = new ResumeRequest(mInterceptedChannel);
       }
 
       if (!runnable) {