From 6079a31c937d0a5684b4e39ceb1bc69524193170 Mon Sep 17 00:00:00 2001 From: "mstoltz%netscape.com" Date: Fri, 23 Mar 2001 04:22:56 +0000 Subject: [PATCH] Bugs 55069, 70951 - JS-blocking APIs for mailnews and embedding. r=mscott, sr=attinasi. Bug 54237 - fix for event-capture bug, r=heikki, sr=jband. git-svn-id: svn://10.0.0.236/trunk@90195 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/caps/idl/nsIScriptSecurityManager.idl | 2 +- .../caps/include/nsScriptSecurityManager.h | 6 +- mozilla/caps/src/nsScriptSecurityManager.cpp | 99 ++++++++++++++----- .../xml/document/src/nsXMLDocument.cpp | 18 +++- mozilla/docshell/base/nsDocShell.cpp | 28 ++++++ mozilla/docshell/base/nsDocShell.h | 2 + mozilla/docshell/base/nsIDocShell.idl | 17 +++- mozilla/dom/src/base/nsJSEnvironment.cpp | 6 +- .../browser/webBrowser/nsIWebBrowserSetup.idl | 3 +- .../browser/webBrowser/nsWebBrowser.cpp | 7 ++ mozilla/mailnews/base/src/nsMsgWindow.cpp | 13 +-- 11 files changed, 155 insertions(+), 46 deletions(-) diff --git a/mozilla/caps/idl/nsIScriptSecurityManager.idl b/mozilla/caps/idl/nsIScriptSecurityManager.idl index 66ce73377df..4002e12d5c0 100644 --- a/mozilla/caps/idl/nsIScriptSecurityManager.idl +++ b/mozilla/caps/idl/nsIScriptSecurityManager.idl @@ -129,7 +129,7 @@ interface nsIScriptSecurityManager : nsISupports * Return true if content from the given principal is allowed to * execute scripts. */ - boolean canExecuteScripts(in nsIPrincipal principal); + [noscript] boolean canExecuteScripts(in JSContextPtr cx, in nsIPrincipal principal); ///////////////// Capabilities ///////////////////// diff --git a/mozilla/caps/include/nsScriptSecurityManager.h b/mozilla/caps/include/nsScriptSecurityManager.h index 7d8c66ef916..6d09ecc25fd 100644 --- a/mozilla/caps/include/nsScriptSecurityManager.h +++ b/mozilla/caps/include/nsScriptSecurityManager.h @@ -36,9 +36,10 @@ #include "nsCOMPtr.h" #include "nsIPref.h" #include "nsISecurityPref.h" - #include "nsIJSContextStack.h" +class nsIDocShell; + ///////////////////// // nsIPrincipalKey // ///////////////////// @@ -97,6 +98,9 @@ public: JSContext * GetCurrentContextQuick(); private: + nsresult + GetRootDocShell(JSContext *cx, nsIDocShell **result); + NS_IMETHOD CheckScriptAccessInternal(JSContext *cx, void* obj, const char* aObjUrlStr, PRInt32 domPropInt, diff --git a/mozilla/caps/src/nsScriptSecurityManager.cpp b/mozilla/caps/src/nsScriptSecurityManager.cpp index 410f418cde4..b4bde9d45bf 100644 --- a/mozilla/caps/src/nsScriptSecurityManager.cpp +++ b/mozilla/caps/src/nsScriptSecurityManager.cpp @@ -62,6 +62,8 @@ #include "nsIScriptGlobalObject.h" #include "nsIDOMWindowInternal.h" #include "nscore.h" +#include "nsIDocShell.h" +#include "nsIDocShellTreeItem.h" static NS_DEFINE_CID(kNetSupportDialogCID, NS_NETSUPPORTDIALOG_CID); static NS_DEFINE_IID(kIIOServiceIID, NS_IIOSERVICE_IID); @@ -407,7 +409,7 @@ NS_IMETHODIMP nsScriptSecurityManager::CheckScriptAccessToURL(JSContext *cx, const char* aObjUrlStr, PRInt32 domPropInt, PRBool isWrite) -{ +{ return CheckScriptAccessInternal(cx, nsnull, aObjUrlStr, domPropInt, isWrite); } @@ -415,7 +417,7 @@ NS_IMETHODIMP nsScriptSecurityManager::CheckScriptAccess(JSContext *cx, void *aObj, PRInt32 domPropInt, PRBool isWrite) -{ +{ return CheckScriptAccessInternal(cx, aObj, nsnull, domPropInt, isWrite); } @@ -450,7 +452,9 @@ nsScriptSecurityManager::CheckScriptAccessInternal(JSContext *cx, case SCRIPT_SECURITY_SAME_DOMAIN_ACCESS: { const char *cap = isWrite ? UBW : UBR; - +#ifdef DEBUG_mstoltz + printf("##### Checking %s : \n", domPropNames[domProp]); +#endif nsCOMPtr objectPrincipal; if (aObj) { @@ -550,7 +554,7 @@ NS_IMETHODIMP nsScriptSecurityManager::CheckLoadURI(nsIURI *aSourceURI, nsIURI *aTargetURI, PRUint32 aFlags) { - nsCOMPtr jarURI; + nsCOMPtr jarURI; nsCOMPtr sourceUri(aSourceURI); while((jarURI = do_QueryInterface(sourceUri))) jarURI->GetJARFile(getter_AddRefs(sourceUri)); @@ -647,20 +651,26 @@ NS_IMETHODIMP nsScriptSecurityManager::CheckFunctionAccess(JSContext *aCx, void *aFunObj, void *aTargetObj) { + //-- This check is called for event handlers nsCOMPtr subject; nsresult rv = GetFunctionObjectPrincipal(aCx, (JSObject *)aFunObj, - getter_AddRefs(subject)); + getter_AddRefs(subject)); if (NS_FAILED(rv)) return rv; - // First check if the principal the function was compiled under is + PRBool isSystem; + if (NS_SUCCEEDED(subject->Equals(mSystemPrincipal, &isSystem)) && isSystem) + // This is the system principal: just allow access + return NS_OK; + + // Check if the principal the function was compiled under is // allowed to execute scripts. if (!subject) { return NS_ERROR_DOM_SECURITY_ERR; } PRBool result; - rv = CanExecuteScripts(subject, &result); + rv = CanExecuteScripts(aCx, subject, &result); if (NS_FAILED(rv)) { return rv; } @@ -862,46 +872,75 @@ nsScriptSecurityManager::EnsureNameSetRegistered() return mNameSetRegistered; } +nsresult +nsScriptSecurityManager::GetRootDocShell(JSContext *cx, nsIDocShell **result) +{ + nsresult rv; + *result = nsnull; + nsCOMPtr docshell; + nsCOMPtr scriptContext = (nsIScriptContext*)JS_GetContextPrivate(cx); + if (!scriptContext) return NS_ERROR_FAILURE; + nsCOMPtr globalObject = scriptContext->GetGlobalObject(); + if (!globalObject) return NS_ERROR_FAILURE; + rv = globalObject->GetDocShell(getter_AddRefs(docshell)); + if (NS_FAILED(rv)) return rv; + nsCOMPtr docshellTreeItem = do_QueryInterface(docshell, &rv); + if (NS_FAILED(rv)) return rv; + nsCOMPtr rootItem; + rv = docshellTreeItem->GetRootTreeItem(getter_AddRefs(rootItem)); + if (NS_FAILED(rv)) return rv; + + return rootItem->QueryInterface(NS_GET_IID(nsIDocShell), (void**)result); +} + NS_IMETHODIMP -nsScriptSecurityManager::CanExecuteScripts(nsIPrincipal *principal, +nsScriptSecurityManager::CanExecuteScripts(JSContext* cx, nsIPrincipal *principal, PRBool *result) { // XXX Really OK to fail? // I suppose that in some embedding there may be no ScriptNameSetRegistry. EnsureNameSetRegistered(); - if (principal == mSystemPrincipal) { - // Even if JavaScript is disabled, we must still execute system scripts + if (principal == mSystemPrincipal) + { + // Even if JavaScript is disabled, we must still execute system scripts *result = PR_TRUE; return NS_OK; } - - if (GetBit(hasDomainPolicyVector, NS_DOM_PROP_JAVASCRIPT_ENABLED)) { + + //-- See if the current window allows JS execution + nsCOMPtr docshell; + nsresult rv; + rv = GetRootDocShell(cx, getter_AddRefs(docshell)); + if (NS_SUCCEEDED(rv)) + { + rv = docshell->GetAllowJavascript(result); + if (NS_FAILED(rv)) return rv; + if (!*result) + return NS_OK; + } + + if (GetBit(hasDomainPolicyVector, NS_DOM_PROP_JAVASCRIPT_ENABLED)) + { // We may have a per-domain security policy for JavaScript execution nsCAutoString capability; PRInt32 secLevel = GetSecurityLevel(principal, NS_DOM_PROP_JAVASCRIPT_ENABLED, PR_FALSE, capability); - if (secLevel != SCRIPT_SECURITY_UNDEFINED_ACCESS) { + if (secLevel != SCRIPT_SECURITY_UNDEFINED_ACCESS) + { *result = (secLevel == SCRIPT_SECURITY_ALL_ACCESS); return NS_OK; } } - if (mIsJavaScriptEnabled != mIsMailJavaScriptEnabled) { + if ((mIsJavaScriptEnabled != mIsMailJavaScriptEnabled) && docshell) + { // Is this script running from mail? - nsCOMPtr codebase = do_QueryInterface(principal); - if (!codebase) - return NS_ERROR_FAILURE; - nsCOMPtr uri; - if (NS_FAILED(codebase->GetURI(getter_AddRefs(uri)))) - return NS_ERROR_FAILURE; - nsXPIDLCString scheme; - if (NS_FAILED(uri->GetScheme(getter_Copies(scheme)))) - return NS_ERROR_FAILURE; - if (nsCRT::strcasecmp(scheme, "imap") == 0 || - nsCRT::strcasecmp(scheme, "mailbox") == 0 || - nsCRT::strcasecmp(scheme, "news") == 0) + PRUint32 appType; + rv = docshell->GetAppType(&appType); + if (NS_FAILED(rv)) return rv; + if (appType == nsIDocShell::APP_TYPE_MAIL) { *result = mIsMailJavaScriptEnabled; return NS_OK; @@ -1685,7 +1724,12 @@ nsScriptSecurityManager::CheckPermissions(JSContext *aCx, nsIPrincipal* aObjectP return NS_ERROR_FAILURE; if (isSameOrigin) + { +#ifdef DEBUG_mstoltz + printf(" OK.\n"); +#endif return NS_OK; + } // Allow access to about:blank nsCOMPtr objectCodebase = do_QueryInterface(aObjectPrincipal); @@ -1712,6 +1756,9 @@ nsScriptSecurityManager::CheckPermissions(JSContext *aCx, nsIPrincipal* aObjectP /* ** Access tests failed, so now report error. */ +#ifdef DEBUG_mstoltz + printf(" FAILED.\n"); +#endif return NS_ERROR_DOM_PROP_ACCESS_DENIED; } diff --git a/mozilla/content/xml/document/src/nsXMLDocument.cpp b/mozilla/content/xml/document/src/nsXMLDocument.cpp index 703483616ea..e5fabdb7701 100644 --- a/mozilla/content/xml/document/src/nsXMLDocument.cpp +++ b/mozilla/content/xml/document/src/nsXMLDocument.cpp @@ -337,15 +337,23 @@ nsXMLDocument::Load(const nsAReadableString& aUrl) if (NS_FAILED(secMan->CheckLoadURIFromScript(nsnull, uri))) return NS_ERROR_FAILURE; - // Set a principal for this document - NS_IF_RELEASE(mPrincipal); - rv = secMan->GetCodebasePrincipal(uri, &mPrincipal); - if (!mPrincipal) return rv; - // Create a channel rv = NS_OpenURI(getter_AddRefs(channel), uri, nsnull, nsnull, this); if (NS_FAILED(rv)) return rv; + // Set a principal for this document + NS_IF_RELEASE(mPrincipal); + nsCOMPtr channelOwner; + rv = channel->GetOwner(getter_AddRefs(channelOwner)); + if (NS_SUCCEEDED(rv) && channelOwner) + rv = channelOwner->QueryInterface(NS_GET_IID(nsIPrincipal), (void**)&mPrincipal); + + if (NS_FAILED(rv) || !channelOwner) + { + rv = secMan->GetCodebasePrincipal(uri, &mPrincipal); + if (!mPrincipal) return rv; + } + // Prepare for loading the XML document "into oneself" nsCOMPtr listener; if (NS_FAILED(rv = StartDocumentLoad(kLoadAsData, channel, diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index bc30608ec68..4be64714e6e 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -127,6 +127,8 @@ nsDocShell::nsDocShell() : mDefaultScrollbarPref(-1,-1), mInitialPageLoad(PR_TRUE), mAllowPlugins(PR_TRUE), + mAllowJavascript(PR_TRUE), + mAppType(nsIDocShell::APP_TYPE_UNKNOWN), mViewMode(viewNormal), mLastViewMode(viewNormal), mRestoreViewMode(PR_FALSE), @@ -698,6 +700,32 @@ NS_IMETHODIMP nsDocShell::SetAllowPlugins(PRBool aAllowPlugins) return NS_OK; } +NS_IMETHODIMP nsDocShell::GetAllowJavascript(PRBool* aAllowJavascript) +{ + NS_ENSURE_ARG_POINTER(aAllowJavascript); + + *aAllowJavascript = mAllowJavascript; + return NS_OK; +} + +NS_IMETHODIMP nsDocShell::SetAllowJavascript(PRBool aAllowJavascript) +{ + mAllowJavascript = aAllowJavascript; + return NS_OK; +} + +NS_IMETHODIMP nsDocShell::GetAppType(PRUint32* aAppType) +{ + *aAppType = mAppType; + return NS_OK; +} + +NS_IMETHODIMP nsDocShell::SetAppType(PRUint32 aAppType) +{ + mAppType = aAppType; + return NS_OK; +} + NS_IMETHODIMP nsDocShell::GetViewMode(PRInt32* aViewMode) { NS_ENSURE_ARG_POINTER(aViewMode); diff --git a/mozilla/docshell/base/nsDocShell.h b/mozilla/docshell/base/nsDocShell.h index de4e16c602b..4c014f1890d 100644 --- a/mozilla/docshell/base/nsDocShell.h +++ b/mozilla/docshell/base/nsDocShell.h @@ -288,6 +288,8 @@ protected: PRUint32 mLoadType; PRBool mInitialPageLoad; PRBool mAllowPlugins; + PRBool mAllowJavascript; + PRUint32 mAppType; PRInt32 mViewMode; PRInt32 mLastViewMode; PRBool mRestoreViewMode; diff --git a/mozilla/docshell/base/nsIDocShell.idl b/mozilla/docshell/base/nsIDocShell.idl index cb410e47256..db93b3e9eda 100644 --- a/mozilla/docshell/base/nsIDocShell.idl +++ b/mozilla/docshell/base/nsIDocShell.idl @@ -1,3 +1,4 @@ + /* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Mozilla Public @@ -138,10 +139,23 @@ interface nsIDocShell : nsISupports attribute nsIDocumentCharsetInfo documentCharsetInfo; /* - Attribute stating if it should allow plugins or not. + Whether to allow plugin execution */ attribute boolean allowPlugins; + /* + Whether to allow Javascript execution + */ + attribute boolean allowJavascript; + + /* + The type of application that created this window + */ + const unsigned long APP_TYPE_UNKNOWN = 0; + const unsigned long APP_TYPE_MAIL = 1; + + attribute unsigned long appType; + /* Definitions for the viewModes the docShell can be in. */ @@ -180,5 +194,6 @@ interface nsIDocShell : nsISupports const unsigned long BUSY_FLAGS_PAGE_LOADING = 4; readonly attribute unsigned long busyFlags; + }; diff --git a/mozilla/dom/src/base/nsJSEnvironment.cpp b/mozilla/dom/src/base/nsJSEnvironment.cpp index e328c591a0c..6f7da752db0 100644 --- a/mozilla/dom/src/base/nsJSEnvironment.cpp +++ b/mozilla/dom/src/base/nsJSEnvironment.cpp @@ -446,7 +446,7 @@ nsJSContext::EvaluateStringWithValue(const nsAReadableString& aScript, nsCOMPtr securityManager; rv = GetSecurityManager(getter_AddRefs(securityManager)); if (NS_SUCCEEDED(rv)) - rv = securityManager->CanExecuteScripts(principal, &ok); + rv = securityManager->CanExecuteScripts(mContext, principal, &ok); if (NS_FAILED(rv)) { JSPRINCIPALS_DROP(mContext, jsprin); return NS_ERROR_FAILURE; @@ -562,7 +562,7 @@ nsJSContext::EvaluateString(const nsAReadableString& aScript, nsCOMPtr securityManager; rv = GetSecurityManager(getter_AddRefs(securityManager)); if (NS_SUCCEEDED(rv)) - rv = securityManager->CanExecuteScripts(principal, &ok); + rv = securityManager->CanExecuteScripts(mContext, principal, &ok); if (NS_FAILED(rv)) { JSPRINCIPALS_DROP(mContext, jsprin); return NS_ERROR_FAILURE; @@ -665,7 +665,7 @@ nsJSContext::CompileScript(const PRUnichar* aText, nsCOMPtr securityManager; rv = GetSecurityManager(getter_AddRefs(securityManager)); if (NS_SUCCEEDED(rv)) - rv = securityManager->CanExecuteScripts(aPrincipal, &ok); + rv = securityManager->CanExecuteScripts(mContext, aPrincipal, &ok); if (NS_FAILED(rv)) { JSPRINCIPALS_DROP(mContext, jsprin); return NS_ERROR_FAILURE; diff --git a/mozilla/embedding/browser/webBrowser/nsIWebBrowserSetup.idl b/mozilla/embedding/browser/webBrowser/nsIWebBrowserSetup.idl index d0ab00bff3e..adf678473e8 100644 --- a/mozilla/embedding/browser/webBrowser/nsIWebBrowserSetup.idl +++ b/mozilla/embedding/browser/webBrowser/nsIWebBrowserSetup.idl @@ -30,7 +30,8 @@ [scriptable, uuid(F15398A0-8018-11d3-AF70-00A024FFC08C)] interface nsIWebBrowserSetup : nsISupports { - const unsigned long SETUP_ALLOW_PLUGINS = 1; + const unsigned long SETUP_ALLOW_PLUGINS = 1; + const unsigned long SETUP_ALLOW_JAVASCRIPT = 2; void setProperty(in unsigned long aId, in unsigned long aValue); }; \ No newline at end of file diff --git a/mozilla/embedding/browser/webBrowser/nsWebBrowser.cpp b/mozilla/embedding/browser/webBrowser/nsWebBrowser.cpp index ecc577ecc29..efca97dc7f2 100644 --- a/mozilla/embedding/browser/webBrowser/nsWebBrowser.cpp +++ b/mozilla/embedding/browser/webBrowser/nsWebBrowser.cpp @@ -597,6 +597,13 @@ NS_IMETHODIMP nsWebBrowser::SetProperty(PRUint32 aId, PRUint32 aValue) mDocShell->SetAllowPlugins(aValue); } break; + case nsIWebBrowserSetup::SETUP_ALLOW_JAVASCRIPT: + { + NS_ENSURE_STATE(mDocShell); + NS_ENSURE_TRUE((aValue == PR_TRUE || aValue == PR_FALSE), NS_ERROR_INVALID_ARG); + mDocShell->SetAllowJavascript(aValue); + } + break; default: return NS_ERROR_INVALID_ARG; diff --git a/mozilla/mailnews/base/src/nsMsgWindow.cpp b/mozilla/mailnews/base/src/nsMsgWindow.cpp index 148c5676c06..e3a2107794a 100644 --- a/mozilla/mailnews/base/src/nsMsgWindow.cpp +++ b/mozilla/mailnews/base/src/nsMsgWindow.cpp @@ -254,6 +254,9 @@ NS_IMETHODIMP nsMsgWindow::SetRootDocShell(nsIDocShell * aDocShell) { mRootDocShellWeak = getter_AddRefs(NS_GetWeakReference(aDocShell)); aDocShell->SetParentURIContentListener(this); + // be sure to set the application flag on the root docshell + // so it knows we are a mail application. + aDocShell->SetAppType(nsIDocShell::APP_TYPE_MAIL); } return NS_OK; } @@ -309,13 +312,7 @@ NS_IMETHODIMP nsMsgWindow::SetDOMWindow(nsIDOMWindowInternal *aWindow) docShellAsItem->GetSameTypeRootTreeItem(getter_AddRefs(rootAsItem)); nsCOMPtr rootAsShell(do_QueryInterface(rootAsItem)); - if(rootAsShell) - rootAsShell->SetParentURIContentListener(this); - - nsAutoString childName; childName.AssignWithConversion("messagepane"); - nsCOMPtr rootAsNode(do_QueryInterface(rootAsItem)); - docShell = do_QueryInterface(rootAsItem); - mRootDocShellWeak = getter_AddRefs(NS_GetWeakReference(docShell)); + SetRootDocShell(rootAsShell); // force ourselves to figure out the message pane nsCOMPtr messageWindowDocShell; @@ -323,7 +320,7 @@ NS_IMETHODIMP nsMsgWindow::SetDOMWindow(nsIDOMWindowInternal *aWindow) SetStatusFeedback(mStatusFeedback); } - //Get nsIMsgWindowCommands object + //Get nsIMsgWindowCommands object nsCOMPtr xpConnectObj; nsCOMPtr piDOMWindow(do_QueryInterface(aWindow)); if (piDOMWindow)