diff --git a/content/xbl/src/nsXBLDocumentInfo.cpp b/content/xbl/src/nsXBLDocumentInfo.cpp index 7126fcf4b246..f36bae125e6b 100644 --- a/content/xbl/src/nsXBLDocumentInfo.cpp +++ b/content/xbl/src/nsXBLDocumentInfo.cpp @@ -76,7 +76,6 @@ public: virtual JSObject *GetGlobalJSObject(); virtual void OnFinalize(PRUint32 aLangID, void *aScriptGlobal); virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts); - virtual nsresult SetNewArguments(nsIArray *aArguments); // nsIScriptObjectPrincipal methods virtual nsIPrincipal* GetPrincipal(); @@ -393,13 +392,6 @@ nsXBLDocGlobalObject::SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts) // We don't care... } -nsresult -nsXBLDocGlobalObject::SetNewArguments(nsIArray *aArguments) -{ - NS_NOTREACHED("waaah!"); - return NS_ERROR_UNEXPECTED; -} - //---------------------------------------------------------------------- // // nsIScriptObjectPrincipal methods diff --git a/content/xul/document/src/nsXULPrototypeDocument.cpp b/content/xul/document/src/nsXULPrototypeDocument.cpp index 394cad57f61d..e0aa67030337 100644 --- a/content/xul/document/src/nsXULPrototypeDocument.cpp +++ b/content/xul/document/src/nsXULPrototypeDocument.cpp @@ -81,7 +81,6 @@ public: // nsIScriptGlobalObject methods virtual void OnFinalize(PRUint32 aLangID, void *aGlobal); virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts); - virtual nsresult SetNewArguments(nsIArray *aArguments); virtual void *GetScriptGlobal(PRUint32 lang); virtual nsresult EnsureScriptEnvironment(PRUint32 aLangID); @@ -809,13 +808,6 @@ nsXULPDGlobalObject::SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts) // We don't care... } -nsresult -nsXULPDGlobalObject::SetNewArguments(nsIArray *aArguments) -{ - NS_NOTREACHED("waaah!"); - return NS_ERROR_UNEXPECTED; -} - //---------------------------------------------------------------------- // // nsIScriptObjectPrincipal methods diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index e515a3b62291..45293fe29c67 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -1376,6 +1376,7 @@ jsval nsDOMClassInfo::sToolbar_id = JSVAL_VOID; jsval nsDOMClassInfo::sLocationbar_id = JSVAL_VOID; jsval nsDOMClassInfo::sPersonalbar_id = JSVAL_VOID; jsval nsDOMClassInfo::sStatusbar_id = JSVAL_VOID; +jsval nsDOMClassInfo::sDialogArguments_id = JSVAL_VOID; jsval nsDOMClassInfo::sDirectories_id = JSVAL_VOID; jsval nsDOMClassInfo::sControllers_id = JSVAL_VOID; jsval nsDOMClassInfo::sLength_id = JSVAL_VOID; @@ -1571,6 +1572,7 @@ nsDOMClassInfo::DefineStaticJSVals(JSContext *cx) SET_JSVAL_TO_STRING(sLocationbar_id, cx, "locationbar"); SET_JSVAL_TO_STRING(sPersonalbar_id, cx, "personalbar"); SET_JSVAL_TO_STRING(sStatusbar_id, cx, "statusbar"); + SET_JSVAL_TO_STRING(sDialogArguments_id, cx, "dialogArguments"); SET_JSVAL_TO_STRING(sDirectories_id, cx, "directories"); SET_JSVAL_TO_STRING(sControllers_id, cx, "controllers"); SET_JSVAL_TO_STRING(sLength_id, cx, "length"); @@ -4322,6 +4324,7 @@ nsDOMClassInfo::ShutDown() sLocationbar_id = JSVAL_VOID; sPersonalbar_id = JSVAL_VOID; sStatusbar_id = JSVAL_VOID; + sDialogArguments_id = JSVAL_VOID; sDirectories_id = JSVAL_VOID; sControllers_id = JSVAL_VOID; sLength_id = JSVAL_VOID; @@ -6555,6 +6558,24 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, return NS_OK; } } + } else if (id == sDialogArguments_id && + mData == &sClassInfoData[eDOMClassInfo_ModalContentWindow_id]) { + nsCOMPtr args; + ((nsGlobalModalWindow *)win)->GetDialogArguments(getter_AddRefs(args)); + + nsIScriptContext *script_cx = win->GetContext(); + if (script_cx) { + JSAutoSuspendRequest asr(cx); + + // Make nsJSContext::SetProperty()'s magic argument array + // handling happen. + rv = script_cx->SetProperty(obj, "dialogArguments", args); + NS_ENSURE_SUCCESS(rv, rv); + + *objp = obj; + } + + return NS_OK; } } @@ -6571,8 +6592,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, // binding a name) a new undefined property that's not already // defined on our prototype chain. This way we can access this // expando w/o ever getting back into XPConnect. - if ((flags & JSRESOLVE_ASSIGNING) && - !(flags & JSRESOLVE_WITH) && + if ((flags & JSRESOLVE_ASSIGNING) && !(flags & JSRESOLVE_WITH) && win->IsInnerWindow()) { JSObject *realObj; wrapper->GetJSObject(&realObj); @@ -9474,7 +9494,10 @@ nsHTMLPluginObjElementSH::PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *obj) { if (nsContentUtils::IsSafeToRunScript()) { - nsresult rv = SetupProtoChain(wrapper, cx, obj); +#ifdef DEBUG + nsresult rv = +#endif + SetupProtoChain(wrapper, cx, obj); // If SetupProtoChain failed then we're in real trouble. We're about to fail // PostCreate but it's more than likely that we handed our (now invalid) diff --git a/dom/base/nsDOMClassInfo.h b/dom/base/nsDOMClassInfo.h index bf9fc3178314..1b326cd8aa9f 100644 --- a/dom/base/nsDOMClassInfo.h +++ b/dom/base/nsDOMClassInfo.h @@ -284,6 +284,7 @@ protected: static jsval sLocationbar_id; static jsval sPersonalbar_id; static jsval sStatusbar_id; + static jsval sDialogArguments_id; static jsval sDirectories_id; static jsval sControllers_id; static jsval sLength_id; diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 8034d7371a00..dd28a7924122 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -895,6 +895,7 @@ nsGlobalWindow::CleanUp() } mArguments = nsnull; mArgumentsLast = nsnull; + mArgumentsOrigin = nsnull; CleanupCachedXBLHandlers(this); @@ -1194,7 +1195,7 @@ nsGlobalWindow::SetScriptContext(PRUint32 lang_id, nsIScriptContext *aScriptCont NS_ASSERTION(script_glob, "GetNativeGlobal returned NULL!"); } // for now, keep mContext real. - if (lang_id==nsIProgrammingLanguage::JAVASCRIPT) { + if (lang_id == nsIProgrammingLanguage::JAVASCRIPT) { mContext = aScriptContext; mJSObject = (JSObject *)script_glob; } @@ -2024,8 +2025,12 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument, } if (mArguments) { - newInnerWindow->SetNewArguments(mArguments); + newInnerWindow->DefineArgumentsProperty(mArguments); + newInnerWindow->mArguments = mArguments; + newInnerWindow->mArgumentsOrigin = mArgumentsOrigin; + mArguments = nsnull; + mArgumentsOrigin = nsnull; } // Give the new inner window our chrome event handler (since it @@ -2109,9 +2114,10 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell) if (mArguments) { // We got no new document after someone called - // SetNewArguments(), drop our reference to the arguments. + // SetArguments(), drop our reference to the arguments. mArguments = nsnull; - // xxxmarkh - should we also drop mArgumentsLast? + mArgumentsLast = nsnull; + mArgumentsOrigin = nsnull; } PRUint32 st_ndx; @@ -2364,41 +2370,52 @@ nsGlobalWindow::SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts) } nsresult -nsGlobalWindow::SetNewArguments(nsIArray *aArguments) +nsGlobalWindow::SetArguments(nsIArray *aArguments, nsIPrincipal *aOrigin) { - FORWARD_TO_OUTER(SetNewArguments, (aArguments), NS_ERROR_NOT_INITIALIZED); - - JSContext *cx; - NS_ENSURE_TRUE(aArguments && mContext && - (cx = (JSContext *)mContext->GetNativeContext()), - NS_ERROR_NOT_INITIALIZED); - - // Note that currentInner may be non-null if someone's doing a - // window.open with an existing window name. - nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal(); - - nsresult rv; - - if (currentInner) { - PRUint32 langID; - NS_STID_FOR_ID(langID) { - void *glob = currentInner->GetScriptGlobal(langID); - nsIScriptContext *ctx = GetScriptContext(langID); - if (glob && ctx) { - if (mIsModalContentWindow) { - rv = ctx->SetProperty(glob, "dialogArguments", aArguments); - } else { - rv = ctx->SetProperty(glob, "arguments", aArguments); - } - NS_ENSURE_SUCCESS(rv, rv); - } - } - } + FORWARD_TO_OUTER(SetArguments, (aArguments, aOrigin), + NS_ERROR_NOT_INITIALIZED); // Hold on to the arguments so that we can re-set them once the next // document is loaded. mArguments = aArguments; - mArgumentsLast = aArguments; + mArgumentsOrigin = aOrigin; + + if (!mIsModalContentWindow) { + mArgumentsLast = aArguments; + } + + nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal(); + + return currentInner ? + currentInner->DefineArgumentsProperty(aArguments) : NS_OK; +} + +nsresult +nsGlobalWindow::DefineArgumentsProperty(nsIArray *aArguments) +{ + JSContext *cx; + nsIScriptContext *ctx = GetOuterWindowInternal()->mContext; + NS_ENSURE_TRUE(aArguments && ctx && + (cx = (JSContext *)ctx->GetNativeContext()), + NS_ERROR_NOT_INITIALIZED); + + if (mIsModalContentWindow) { + // Modal content windows don't have an "arguments" property, they + // have a "dialogArguments" property which is handled + // separately. See nsWindowSH::NewResolve(). + + return NS_OK; + } + + PRUint32 langID; + NS_STID_FOR_ID(langID) { + void *glob = GetScriptGlobal(langID); + ctx = GetScriptContext(langID); + if (glob && ctx) { + nsresult rv = ctx->SetProperty(glob, "arguments", aArguments); + NS_ENSURE_SUCCESS(rv, rv); + } + } return NS_OK; } @@ -6087,14 +6104,42 @@ nsGlobalWindow::ShowModalDialog(const nsAString& aURI, nsIVariant *aArgs, NS_ENSURE_SUCCESS(rv, rv); if (dlgWin) { - nsCOMPtr win(do_QueryInterface(dlgWin)); + nsCOMPtr subjectPrincipal; + rv = nsContentUtils::GetSecurityManager()-> + GetSubjectPrincipal(getter_AddRefs(subjectPrincipal)); + if (NS_FAILED(rv)) { + return rv; + } - nsPIDOMWindow *inner = win->GetCurrentInnerWindow(); + PRBool canAccess = PR_TRUE; - nsCOMPtr dlgInner(do_QueryInterface(inner)); + if (subjectPrincipal) { + nsCOMPtr objPrincipal = + do_QueryInterface(dlgWin); + nsCOMPtr dialogPrincipal; - if (dlgInner) { - dlgInner->GetReturnValue(aRetVal); + if (objPrincipal) { + dialogPrincipal = objPrincipal->GetPrincipal(); + + rv = subjectPrincipal->Subsumes(dialogPrincipal, &canAccess); + NS_ENSURE_SUCCESS(rv, rv); + } else { + // Uh, not sure what kind of dialog this is. Prevent access to + // be on the safe side... + + canAccess = PR_FALSE; + } + } + + if (canAccess) { + nsCOMPtr win(do_QueryInterface(dlgWin)); + nsPIDOMWindow *inner = win->GetCurrentInnerWindow(); + + nsCOMPtr dlgInner(do_QueryInterface(inner)); + + if (dlgInner) { + dlgInner->GetReturnValue(aRetVal); + } } } @@ -7388,7 +7433,7 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName, "Shouldn't have caller context when called noscript"); *aReturn = nsnull; - + nsCOMPtr chrome; GetWebBrowserChrome(getter_AddRefs(chrome)); if (!chrome) { @@ -9023,7 +9068,14 @@ nsGlobalModalWindow::GetDialogArguments(nsIArray **aArguments) FORWARD_TO_INNER_MODAL_CONTENT_WINDOW(GetDialogArguments, (aArguments), NS_ERROR_NOT_INITIALIZED); - *aArguments = mArguments; + PRBool subsumes = PR_FALSE; + nsIPrincipal *self = GetPrincipal(); + if (self && NS_SUCCEEDED(self->Subsumes(mArgumentsOrigin, &subsumes)) && + subsumes) { + NS_IF_ADDREF(*aArguments = mArguments); + } else { + *aArguments = nsnull; + } return NS_OK; } @@ -9048,6 +9100,20 @@ nsGlobalModalWindow::SetReturnValue(nsIVariant *aRetVal) return NS_OK; } +nsresult +nsGlobalModalWindow::SetNewDocument(nsIDocument *aDocument, + nsISupports *aState, + PRBool aClearScopeHint) +{ + // If we're loading a new document into a modal dialog, clear the + // return value that was set, if any, by the current document. + if (aDocument) { + mReturnValue = nsnull; + } + + return nsGlobalWindow::SetNewDocument(aDocument, aState, aClearScopeHint); +} + //***************************************************************************** // nsGlobalWindow: Creator Function (This should go away) //***************************************************************************** diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 94d789dacbc9..33ffdd2e4116 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -261,7 +261,6 @@ public: virtual void OnFinalize(PRUint32 aLangID, void *aScriptGlobal); virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts); - virtual nsresult SetNewArguments(nsIArray *aArguments); // nsIScriptObjectPrincipal virtual nsIPrincipal* GetPrincipal(); @@ -338,8 +337,8 @@ public: virtual NS_HIDDEN_(void) SetDocShell(nsIDocShell* aDocShell); virtual NS_HIDDEN_(nsresult) SetNewDocument(nsIDocument *aDocument, - nsISupports *aState, - PRBool aClearScopeHint); + nsISupports *aState, + PRBool aClearScopeHint); virtual NS_HIDDEN_(void) SetOpenerWindow(nsIDOMWindowInternal *aOpener, PRBool aOriginalOpener); virtual NS_HIDDEN_(void) EnsureSizeUpToDate(); @@ -447,6 +446,7 @@ public: virtual void SetReadyForFocus(); virtual void PageHidden(); virtual nsresult DispatchAsyncHashchange(); + virtual nsresult SetArguments(nsIArray *aArguments, nsIPrincipal *aOrigin); static PRBool DOMWindowDumpEnabled(); @@ -463,6 +463,7 @@ protected: nsISupports *aState, PRBool aClearScopeHint, PRBool aIsInternalCall); + nsresult DefineArgumentsProperty(nsIArray *aArguments); // Get the parent, returns null if this is a toplevel window nsIDOMWindowInternal *GetParentInternal(); @@ -717,6 +718,7 @@ protected: nsCOMPtr mControllers; nsCOMPtr mArguments; nsCOMPtr mArgumentsLast; + nsCOMPtr mArgumentsOrigin; nsRefPtr mNavigator; nsRefPtr mScreen; nsRefPtr mHistory; @@ -838,6 +840,10 @@ public: NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsGlobalModalWindow, nsGlobalWindow) + virtual NS_HIDDEN_(nsresult) SetNewDocument(nsIDocument *aDocument, + nsISupports *aState, + PRBool aClearScopeHint); + protected: nsCOMPtr mReturnValue; }; diff --git a/dom/base/nsIScriptGlobalObject.h b/dom/base/nsIScriptGlobalObject.h index 84a5dd3567b1..88501bbba9d8 100644 --- a/dom/base/nsIScriptGlobalObject.h +++ b/dom/base/nsIScriptGlobalObject.h @@ -101,13 +101,12 @@ NS_HandleScriptError(nsIScriptGlobalObject *aScriptGlobal, #define NS_ISCRIPTGLOBALOBJECT_IID \ -{ /* {6afecd40-0b9a-4cfd-8c42-0f645cd91829} */ \ - 0x6afecd40, 0x0b9a, 0x4cfd, \ - { 0x8c, 0x42, 0x0f, 0x64, 0x5c, 0xd9, 0x18, 0x29 } } +{ 0xe9f3f2c1, 0x2d94, 0x4722, \ + { 0xbb, 0xd4, 0x2b, 0xf6, 0xfd, 0xf4, 0x2f, 0x48 } } /** -+ * The global object which keeps a script context for each supported script -+ * language. This often used to store per-window global state. + * The global object which keeps a script context for each supported script + * language. This often used to store per-window global state. */ class nsIScriptGlobalObject : public nsISupports @@ -166,15 +165,8 @@ public: */ virtual void SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts) = 0; - /** Set a new arguments object for this window. This will be set on - * the window right away (if there's an existing document) and it - * will also be installed on the window when the next document is - * loaded. Each language impl is responsible for converting to - * an array of args as appropriate for that language. - */ - virtual nsresult SetNewArguments(nsIArray *aArguments) = 0; - - /** Handle a script error. Generally called by a script context. + /** + * Handle a script error. Generally called by a script context. */ virtual nsresult HandleScriptError(nsScriptErrorEvent *aErrorEvent, nsEventStatus *aEventStatus) { diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index 4be552e317bc..369de3ad6155 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -75,10 +75,11 @@ class nsPresContext; struct nsTimeout; class nsScriptObjectHolder; class nsXBLPrototypeHandler; +class nsIArray; #define NS_PIDOMWINDOW_IID \ -{ 0x249423c9, 0x42a6, 0x8243, \ - { 0x49, 0x45, 0x71, 0x7f, 0x8d, 0x28, 0x84, 0x43 } } +{ 0x70c9f57f, 0xf7b3, 0x4a37, \ + { 0xbe, 0x36, 0xbb, 0xb2, 0xd7, 0xe9, 0x40, 0x13 } } class nsPIDOMWindow : public nsIDOMWindowInternal { @@ -464,6 +465,15 @@ public: */ virtual void SetHasOrientationEventListener() = 0; + /** + * Set a arguments for this window. This will be set on the window + * right away (if there's an existing document) and it will also be + * installed on the window when the next document is loaded. Each + * language impl is responsible for converting to an array of args + * as appropriate for that language. + */ + virtual nsresult SetArguments(nsIArray *aArguments, nsIPrincipal *aOrigin) = 0; + protected: // The nsPIDOMWindow constructor. The aOuterWindow argument should // be null if and only if the created window itself is an outer diff --git a/dom/tests/mochitest/bugs/Makefile.in b/dom/tests/mochitest/bugs/Makefile.in index 498a3146ed9a..01c1153f7cfc 100644 --- a/dom/tests/mochitest/bugs/Makefile.in +++ b/dom/tests/mochitest/bugs/Makefile.in @@ -100,6 +100,8 @@ _TEST_FILES = \ test_bug484775.html \ test_bug427744.html \ test_bug495219.html \ + test_bug504862.html \ + file_bug504862.html \ $(NULL) libs:: $(_TEST_FILES) diff --git a/dom/tests/mochitest/bugs/file_bug504862.html b/dom/tests/mochitest/bugs/file_bug504862.html new file mode 100644 index 000000000000..c253c736e048 --- /dev/null +++ b/dom/tests/mochitest/bugs/file_bug504862.html @@ -0,0 +1,22 @@ + + + diff --git a/dom/tests/mochitest/bugs/test_bug504862.html b/dom/tests/mochitest/bugs/test_bug504862.html new file mode 100644 index 000000000000..cecebe1fc686 --- /dev/null +++ b/dom/tests/mochitest/bugs/test_bug504862.html @@ -0,0 +1,37 @@ + + + + + Test for Bug 504862 + + + + + +Mozilla Bug 504862 + + + + diff --git a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp index 4631be3956b4..cec251016f7b 100644 --- a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp +++ b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp @@ -60,6 +60,7 @@ #include "nsIDOMWindow.h" #include "nsIDOMChromeWindow.h" #include "nsIDOMWindowInternal.h" +#include "nsIDOMModalContentWindow.h" #include "nsIScriptObjectPrincipal.h" #include "nsIScreen.h" #include "nsIScreenManager.h" @@ -573,11 +574,21 @@ nsWindowWatcher::OpenWindowJSInternal(nsIDOMWindow *aParent, SizeSpec sizeSpec; CalcSizeSpec(features.get(), sizeSpec); - PRBool isCallerChrome = PR_FALSE; nsCOMPtr sm(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID)); - if (sm) - sm->SubjectPrincipalIsSystem(&isCallerChrome); + + // Remember who's calling us. This code used to assume a null + // subject principal if it failed to get the principal, but that's + // just not safe, so bail on errors here. + nsCOMPtr callerPrincipal; + rv = sm->GetSubjectPrincipal(getter_AddRefs(callerPrincipal)); + NS_ENSURE_SUCCESS(rv, rv); + + PRBool isCallerChrome = PR_TRUE; + if (callerPrincipal) { + rv = sm->IsSystemPrincipal(callerPrincipal, &isCallerChrome); + NS_ENSURE_SUCCESS(rv, rv); + } JSContext *cx = GetJSContextFromWindow(aParent); @@ -756,9 +767,10 @@ nsWindowWatcher::OpenWindowJSInternal(nsIDOMWindow *aParent, if ((aDialog || windowIsModalContentDialog) && argv) { // Set the args on the new window. - nsCOMPtr scriptGlobal(do_QueryInterface(*_retval)); - NS_ENSURE_TRUE(scriptGlobal, NS_ERROR_UNEXPECTED); - rv = scriptGlobal->SetNewArguments(argv); + nsCOMPtr piwin(do_QueryInterface(*_retval)); + NS_ENSURE_TRUE(piwin, NS_ERROR_UNEXPECTED); + + rv = piwin->SetArguments(argv, callerPrincipal); NS_ENSURE_SUCCESS(rv, rv); }