Bug 1163898 part 1. Give DOMEventTargetHelper a sane accessor for getting its nsIGlobalObject. r=smaug
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 12 May 2015 15:56:39 -0400
changeset 274377 2db3491d59e4035b2fb0e951d4b40299a8d6c4eb
parent 274376 efef07486ddeeb8fe3fca5c1259a393ebf2062fb
child 274378 d9429069ec0e0ccae17e979388c7fbc2e88985da
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1163898
milestone41.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 1163898 part 1. Give DOMEventTargetHelper a sane accessor for getting its nsIGlobalObject. r=smaug
dom/base/nsGlobalWindow.h
dom/base/nsINode.cpp
dom/base/nsINode.h
dom/base/nsPIWindowRoot.h
dom/base/nsWindowRoot.cpp
dom/base/nsWindowRoot.h
dom/events/DOMEventTargetHelper.h
dom/events/EventTarget.h
dom/events/Touch.cpp
dom/events/Touch.h
dom/indexedDB/IndexedDatabaseManager.cpp
dom/webidl/EventTarget.webidl
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -403,25 +403,34 @@ public:
     GetOrCreateListenerManager() override;
 
   using mozilla::dom::EventTarget::RemoveEventListener;
   virtual void AddEventListener(const nsAString& aType,
                                 mozilla::dom::EventListener* aListener,
                                 bool aUseCapture,
                                 const mozilla::dom::Nullable<bool>& aWantsUntrusted,
                                 mozilla::ErrorResult& aRv) override;
-  virtual nsIDOMWindow* GetOwnerGlobal() override
+  virtual nsIDOMWindow* GetOwnerGlobalForBindings() override
   {
     if (IsOuterWindow()) {
       return this;
     }
 
     return GetOuterFromCurrentInner(this);
   }
 
+  virtual nsIGlobalObject* GetOwnerGlobal() const override
+  {
+    if (IsOuterWindow()) {
+      return GetCurrentInnerWindowInternal();
+    }
+
+    return const_cast<nsGlobalWindow*>(this);
+  }
+
   // nsPIDOMWindow
   virtual nsPIDOMWindow* GetPrivateRoot() override;
 
   // Outer windows only.
   virtual void ActivateOrDeactivate(bool aActivate) override;
   virtual void SetActive(bool aActive) override;
   virtual void SetIsBackground(bool aIsBackground) override;
   virtual void SetChromeEventHandler(mozilla::dom::EventTarget* aChromeEventHandler) override;
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -1291,23 +1291,30 @@ nsINode::GetExistingListenerManager() co
 
 nsIScriptContext*
 nsINode::GetContextForEventHandlers(nsresult* aRv)
 {
   return nsContentUtils::GetContextForEventHandlers(this, aRv);
 }
 
 nsIDOMWindow*
-nsINode::GetOwnerGlobal()
+nsINode::GetOwnerGlobalForBindings()
 {
   bool dummy;
   return nsPIDOMWindow::GetOuterFromCurrentInner(
     static_cast<nsGlobalWindow*>(OwnerDoc()->GetScriptHandlingObject(dummy)));
 }
 
+nsIGlobalObject*
+nsINode::GetOwnerGlobal() const
+{
+  bool dummy;
+  return OwnerDoc()->GetScriptHandlingObject(dummy);
+}
+
 bool
 nsINode::UnoptimizableCCNode() const
 {
   const uintptr_t problematicFlags = (NODE_IS_ANONYMOUS_ROOT |
                                       NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE |
                                       NODE_IS_NATIVE_ANONYMOUS_ROOT |
                                       NODE_MAY_BE_IN_BINDING_MNGR |
                                       NODE_IS_IN_SHADOW_TREE);
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -983,17 +983,18 @@ public:
   using mozilla::dom::EventTarget::RemoveEventListener;
   using nsIDOMEventTarget::AddEventListener;
   virtual void AddEventListener(const nsAString& aType,
                                 mozilla::dom::EventListener* aListener,
                                 bool aUseCapture,
                                 const mozilla::dom::Nullable<bool>& aWantsUntrusted,
                                 mozilla::ErrorResult& aRv) override;
   using nsIDOMEventTarget::AddSystemEventListener;
-  virtual nsIDOMWindow* GetOwnerGlobal() override;
+  virtual nsIDOMWindow* GetOwnerGlobalForBindings() override;
+  virtual nsIGlobalObject* GetOwnerGlobal() const override;
 
   /**
    * Adds a mutation observer to be notified when this node, or any of its
    * descendants, are modified. The node will hold a weak reference to the
    * observer, which means that it is the responsibility of the observer to
    * remove itself in case it dies before the node.  If an observer is added
    * while observers are being notified, it may also be notified.  In general,
    * adding observers while inside a notification is not a good idea.  An
--- a/dom/base/nsPIWindowRoot.h
+++ b/dom/base/nsPIWindowRoot.h
@@ -33,14 +33,13 @@ public:
                                            nsIController** aResult) = 0;
   virtual nsresult GetControllers(nsIControllers** aResult) = 0;
 
   virtual void GetEnabledDisabledCommands(nsTArray<nsCString>& aEnabledCommands,
                                           nsTArray<nsCString>& aDisabledCommands) = 0;
 
   virtual void SetParentTarget(mozilla::dom::EventTarget* aTarget) = 0;
   virtual mozilla::dom::EventTarget* GetParentTarget() = 0;
-  virtual nsIDOMWindow* GetOwnerGlobal() override = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsPIWindowRoot, NS_IWINDOWROOT_IID)
 
 #endif // nsPIWindowRoot_h__
--- a/dom/base/nsWindowRoot.cpp
+++ b/dom/base/nsWindowRoot.cpp
@@ -183,21 +183,30 @@ nsWindowRoot::PreHandleEvent(EventChainP
 
 nsresult
 nsWindowRoot::PostHandleEvent(EventChainPostVisitor& aVisitor)
 {
   return NS_OK;
 }
 
 nsIDOMWindow*
-nsWindowRoot::GetOwnerGlobal()
+nsWindowRoot::GetOwnerGlobalForBindings()
 {
   return GetWindow();
 }
 
+nsIGlobalObject*
+nsWindowRoot::GetOwnerGlobal() const
+{
+  nsCOMPtr<nsIGlobalObject> global =
+    do_QueryInterface(mWindow->GetCurrentInnerWindow());
+  // We're still holding a ref to it, so returning the raw pointer is ok...
+  return global;
+}
+
 nsPIDOMWindow*
 nsWindowRoot::GetWindow()
 {
   return mWindow;
 }
 
 nsresult
 nsWindowRoot::GetControllers(nsIControllers** aResult)
--- a/dom/base/nsWindowRoot.h
+++ b/dom/base/nsWindowRoot.h
@@ -54,17 +54,18 @@ public:
   virtual nsIDOMNode* GetPopupNode() override;
   virtual void SetPopupNode(nsIDOMNode* aNode) override;
 
   virtual void SetParentTarget(mozilla::dom::EventTarget* aTarget) override
   {
     mParent = aTarget;
   }
   virtual mozilla::dom::EventTarget* GetParentTarget() override { return mParent; }
-  virtual nsIDOMWindow* GetOwnerGlobal() override;
+  virtual nsIDOMWindow* GetOwnerGlobalForBindings() override;
+  virtual nsIGlobalObject* GetOwnerGlobal() const override;
 
   nsIGlobalObject* GetParentObject();
 
   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsWindowRoot,
                                                          nsIDOMEventTarget)
 
--- a/dom/events/DOMEventTargetHelper.h
+++ b/dom/events/DOMEventTargetHelper.h
@@ -116,17 +116,17 @@ public:
   nsresult SetEventHandler(nsIAtom* aType,
                            JSContext* aCx,
                            const JS::Value& aValue);
   using dom::EventTarget::SetEventHandler;
   void GetEventHandler(nsIAtom* aType,
                        JSContext* aCx,
                        JS::Value* aValue);
   using dom::EventTarget::GetEventHandler;
-  virtual nsIDOMWindow* GetOwnerGlobal() override
+  virtual nsIDOMWindow* GetOwnerGlobalForBindings() override
   {
     return nsPIDOMWindow::GetOuterFromCurrentInner(GetOwner());
   }
 
   nsresult CheckInnerWindowCorrectness()
   {
     NS_ENSURE_STATE(!mHasOrHasHadOwnerWindow || mOwnerWindow);
     if (mOwnerWindow && !mOwnerWindow->IsCurrentInnerWindow()) {
@@ -135,17 +135,22 @@ public:
     return NS_OK;
   }
 
   nsPIDOMWindow* GetOwner() const { return mOwnerWindow; }
   void BindToOwner(nsIGlobalObject* aOwner);
   void BindToOwner(nsPIDOMWindow* aOwner);
   void BindToOwner(DOMEventTargetHelper* aOther);
   virtual void DisconnectFromOwner();                   
-  nsIGlobalObject* GetParentObject() const {
+  nsIGlobalObject* GetParentObject() const
+  {
+    return GetOwnerGlobal();
+  }
+  virtual nsIGlobalObject* GetOwnerGlobal() const override
+  {
     nsCOMPtr<nsIGlobalObject> parentObject = do_QueryReferent(mParentObject);
     return parentObject;
   }
   bool HasOrHasHadOwner() { return mHasOrHasHadOwnerWindow; }
 
   virtual void EventListenerAdded(nsIAtom* aType) override;
   virtual void EventListenerRemoved(nsIAtom* aType) override;
   virtual void EventListenerWasAdded(const nsAString& aType,
--- a/dom/events/EventTarget.h
+++ b/dom/events/EventTarget.h
@@ -7,33 +7,34 @@
 #ifndef mozilla_dom_EventTarget_h_
 #define mozilla_dom_EventTarget_h_
 
 #include "nsIDOMEventTarget.h"
 #include "nsWrapperCache.h"
 #include "nsIAtom.h"
 
 class nsIDOMWindow;
+class nsIGlobalObject;
 
 namespace mozilla {
 
 class ErrorResult;
 class EventListenerManager;
 
 namespace dom {
 
 class Event;
 class EventListener;
 class EventHandlerNonNull;
 template <class T> struct Nullable;
 
 // IID for the dom::EventTarget interface
 #define NS_EVENTTARGET_IID \
-{ 0xce3817d0, 0x177b, 0x402f, \
- { 0xae, 0x75, 0xf8, 0x4e, 0xbe, 0x5a, 0x07, 0xc3 } }
+{ 0x605158a9, 0xe229, 0x45b1, \
+ { 0xbc, 0x12, 0x02, 0x9f, 0xa3, 0xa9, 0x3f, 0xcb } }
 
 class EventTarget : public nsIDOMEventTarget,
                     public nsWrapperCache
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_EVENTTARGET_IID)
 
   // WebIDL API
@@ -64,17 +65,22 @@ public:
 
   // Note, for an event 'foo' aType will be 'onfoo'.
   virtual void EventListenerAdded(nsIAtom* aType) {}
   virtual void EventListenerRemoved(nsIAtom* aType) {}
 
   // Returns an outer window that corresponds to the inner window this event
   // target is associated with.  Will return null if the inner window is not the
   // current inner or if there is no window around at all.
-  virtual nsIDOMWindow* GetOwnerGlobal() = 0;
+  virtual nsIDOMWindow* GetOwnerGlobalForBindings() = 0;
+
+  // The global object this event target is associated with, if any.
+  // This may be an inner window or some other global object.  This
+  // will never be an outer window.
+  virtual nsIGlobalObject* GetOwnerGlobal() const = 0;
 
   /**
    * Get the event listener manager, creating it if it does not already exist.
    */
   virtual EventListenerManager* GetOrCreateListenerManager() = 0;
 
   /**
    * Get the event listener manager, returning null if it does not already
--- a/dom/events/Touch.cpp
+++ b/dom/events/Touch.cpp
@@ -131,27 +131,22 @@ Touch::Equals(Touch* aTouch)
 }
 
 JSObject*
 Touch::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return TouchBinding::Wrap(aCx, this, aGivenProto);
 }
 
-// Parent ourselves to the window of the target. This achieves the desirable
+// Parent ourselves to the global of the target. This achieves the desirable
 // effects of parenting to the target, but avoids making the touch inaccessible
 // when the target happens to be NAC and therefore reflected into the XBL scope.
-EventTarget*
+nsIGlobalObject*
 Touch::GetParentObject()
 {
   if (!mTarget) {
     return nullptr;
   }
-  nsCOMPtr<nsPIDOMWindow> outer = do_QueryInterface(mTarget->GetOwnerGlobal());
-  if (!outer) {
-    return nullptr;
-  }
-  MOZ_ASSERT(outer->IsOuterWindow());
-  return static_cast<nsGlobalWindow*>(outer->GetCurrentInnerWindow());
+  return mTarget->GetOwnerGlobal();
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/events/Touch.h
+++ b/dom/events/Touch.h
@@ -52,17 +52,17 @@ public:
   void InitializePoints(nsPresContext* aPresContext, WidgetEvent* aEvent);
 
   void SetTarget(EventTarget* aTarget);
 
   bool Equals(Touch* aTouch);
 
   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
-  EventTarget* GetParentObject();
+  nsIGlobalObject* GetParentObject();
 
   // WebIDL
   int32_t Identifier() const { return mIdentifier; }
   EventTarget* GetTarget() const;
   int32_t ScreenX() const { return mScreenPoint.x; }
   int32_t ScreenY() const { return mScreenPoint.y; }
   int32_t ClientX() const { return mClientPoint.x; }
   int32_t ClientY() const { return mClientPoint.y; }
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -423,17 +423,18 @@ IndexedDatabaseManager::CommonPostHandle
 
   init.mMessage = errorName;
   init.mCancelable = true;
   init.mBubbles = true;
 
   nsEventStatus status = nsEventStatus_eIgnore;
 
   if (NS_IsMainThread()) {
-    if (nsIDOMWindow* window = eventTarget->GetOwnerGlobal()) {
+    nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(eventTarget->GetOwnerGlobal());
+    if (window) {
       nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(window);
       MOZ_ASSERT(sgo);
 
       if (NS_WARN_IF(NS_FAILED(sgo->HandleScriptError(init, &status)))) {
         status = nsEventStatus_eIgnore;
       }
     } else {
       // We don't fire error events at any global for non-window JS on the main
--- a/dom/webidl/EventTarget.webidl
+++ b/dom/webidl/EventTarget.webidl
@@ -38,11 +38,11 @@ partial interface EventTarget {
   [ChromeOnly]
   EventHandler getEventHandler(DOMString type);
 };
 
 // Mozilla extension to make firing events on event targets from
 // chrome easier.  This returns the window which can be used to create
 // events to fire at this EventTarget, or null if there isn't one.
 partial interface EventTarget {
-  [ChromeOnly, Exposed=Window]
+  [ChromeOnly, Exposed=Window, BinaryName="ownerGlobalForBindings"]
   readonly attribute WindowProxy? ownerGlobal;
 };