Fixing bug 235457. Making it possible to open a window from chrome as if it was opened from untrusted script. r=danm-moz@comcast.net, sr=peterv@propagandism.org

This commit is contained in:
jst%mozilla.jstenback.com 2004-06-07 21:50:25 +00:00
parent 42a477691d
commit 50a8b02ca7
3 changed files with 58 additions and 23 deletions

View File

@ -5473,12 +5473,28 @@ GlobalWindowImpl::SecurityCheckURL(const char *aURL)
if (!mContext || !mDocument || !sSecMan)
return NS_ERROR_FAILURE;
// get the JSContext from the call stack
nsCOMPtr<nsIThreadJSContextStack> stack(do_GetService(sJSStackContractID));
if (stack)
stack->Peek(&cx);
if (!cx) // not bloody likely. but if there's no JS on the call stack,
return NS_OK; // then we should pass the security check.
nsCOMPtr<nsIDOMChromeWindow> chrome_win =
do_QueryInterface(NS_STATIC_CAST(nsIDOMWindow *, this));
if (IsCallerChrome() && !chrome_win) {
// If open() is called from chrome on a non-chrome window, we'll
// use the context from the window on which open() is being called
// to prevent giving chrome priveleges to new windows opened in
// such a way. This also makes us get the appropriate base URI for
// the below URI resolution code.
cx = (JSContext *)mContext->GetNativeContext();
} else {
// get the JSContext from the call stack
nsCOMPtr<nsIThreadJSContextStack> stack(do_GetService(sJSStackContractID));
if (stack)
stack->Peek(&cx);
if (!cx) {
// if there's no JS on the call stack, then we should pass the
// security check.
return NS_OK;
}
}
/* resolve the URI, which could be relative to the calling window
(note the algorithm to get the base URI should match the one
@ -5497,7 +5513,7 @@ GlobalWindowImpl::SecurityCheckURL(const char *aURL)
caller->GetDocument(getter_AddRefs(callerDOMdoc));
nsCOMPtr<nsIDocument> callerDoc(do_QueryInterface(callerDOMdoc));
if (callerDoc)
baseURI = callerDoc->GetDocumentURI();
baseURI = callerDoc->GetBaseURI();
}
}

View File

@ -55,6 +55,7 @@
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIDOMWindow.h"
#include "nsIDOMChromeWindow.h"
#include "nsIDOMWindowInternal.h"
#include "nsIScreen.h"
#include "nsIScreenManager.h"
@ -463,13 +464,13 @@ nsWindowWatcher::OpenWindow(nsIDOMWindow *aParent,
NS_IMETHODIMP
nsWindowWatcher::OpenWindowJS(nsIDOMWindow *aParent,
const char *aUrl,
const char *aName,
const char *aFeatures,
PRBool aDialog,
PRUint32 argc,
jsval *argv,
nsIDOMWindow **_retval)
const char *aUrl,
const char *aName,
const char *aFeatures,
PRBool aDialog,
PRUint32 argc,
jsval *argv,
nsIDOMWindow **_retval)
{
nsresult rv = NS_OK;
PRBool nameSpecified,
@ -513,8 +514,11 @@ nsWindowWatcher::OpenWindowJS(nsIDOMWindow *aParent,
features.StripWhitespace();
}
chromeFlags = CalculateChromeFlags(features.get(), featuresSpecified, aDialog,
uriToLoadIsChrome);
nsCOMPtr<nsIDOMChromeWindow> chromeParent(do_QueryInterface(aParent));
chromeFlags = CalculateChromeFlags(features.get(), featuresSpecified,
aDialog, uriToLoadIsChrome,
!aParent || chromeParent);
// try to find an extant window with the given name
if (nameSpecified) {
@ -1158,7 +1162,7 @@ void nsWindowWatcher::CheckWindowName(nsString& aName)
#define NS_CALCULATE_CHROME_FLAG_FOR(feature, flag) \
prefBranch->GetBoolPref(feature, &forceEnable); \
if (forceEnable && !isChrome) { \
if (forceEnable && !(isChrome && aHasChromeParent)) { \
chromeFlags |= flag; \
} else { \
chromeFlags |= WinHasOption(aFeatures, feature, \
@ -1177,7 +1181,8 @@ void nsWindowWatcher::CheckWindowName(nsString& aName)
PRUint32 nsWindowWatcher::CalculateChromeFlags(const char *aFeatures,
PRBool aFeaturesSpecified,
PRBool aDialog,
PRBool aChromeURL)
PRBool aChromeURL,
PRBool aHasChromeParent)
{
if(!aFeaturesSpecified || !aFeatures) {
if(aDialog)
@ -1304,9 +1309,11 @@ PRUint32 nsWindowWatcher::CalculateChromeFlags(const char *aFeatures,
PRBool enabled;
nsresult res =
securityManager->IsCapabilityEnabled("UniversalBrowserWrite", &enabled);
if (NS_FAILED(res) || !enabled) {
//If priv check fails, set all elements to minimum reqs., else leave them alone.
if (NS_FAILED(res) || !enabled || (isChrome && !aHasChromeParent)) {
// If priv check fails (or if we're called from chrome, but the
// parent is not a chrome window), set all elements to minimum
// reqs., else leave them alone.
chromeFlags |= nsIWebBrowserChrome::CHROME_TITLEBAR;
chromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_CLOSE;
chromeFlags &= ~nsIWebBrowserChrome::CHROME_WINDOW_LOWERED;
@ -1556,9 +1563,20 @@ nsWindowWatcher::SizeOpenedDocShellItem(nsIDocShellTreeItem *aDocShellItem,
nsCOMPtr<nsIScriptSecurityManager>
securityManager(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID));
if (securityManager) {
res = securityManager->IsCapabilityEnabled("UniversalBrowserWrite", &enabled);
res = securityManager->IsCapabilityEnabled("UniversalBrowserWrite",
&enabled);
if (NS_FAILED(res))
enabled = PR_FALSE;
else if (enabled && aParent) {
nsCOMPtr<nsIDOMChromeWindow> chromeWin(do_QueryInterface(aParent));
PRBool isChrome = PR_FALSE;
securityManager->SubjectPrincipalIsSystem(&isChrome);
// Only enable special priveleges for chrome when chrome calls
// open() on a chrome window
enabled = !(isChrome && chromeWin == nsnull);
}
}
if (!enabled) {

View File

@ -96,7 +96,8 @@ private:
static PRUint32 CalculateChromeFlags(const char *aFeatures,
PRBool aFeaturesSpecified,
PRBool aDialog,
PRBool aChromeURL);
PRBool aChromeURL,
PRBool aHasChromeParent);
static PRInt32 WinHasOption(const char *aOptions, const char *aName,
PRInt32 aDefault, PRBool *aPresenceFlag);
static nsresult ReadyOpenedDocShellItem(nsIDocShellTreeItem *aOpenedItem,