Bug 105050 - return null window.opener to scripts if opener is a mail window.
Bug 32571 - Prompt user before allowing scripts to close windows if opener is null. both r=heikki, sr=jst.
This commit is contained in:
Родитель
ce1b14f952
Коммит
7446e86422
|
@ -198,6 +198,12 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
|||
[noscript] nsIPrincipal getObjectPrincipal(in JSContextPtr cx,
|
||||
in JSObjectPtr obj);
|
||||
|
||||
/**
|
||||
* Returns true if the principal of the currently running script is the
|
||||
* system principal, false otherwise.
|
||||
*/
|
||||
boolean subjectPrincipalIsSystem();
|
||||
|
||||
/**
|
||||
* Forget all currently stored security policies and reread from prefs.
|
||||
* This must be called after any capability.policy prefs have changed.
|
||||
|
|
|
@ -1240,6 +1240,31 @@ nsScriptSecurityManager::GetSystemPrincipal(nsIPrincipal **result)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptSecurityManager::SubjectPrincipalIsSystem(PRBool* aIsSystem)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsSystem);
|
||||
*aIsSystem = PR_FALSE;
|
||||
|
||||
if (!mSystemPrincipal)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIPrincipal> subject;
|
||||
nsresult rv = GetSubjectPrincipal(getter_AddRefs(subject));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if(!subject)
|
||||
{
|
||||
// No subject principal means no JS is running;
|
||||
// this is the equivalent of system principal code
|
||||
*aIsSystem = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return mSystemPrincipal->Equals(subject, aIsSystem);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptSecurityManager::GetCertificatePrincipal(const char* aCertID,
|
||||
nsIPrincipal **result)
|
||||
|
@ -2677,7 +2702,6 @@ nsScriptSecurityManager::InitPrefs()
|
|||
PRUint32 prefCount;
|
||||
char** prefNames;
|
||||
|
||||
//-- Set a callback for policy changes
|
||||
// Registering the security manager as an observer to the
|
||||
// profile-after-change topic. We will build up the policy table
|
||||
// after the initial profile loads and after profile switches.
|
||||
|
|
|
@ -1 +1,4 @@
|
|||
JSURLLoadBlockedWarning=Attempt to load a javascript: URL from one host\nin a window displaying content from another host\nwas blocked by the security manager.
|
||||
JSURLLoadBlockedWarning = Attempt to load a javascript: URL from one host\nin a window displaying content from another host\nwas blocked by the security manager.
|
||||
ConfirmWindowCloseDialogTitle = Close Window?
|
||||
ConfirmWindowCloseDialogText = A script wants to close the current window. Do you wish to allow this?
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ REQUIRES = xpcom \
|
|||
xmlextras \
|
||||
find \
|
||||
appshell \
|
||||
intl \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
|
|
|
@ -57,6 +57,7 @@ REQUIRES = xpcom \
|
|||
htmlparser \
|
||||
chardet \
|
||||
transformiix \
|
||||
intl \
|
||||
xmlextras \
|
||||
find \
|
||||
appshell \
|
||||
|
|
|
@ -124,6 +124,7 @@
|
|||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsIJSNativeInitializer.h"
|
||||
#include "nsIStringBundle.h"
|
||||
|
||||
#include "plbase64.h"
|
||||
|
||||
|
@ -155,7 +156,7 @@ static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
|||
static NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID); // For window.find()
|
||||
static const char *sWindowWatcherContractID = "@mozilla.org/embedcomp/window-watcher;1";
|
||||
static const char *sJSStackContractID = "@mozilla.org/js/xpc/ContextStack;1";
|
||||
|
||||
static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
|
||||
|
||||
static const char * const kCryptoContractID = NS_CRYPTO_CONTRACTID;
|
||||
static const char * const kPkcs11ContractID = NS_PKCS11_CONTRACTID;
|
||||
|
@ -1156,7 +1157,28 @@ GlobalWindowImpl::GetControllers(nsIControllers** aResult)
|
|||
NS_IMETHODIMP
|
||||
GlobalWindowImpl::GetOpener(nsIDOMWindowInternal** aOpener)
|
||||
{
|
||||
*aOpener = mOpener;
|
||||
*aOpener = nsnull;
|
||||
// We don't want to reveal the opener if the opener is a mail window,
|
||||
// because opener can be used to spoof the contents of a message (bug 105050).
|
||||
// So, we look in the opener's root docshell to see if it's a mail window.
|
||||
nsCOMPtr<nsIScriptGlobalObject> openerSGO(do_QueryInterface(mOpener));
|
||||
if (openerSGO) {
|
||||
nsCOMPtr<nsIDocShell> openerDocShell;
|
||||
openerSGO->GetDocShell(getter_AddRefs(openerDocShell));
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(openerDocShell));
|
||||
if (docShellAsItem) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> openerRootItem;
|
||||
docShellAsItem->GetRootTreeItem(getter_AddRefs(openerRootItem));
|
||||
nsCOMPtr<nsIDocShell> openerRootDocShell(do_QueryInterface(openerRootItem));
|
||||
if (openerRootDocShell) {
|
||||
PRUint32 appType;
|
||||
nsresult rv = openerRootDocShell->GetAppType(&appType);
|
||||
if (NS_SUCCEEDED(rv) && appType != nsIDocShell::APP_TYPE_MAIL) {
|
||||
*aOpener = mOpener;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_IF_ADDREF(*aOpener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -2438,6 +2460,46 @@ GlobalWindowImpl::GetFrames(nsIDOMWindow** aFrames)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
#define DOM_PROPERTIES_URL "chrome://communicator/locale/dom/dom.properties"
|
||||
|
||||
nsresult
|
||||
GlobalWindowImpl::ConfirmClose(PRBool* aConfirmed)
|
||||
{
|
||||
nsresult rv;
|
||||
// Get the localized strings for the dialog
|
||||
nsCOMPtr<nsIStringBundleService> bundleService(
|
||||
do_GetService(kStringBundleServiceCID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
//XXX: What to do on error?
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
rv = bundleService->CreateBundle(NS_LITERAL_CSTRING(DOM_PROPERTIES_URL).get(),
|
||||
getter_AddRefs(bundle));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsXPIDLString confirmTitle;
|
||||
rv = bundle->GetStringFromName(NS_LITERAL_STRING("ConfirmWindowCloseDialogTitle").get(),
|
||||
getter_Copies(confirmTitle));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsXPIDLString confirmText;
|
||||
rv = bundle->GetStringFromName(NS_LITERAL_STRING("ConfirmWindowCloseDialogText").get(),
|
||||
getter_Copies(confirmText));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Show the dialog
|
||||
nsCOMPtr<nsIPrompt> prompter;
|
||||
rv = GetPrompter(getter_AddRefs(prompter));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return prompter->Confirm(confirmTitle,
|
||||
confirmText, aConfirmed);
|
||||
}
|
||||
|
||||
#define DENY_SCRIPT_CLOSE 0
|
||||
#define CONFIRM_SCRIPT_CLOSE 1
|
||||
#define ALLOW_SCRIPT_CLOSE 2
|
||||
|
||||
NS_IMETHODIMP
|
||||
GlobalWindowImpl::Close()
|
||||
{
|
||||
|
@ -2447,15 +2509,44 @@ GlobalWindowImpl::Close()
|
|||
if (parent != NS_STATIC_CAST(nsIDOMWindow *, this)) {
|
||||
// window.close() is called on a frame in a frameset, such calls
|
||||
// are ignored.
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Note: the basic security check, rejecting windows not opened through JS,
|
||||
// has been removed. This was approved long ago by ...you're going to call me
|
||||
// on this, aren't you... well it was. And anyway, a better means is coming.
|
||||
// In the new world of application-level interfaces being written in JS, this
|
||||
// security check was causing problems.
|
||||
// If this window was not opened by script (!mOpener), find out
|
||||
// whether it's OK for a script to close it.
|
||||
if (!mOpener) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// System scripts can close all windows
|
||||
PRBool InSystemCode = PR_FALSE;
|
||||
rv = secMan->SubjectPrincipalIsSystem(&InSystemCode);
|
||||
if (NS_FAILED(rv) || !InSystemCode) {
|
||||
// Check the pref "dom.allow_scripts_to_close_windows"
|
||||
nsCOMPtr<nsIPref> pref(do_GetService(kPrefServiceCID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt32 closePref;
|
||||
rv = pref->GetIntPref("dom.allow_scripts_to_close_windows", &closePref);
|
||||
if (NS_FAILED(rv))
|
||||
closePref = CONFIRM_SCRIPT_CLOSE;
|
||||
PRBool confirmOK = PR_FALSE;
|
||||
if (closePref == CONFIRM_SCRIPT_CLOSE) {
|
||||
// Ask the user whether it's OK to close the window
|
||||
rv = ConfirmClose(&confirmOK);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
} else {
|
||||
confirmOK = (closePref == ALLOW_SCRIPT_CLOSE);
|
||||
}
|
||||
if (!confirmOK) {
|
||||
// User clicked Cancel, so abort the close
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIJSContextStack> stack =
|
||||
do_GetService("@mozilla.org/js/xpc/ContextStack;1");
|
||||
|
|
|
@ -214,6 +214,7 @@ protected:
|
|||
const nsAReadableString& aOptions,
|
||||
PRBool aDialog, jsval *argv, PRUint32 argc,
|
||||
nsISupports *aExtraArgument, nsIDOMWindow **aReturn);
|
||||
nsresult ConfirmClose(PRBool* aConfirmed);
|
||||
static void CloseWindow(nsISupports* aWindow);
|
||||
|
||||
// Timeout Functions
|
||||
|
|
|
@ -334,6 +334,9 @@ pref("capability.principal.codebase.foo.granted", "UniversalFoo");
|
|||
//////////////////////////////////////////////////////////
|
||||
|
||||
pref("dom.disable_open_during_load", false);
|
||||
// 0 = never allow scripts to close windows that weren't opened by script,
|
||||
// 1 = prompt user, 2 = always allow. Default is prompt.
|
||||
pref("dom.allow_scripts_to_close_windows", 1);
|
||||
|
||||
pref("javascript.enabled", true);
|
||||
pref("javascript.allow.mailnews", false);
|
||||
|
|
Загрузка…
Ссылка в новой задаче