зеркало из https://github.com/mozilla/gecko-dev.git
Bug 989584. Allow sites to set window.opener to any value. r=peterv
This commit is contained in:
Родитель
4b32240082
Коммит
da05bf53a8
|
@ -4339,13 +4339,7 @@ nsGlobalWindow::GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& aNames,
|
|||
nsGlobalWindow::IsChromeWindow(JSContext* aCx, JSObject* aObj)
|
||||
{
|
||||
// For now, have to deal with XPConnect objects here.
|
||||
nsGlobalWindow* win;
|
||||
nsresult rv = UNWRAP_OBJECT(Window, aObj, win);
|
||||
if (NS_FAILED(rv)) {
|
||||
nsCOMPtr<nsPIDOMWindow> piWin = do_QueryWrapper(aCx, aObj);
|
||||
win = static_cast<nsGlobalWindow*>(piWin.get());
|
||||
}
|
||||
return win->IsChromeWindow();
|
||||
return xpc::WindowOrNull(aObj)->IsChromeWindow();
|
||||
}
|
||||
|
||||
nsIDOMOfflineResourceList*
|
||||
|
@ -4471,9 +4465,9 @@ nsGlobalWindow::GetControllers(nsIControllers** aResult)
|
|||
}
|
||||
|
||||
nsIDOMWindow*
|
||||
nsGlobalWindow::GetOpener(ErrorResult& aError)
|
||||
nsGlobalWindow::GetOpenerWindow(ErrorResult& aError)
|
||||
{
|
||||
FORWARD_TO_OUTER_OR_THROW(GetOpener, (aError), aError, nullptr);
|
||||
FORWARD_TO_OUTER_OR_THROW(GetOpenerWindow, (aError), aError, nullptr);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> opener = do_QueryReferent(mOpener);
|
||||
if (!opener) {
|
||||
|
@ -4512,18 +4506,41 @@ nsGlobalWindow::GetOpener(ErrorResult& aError)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
JS::Value
|
||||
nsGlobalWindow::GetOpener(JSContext* aCx, ErrorResult& aError)
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindow> opener = GetOpenerWindow(aError);
|
||||
if (aError.Failed() || !opener) {
|
||||
return JS::NullValue();
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> val(aCx);
|
||||
aError = nsContentUtils::WrapNative(aCx, opener, &val);
|
||||
return val;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::GetOpener(nsIDOMWindow** aOpener)
|
||||
nsGlobalWindow::GetScriptableOpener(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aOpener)
|
||||
{
|
||||
ErrorResult rv;
|
||||
nsCOMPtr<nsIDOMWindow> opener = GetOpener(rv);
|
||||
opener.forget(aOpener);
|
||||
aOpener.set(GetOpener(aCx, rv));
|
||||
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::GetOpener(nsIDOMWindow** aOpener)
|
||||
{
|
||||
ErrorResult rv;
|
||||
nsCOMPtr<nsIDOMWindow> opener = GetOpenerWindow(rv);
|
||||
opener.forget(aOpener);
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::SetOpener(nsIDOMWindow* aOpener, ErrorResult& aError)
|
||||
nsGlobalWindow::SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
|
||||
ErrorResult& aError)
|
||||
{
|
||||
// Check if we were called from a privileged chrome script. If not, and if
|
||||
// aOpener is not null, just define aOpener on our inner window's JS object,
|
||||
|
@ -4531,35 +4548,15 @@ nsGlobalWindow::SetOpener(nsIDOMWindow* aOpener, ErrorResult& aError)
|
|||
// Xray expando object, but don't set it on the outer window, so that it'll
|
||||
// get reset on navigation. This is just like replaceable properties, but
|
||||
// we're not quite readonly.
|
||||
if (aOpener && !nsContentUtils::IsCallerChrome()) {
|
||||
// JS_WrapObject will outerize, so we don't care if aOpener is an inner.
|
||||
nsCOMPtr<nsIGlobalObject> glob = do_QueryInterface(aOpener);
|
||||
if (!glob) {
|
||||
aError.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
AutoJSContext cx;
|
||||
JSAutoRequest ar(cx);
|
||||
// Note we explicitly do NOT enter any particular compartment here; we want
|
||||
// the caller compartment in cases when we have a caller, so that we define
|
||||
// expandos on Xrays as needed.
|
||||
|
||||
JS::Rooted<JSObject*> otherObj(cx, glob->GetGlobalJSObject());
|
||||
if (!otherObj) {
|
||||
aError.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> thisObj(cx, GetWrapperPreserveColor());
|
||||
if (!aOpener.isNull() && !nsContentUtils::IsCallerChrome()) {
|
||||
JS::Rooted<JSObject*> thisObj(aCx, GetWrapperPreserveColor());
|
||||
if (!thisObj) {
|
||||
aError.Throw(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!JS_WrapObject(cx, &otherObj) ||
|
||||
!JS_WrapObject(cx, &thisObj) ||
|
||||
!JS_DefineProperty(cx, thisObj, "opener", otherObj, JSPROP_ENUMERATE,
|
||||
if (!JS_WrapObject(aCx, &thisObj) ||
|
||||
!JS_DefineProperty(aCx, thisObj, "opener", aOpener, JSPROP_ENUMERATE,
|
||||
JS_PropertyStub, JS_StrictPropertyStub)) {
|
||||
aError.Throw(NS_ERROR_FAILURE);
|
||||
}
|
||||
|
@ -4567,16 +4564,47 @@ nsGlobalWindow::SetOpener(nsIDOMWindow* aOpener, ErrorResult& aError)
|
|||
return;
|
||||
}
|
||||
|
||||
SetOpenerWindow(aOpener, false);
|
||||
if (!aOpener.isObjectOrNull()) {
|
||||
// Chrome code trying to set some random value as opener
|
||||
aError.Throw(NS_ERROR_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
|
||||
nsGlobalWindow* win = nullptr;
|
||||
if (aOpener.isObject()) {
|
||||
JSObject* unwrapped = js::CheckedUnwrap(&aOpener.toObject(),
|
||||
/* stopAtOuter = */ false);
|
||||
if (!unwrapped) {
|
||||
aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
win = xpc::WindowOrNull(unwrapped);
|
||||
if (!win) {
|
||||
// Wasn't a window
|
||||
aError.Throw(NS_ERROR_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SetOpenerWindow(win, false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::SetScriptableOpener(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aOpener)
|
||||
{
|
||||
ErrorResult rv;
|
||||
SetOpener(aCx, aOpener, rv);
|
||||
|
||||
return rv.ErrorCode();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalWindow::SetOpener(nsIDOMWindow* aOpener)
|
||||
{
|
||||
ErrorResult rv;
|
||||
SetOpener(aOpener, rv);
|
||||
|
||||
return rv.ErrorCode();
|
||||
SetOpenerWindow(aOpener, false);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -13699,13 +13727,7 @@ bool
|
|||
nsGlobalWindow::IsModalContentWindow(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
// For now, have to deal with XPConnect objects here.
|
||||
nsGlobalWindow* win;
|
||||
nsresult rv = UNWRAP_OBJECT(Window, aGlobal, win);
|
||||
if (NS_FAILED(rv)) {
|
||||
nsCOMPtr<nsPIDOMWindow> piWin = do_QueryWrapper(aCx, aGlobal);
|
||||
win = static_cast<nsGlobalWindow*>(piWin.get());
|
||||
}
|
||||
return win->IsModalContentWindow();
|
||||
return xpc::WindowOrNull(aGlobal)->IsModalContentWindow();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -836,8 +836,12 @@ public:
|
|||
aError = GetScriptableTop(getter_AddRefs(top));
|
||||
return top.forget();
|
||||
}
|
||||
nsIDOMWindow* GetOpener(mozilla::ErrorResult& aError);
|
||||
void SetOpener(nsIDOMWindow* aOpener, mozilla::ErrorResult& aError);
|
||||
protected:
|
||||
nsIDOMWindow* GetOpenerWindow(mozilla::ErrorResult& aError);
|
||||
public:
|
||||
JS::Value GetOpener(JSContext* aCx, mozilla::ErrorResult& aError);
|
||||
void SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
|
||||
mozilla::ErrorResult& aError);
|
||||
using nsIDOMWindow::GetParent;
|
||||
already_AddRefed<nsIDOMWindow> GetParent(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::Element* GetFrameElement(mozilla::ErrorResult& aError);
|
||||
|
|
|
@ -59,6 +59,25 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=868996
|
|||
is(evalsb("win.opener", sb2), window,
|
||||
"Navigating a window should have reset the opener in sb2");
|
||||
|
||||
win.opener = 5;
|
||||
evalsb("win.opener = 5", sb1);
|
||||
evalsb("win.opener = 5", sb2);
|
||||
is(win.opener, 5, "Should be able to set an opener to a primitive");
|
||||
is(evalsb("win.opener", sb1), 5,
|
||||
"Should be able to set the opener to a primitive in a sandbox one");
|
||||
is(evalsb("win.opener", sb2), 5,
|
||||
"Should be able to set the opener to a primitive in a sandbox two");
|
||||
win.location = "data:text/html,<script>opener.setTimeout(opener.continueOpenerTest2, 0, this);</" + "script>";
|
||||
}
|
||||
|
||||
function continueOpenerTest2(win) {
|
||||
is(win.opener, window,
|
||||
"Navigating a window again should have reset the opener we stashed on it temporarily");
|
||||
is(evalsb("win.opener", sb1), window,
|
||||
"Navigating a window again should have reset the opener in sb1");
|
||||
is(evalsb("win.opener", sb2), window,
|
||||
"Navigating a window again should have reset the opener in sb2");
|
||||
|
||||
win.opener = null;
|
||||
is(win.opener, null, "Should be able to set the opener to null");
|
||||
is(evalsb("win.opener", sb1), null,
|
||||
|
|
|
@ -24,7 +24,7 @@ interface nsIVariant;
|
|||
* @see <http://www.whatwg.org/html/#window>
|
||||
*/
|
||||
|
||||
[scriptable, uuid(fbefa573-0ba2-4d15-befb-d60277643a0b)]
|
||||
[scriptable, uuid(d4316591-d16e-405c-8093-b441cbef3230)]
|
||||
interface nsIDOMWindow : nsISupports
|
||||
{
|
||||
// the current browsing context
|
||||
|
@ -151,7 +151,11 @@ interface nsIDOMWindow : nsISupports
|
|||
}
|
||||
%}
|
||||
|
||||
attribute nsIDOMWindow opener;
|
||||
[implicit_jscontext, binaryname(ScriptableOpener)]
|
||||
attribute jsval opener;
|
||||
|
||||
[noscript, binaryname(Opener)]
|
||||
attribute nsIDOMWindow openerWindow;
|
||||
|
||||
/**
|
||||
* |frameElement| gets this window's <iframe> or <frame> element, if it has
|
||||
|
|
|
@ -54,7 +54,7 @@ typedef any Transferable;
|
|||
[Replaceable, CrossOriginReadable] readonly attribute unsigned long length;
|
||||
//[Unforgeable, Throws, CrossOriginReadable] readonly attribute WindowProxy top;
|
||||
[Unforgeable, Throws, CrossOriginReadable] readonly attribute WindowProxy? top;
|
||||
[Throws, CrossOriginReadable] attribute WindowProxy? opener;
|
||||
[Throws, CrossOriginReadable] attribute any opener;
|
||||
//[Throws] readonly attribute WindowProxy parent;
|
||||
[Replaceable, Throws, CrossOriginReadable] readonly attribute WindowProxy? parent;
|
||||
[Throws] readonly attribute Element? frameElement;
|
||||
|
|
Загрузка…
Ссылка в новой задаче