Bug 965144. Make the Window-specific bits of XrayWrapper work with WebIDL windows. r=bholley
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 29 Jan 2014 22:34:25 -0800
changeset 181964 78767e93ff146527b5139896888fd897a7d4d277
parent 181963 b9c5659550c67aafa073e6509c4aa014dfd45109
child 181965 af39c4df306ffd7f978d0e0d475e4678aa91f3c8
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs965144
milestone29.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 965144. Make the Window-specific bits of XrayWrapper work with WebIDL windows. r=bholley
js/xpconnect/wrappers/XrayWrapper.cpp
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -1,8 +1,9 @@
+
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=4 sw=4 et tw=99 ft=cpp:
  *
  * 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 "XrayWrapper.h"
@@ -16,16 +17,17 @@
 #include "XPCWrapper.h"
 #include "xpcprivate.h"
 
 #include "jsapi.h"
 #include "jsprf.h"
 #include "nsJSUtils.h"
 
 #include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/WindowBinding.h"
 #include "nsGlobalWindow.h"
 
 using namespace mozilla::dom;
 using namespace JS;
 using namespace mozilla;
 
 using js::Wrapper;
 using js::IsCrossCompartmentWrapper;
@@ -658,30 +660,36 @@ XPCWrappedNativeXrayTraits::resolveDOMCo
     }
 
     if (pobj && !JS_GetPropertyDescriptorById(cx, holder, id, 0, desc))
         return false;
 
     return true;
 }
 
-template <typename T>
-static T*
-As(JSObject *wrapper)
+static nsGlobalWindow*
+AsWindow(JSContext *cx, JSObject *wrapper)
 {
-    XPCWrappedNative *wn = XPCWrappedNativeXrayTraits::getWN(wrapper);
-    nsCOMPtr<T> native = do_QueryWrappedNative(wn);
-    return native;
+  nsGlobalWindow* win;
+  // We want to use our target object here, since we don't want to be
+  // doing a security check while unwrapping.
+  JSObject* target = XrayTraits::getTargetObject(wrapper);
+  nsresult rv = UNWRAP_OBJECT(Window, target, win);
+  if (NS_SUCCEEDED(rv))
+      return win;
+
+  nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(
+      nsContentUtils::XPConnect()->GetNativeOfWrapper(cx, target));
+  return static_cast<nsGlobalWindow*>(piWin.get());
 }
 
-template <typename T>
 static bool
-Is(JSObject *wrapper)
+IsWindow(JSContext *cx, JSObject *wrapper)
 {
-    return !!As<T>(wrapper);
+    return !!AsWindow(cx, wrapper);
 }
 
 static nsQueryInterface
 do_QueryInterfaceNative(JSContext* cx, HandleObject wrapper);
 
 void
 XPCWrappedNativeXrayTraits::preserveWrapper(JSObject *target)
 {
@@ -716,17 +724,17 @@ XPCWrappedNativeXrayTraits::resolveNativ
 
 
     // The |controllers| property is accessible as a [ChromeOnly] property on
     // Window.WebIDL, and [noscript] in XPIDL. Chrome needs to see this over
     // Xray, so we need to special-case it until we move |Window| to WebIDL.
     nsGlobalWindow *win = nullptr;
     if (id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_CONTROLLERS) &&
         AccessCheck::isChrome(wrapper) &&
-        (win = static_cast<nsGlobalWindow*>(As<nsPIDOMWindow>(wrapper))))
+        (win = AsWindow(cx, wrapper)))
     {
         nsCOMPtr<nsIControllers> c;
         nsresult rv = win->GetControllers(getter_AddRefs(c));
         if (NS_SUCCEEDED(rv) && c) {
             rv = nsXPConnect::XPConnect()->WrapNativeToJSVal(cx, CurrentGlobalOrNull(cx),
                                                              c, nullptr, nullptr, true,
                                                              desc.value());
         }
@@ -884,32 +892,31 @@ XPCWrappedNativeXrayTraits::resolveOwnPr
     bool ok = XrayTraits::resolveOwnProperty(cx, jsWrapper, wrapper, holder,
                                              id, desc, flags);
     if (!ok || desc.object())
         return ok;
 
     // Check for indexed access on a window.
     int32_t index = GetArrayIndexFromId(cx, id);
     if (IsArrayIndex(index)) {
-        nsGlobalWindow* win =
-            static_cast<nsGlobalWindow*>(As<nsPIDOMWindow>(wrapper));
+        nsGlobalWindow* win = AsWindow(cx, wrapper);
         // Note: As() unwraps outer windows to get to the inner window.
         if (win) {
             bool unused;
             nsCOMPtr<nsIDOMWindow> subframe = win->IndexedGetter(index, unused);
             if (subframe) {
                 nsGlobalWindow* global = static_cast<nsGlobalWindow*>(subframe.get());
                 global->EnsureInnerWindow();
                 JSObject* obj = global->FastGetGlobalJSObject();
                 if (MOZ_UNLIKELY(!obj)) {
                     // It's gone?
                     return xpc::Throw(cx, NS_ERROR_FAILURE);
                 }
                 desc.value().setObject(*obj);
-                mozilla::dom::FillPropertyDescriptor(desc, wrapper, true);
+                FillPropertyDescriptor(desc, wrapper, true);
                 return JS_WrapPropertyDescriptor(cx, desc);
             }
         }
     }
 
     // Xray wrappers don't use the regular wrapper hierarchy, so we should be
     // in the wrapper's compartment here, not the wrappee.
     MOZ_ASSERT(js::IsObjectInContextCompartment(wrapper, cx));
@@ -974,17 +981,17 @@ XPCWrappedNativeXrayTraits::defineProper
         *defined = true;
         return JS_DefinePropertyById(cx, holder, id, desc.value(), desc.getter(), desc.setter(),
                                      desc.attributes());
     }
 
     // Check for an indexed property on a Window.  If that's happening, do
     // nothing but claim we defined it so it won't get added as an expando.
     int32_t index = GetArrayIndexFromId(cx, id);
-    if (IsArrayIndex(index) && Is<nsIDOMWindow>(wrapper)) {
+    if (IsArrayIndex(index) && IsWindow(cx, wrapper)) {
         *defined = true;
         return true;
     }
 
     return true;
 }
 
 bool
@@ -1097,16 +1104,39 @@ DOMXrayTraits::resolveOwnProperty(JSCont
                                   MutableHandle<JSPropertyDescriptor> desc, unsigned flags)
 {
     // Call the common code.
     bool ok = XrayTraits::resolveOwnProperty(cx, jsWrapper, wrapper, holder,
                                              id, desc, flags);
     if (!ok || desc.object())
         return ok;
 
+    // Check for indexed access on a window.
+    int32_t index = GetArrayIndexFromId(cx, id);
+    if (IsArrayIndex(index)) {
+        nsGlobalWindow* win = AsWindow(cx, wrapper);
+        // Note: As() unwraps outer windows to get to the inner window.
+        if (win) {
+            bool unused;
+            nsCOMPtr<nsIDOMWindow> subframe = win->IndexedGetter(index, unused);
+            if (subframe) {
+                nsGlobalWindow* global = static_cast<nsGlobalWindow*>(subframe.get());
+                global->EnsureInnerWindow();
+                JSObject* obj = global->FastGetGlobalJSObject();
+                if (MOZ_UNLIKELY(!obj)) {
+                    // It's gone?
+                    return xpc::Throw(cx, NS_ERROR_FAILURE);
+                }
+                desc.value().setObject(*obj);
+                FillPropertyDescriptor(desc, wrapper, true);
+                return JS_WrapPropertyDescriptor(cx, desc);
+            }
+        }
+    }
+
     RootedObject obj(cx, getTargetObject(wrapper));
     if (!XrayResolveOwnProperty(cx, wrapper, obj, id, desc, flags))
         return false;
 
     MOZ_ASSERT(!desc.object() || desc.object() == wrapper, "What did we resolve this on?");
 
     return true;
 }
@@ -1114,16 +1144,24 @@ DOMXrayTraits::resolveOwnProperty(JSCont
 bool
 DOMXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
                               MutableHandle<JSPropertyDescriptor> desc,
                               Handle<JSPropertyDescriptor> existingDesc, bool *defined)
 {
     if (!existingDesc.object())
         return true;
 
+    // Check for an indexed property on a Window.  If that's happening, do
+    // nothing but claim we defined it so it won't get added as an expando.
+    int32_t index = GetArrayIndexFromId(cx, id);
+    if (IsArrayIndex(index) && IsWindow(cx, wrapper)) {
+        *defined = true;
+        return true;
+    }
+
     JS::Rooted<JSObject*> obj(cx, getTargetObject(wrapper));
     return XrayDefineProperty(cx, wrapper, obj, id, desc, defined);
 }
 
 bool
 DOMXrayTraits::enumerateNames(JSContext *cx, HandleObject wrapper, unsigned flags,
                               AutoIdVector &props)
 {
@@ -1465,30 +1503,28 @@ XrayWrapper<Base, Traits>::getPropertyDe
     // We need to handle named access on the Window somewhere other than
     // Traits::resolveOwnProperty, because per spec it happens on the Global
     // Scope Polluter and thus the resulting properties are non-|own|. However,
     // we're set up (above) to cache (on the holder) anything that comes out of
     // resolveNativeProperty, which we don't want for something dynamic like
     // named access. So we just handle it separately here.
     nsGlobalWindow *win = nullptr;
     if (!desc.object() &&
-        (Traits::Type == XrayForWrappedNative) &&
         JSID_IS_STRING(id) &&
-        (win = static_cast<nsGlobalWindow*>(As<nsPIDOMWindow>(wrapper))))
+        (win = AsWindow(cx, wrapper)))
     {
         nsDependentJSString name(id);
         nsCOMPtr<nsIDOMWindow> childDOMWin = win->GetChildWindow(name);
         if (childDOMWin) {
             nsGlobalWindow *cwin = static_cast<nsGlobalWindow*>(childDOMWin.get());
             JSObject *childObj = cwin->FastGetGlobalJSObject();
             if (MOZ_UNLIKELY(!childObj))
                 return xpc::Throw(cx, NS_ERROR_FAILURE);
-            mozilla::dom::FillPropertyDescriptor(desc, wrapper,
-                                                 ObjectValue(*childObj),
-                                                 /* readOnly = */ true);
+            FillPropertyDescriptor(desc, wrapper, ObjectValue(*childObj),
+                                   /* readOnly = */ true);
             return JS_WrapPropertyDescriptor(cx, desc);
         }
     }
 
     if (!desc.object() &&
         id == nsXPConnect::GetRuntimeInstance()->GetStringID(XPCJSRuntime::IDX_TO_STRING))
     {