Bug 965144. Make the Window-specific bits of XrayWrapper work with WebIDL windows. r=bholley

This commit is contained in:
Boris Zbarsky 2014-01-29 22:34:25 -08:00
parent 0b37a69f1e
commit fffb30ddd3

View File

@ -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 <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
@ -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<nsGlobalWindow*>(As<nsPIDOMWindow>(wrapper))))
(win = AsWindow(cx, wrapper)))
{
nsCOMPtr<nsIControllers> 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<nsGlobalWindow*>(As<nsPIDOMWindow>(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<nsIDOMWindow>(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<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;
@ -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<JSObject*> obj(cx, getTargetObject(wrapper));
return XrayDefineProperty(cx, wrapper, obj, id, desc, defined);
}
@ -1470,9 +1508,8 @@ XrayWrapper<Base, Traits>::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<nsGlobalWindow*>(As<nsPIDOMWindow>(wrapper))))
(win = AsWindow(cx, wrapper)))
{
nsDependentJSString name(id);
nsCOMPtr<nsIDOMWindow> childDOMWin = win->GetChildWindow(name);
@ -1481,9 +1518,8 @@ XrayWrapper<Base, Traits>::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);
}
}