From fffb30ddd3263f4f58f41f17c2c2885d6cab82a6 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 29 Jan 2014 22:34:25 -0800 Subject: [PATCH] Bug 965144. Make the Window-specific bits of XrayWrapper work with WebIDL windows. r=bholley --- js/xpconnect/wrappers/XrayWrapper.cpp | 74 ++++++++++++++++++++------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/js/xpconnect/wrappers/XrayWrapper.cpp b/js/xpconnect/wrappers/XrayWrapper.cpp index efa48edc219..7b7d1565030 100644 --- a/js/xpconnect/wrappers/XrayWrapper.cpp +++ b/js/xpconnect/wrappers/XrayWrapper.cpp @@ -1,3 +1,4 @@ + /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=4 sw=4 et tw=99 ft=cpp: * @@ -21,6 +22,7 @@ #include "nsJSUtils.h" #include "mozilla/dom/BindingUtils.h" +#include "mozilla/dom/WindowBinding.h" #include "nsGlobalWindow.h" using namespace mozilla::dom; @@ -663,20 +665,26 @@ XPCWrappedNativeXrayTraits::resolveDOMCollectionProperty(JSContext *cx, HandleOb return true; } -template -static T* -As(JSObject *wrapper) +static nsGlobalWindow* +AsWindow(JSContext *cx, JSObject *wrapper) { - XPCWrappedNative *wn = XPCWrappedNativeXrayTraits::getWN(wrapper); - nsCOMPtr 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 piWin = do_QueryInterface( + nsContentUtils::XPConnect()->GetNativeOfWrapper(cx, target)); + return static_cast(piWin.get()); } -template static bool -Is(JSObject *wrapper) +IsWindow(JSContext *cx, JSObject *wrapper) { - return !!As(wrapper); + return !!AsWindow(cx, wrapper); } static nsQueryInterface @@ -721,7 +729,7 @@ XPCWrappedNativeXrayTraits::resolveNativeProperty(JSContext *cx, HandleObject wr nsGlobalWindow *win = nullptr; if (id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_CONTROLLERS) && AccessCheck::isChrome(wrapper) && - (win = static_cast(As(wrapper)))) + (win = AsWindow(cx, wrapper))) { nsCOMPtr c; nsresult rv = win->GetControllers(getter_AddRefs(c)); @@ -889,8 +897,7 @@ XPCWrappedNativeXrayTraits::resolveOwnProperty(JSContext *cx, Wrapper &jsWrapper // Check for indexed access on a window. int32_t index = GetArrayIndexFromId(cx, id); if (IsArrayIndex(index)) { - nsGlobalWindow* win = - static_cast(As(wrapper)); + nsGlobalWindow* win = AsWindow(cx, wrapper); // Note: As() unwraps outer windows to get to the inner window. if (win) { bool unused; @@ -904,7 +911,7 @@ XPCWrappedNativeXrayTraits::resolveOwnProperty(JSContext *cx, Wrapper &jsWrapper 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); } } @@ -979,7 +986,7 @@ XPCWrappedNativeXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, // 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(wrapper)) { + if (IsArrayIndex(index) && IsWindow(cx, wrapper)) { *defined = true; return true; } @@ -1102,6 +1109,29 @@ DOMXrayTraits::resolveOwnProperty(JSContext *cx, Wrapper &jsWrapper, HandleObjec 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 subframe = win->IndexedGetter(index, unused); + if (subframe) { + nsGlobalWindow* global = static_cast(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; @@ -1119,6 +1149,14 @@ DOMXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id, 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 obj(cx, getTargetObject(wrapper)); return XrayDefineProperty(cx, wrapper, obj, id, desc, defined); } @@ -1470,9 +1508,8 @@ XrayWrapper::getPropertyDescriptor(JSContext *cx, HandleObject wra // 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(As(wrapper)))) + (win = AsWindow(cx, wrapper))) { nsDependentJSString name(id); nsCOMPtr childDOMWin = win->GetChildWindow(name); @@ -1481,9 +1518,8 @@ XrayWrapper::getPropertyDescriptor(JSContext *cx, HandleObject wra 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); } }