Don't allow loads to start in a docshell that's firing the unload event. Alsodon't allow document.open of the document in that docshell. Bug 371360,r=biesi, sr=jst

This commit is contained in:
bzbarsky@mit.edu 2007-06-14 11:18:05 -07:00
parent d11bc710a8
commit ac7d66789b
5 changed files with 55 additions and 8 deletions

View File

@ -2040,6 +2040,16 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace)
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
// check whether we're in the middle of unload. If so, ignore this call.
nsCOMPtr<nsIDocShell> shell = do_QueryReferent(mDocumentContainer);
if (shell) {
PRBool inUnload;
shell->GetIsInUnload(&inUnload);
if (inUnload) {
return NS_OK;
}
}
// Note: We want to use GetDocumentFromContext here because this document
// should inherit the security information of the document that's opening us,
// (since if it's secure, then it's presumeably trusted).

View File

@ -671,6 +671,9 @@ nsDocShell::LoadURI(nsIURI * aURI,
PRUint32 aLoadFlags,
PRBool aFirstParty)
{
if (mFiredUnloadEvent) {
return NS_OK; // JS may not handle returning of an error code
}
nsresult rv;
nsCOMPtr<nsIURI> referrer;
nsCOMPtr<nsIInputStream> postStream;
@ -973,6 +976,7 @@ nsDocShell::FirePageHideNotification(PRBool aIsUnload)
}
}
}
return NS_OK;
}
@ -2198,6 +2202,13 @@ nsDocShell::SetChildOffset(PRUint32 aChildOffset)
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetIsInUnload(PRBool* aIsInUnload)
{
*aIsInUnload = mFiredUnloadEvent;
return NS_OK;
}
//*****************************************************************************
// nsDocShell::nsIDocShellTreeNode
//*****************************************************************************
@ -2630,6 +2641,12 @@ nsDocShell::IsPrintingOrPP(PRBool aDisplayErrorDialog)
return mIsPrintingOrPP;
}
PRBool
nsDocShell::IsNavigationAllowed(PRBool aDisplayPrintErrorDialog)
{
return !IsPrintingOrPP(aDisplayPrintErrorDialog) && !mFiredUnloadEvent;
}
//*****************************************************************************
// nsDocShell::nsIWebNavigation
//*****************************************************************************
@ -2637,7 +2654,7 @@ nsDocShell::IsPrintingOrPP(PRBool aDisplayErrorDialog)
NS_IMETHODIMP
nsDocShell::GetCanGoBack(PRBool * aCanGoBack)
{
if (IsPrintingOrPP(PR_FALSE)) {
if (!IsNavigationAllowed(PR_FALSE)) {
*aCanGoBack = PR_FALSE;
return NS_OK; // JS may not handle returning of an error code
}
@ -2654,7 +2671,7 @@ nsDocShell::GetCanGoBack(PRBool * aCanGoBack)
NS_IMETHODIMP
nsDocShell::GetCanGoForward(PRBool * aCanGoForward)
{
if (IsPrintingOrPP(PR_FALSE)) {
if (!IsNavigationAllowed(PR_FALSE)) {
*aCanGoForward = PR_FALSE;
return NS_OK; // JS may not handle returning of an error code
}
@ -2671,7 +2688,7 @@ nsDocShell::GetCanGoForward(PRBool * aCanGoForward)
NS_IMETHODIMP
nsDocShell::GoBack()
{
if (IsPrintingOrPP()) {
if (!IsNavigationAllowed()) {
return NS_OK; // JS may not handle returning of an error code
}
nsresult rv;
@ -2687,7 +2704,7 @@ nsDocShell::GoBack()
NS_IMETHODIMP
nsDocShell::GoForward()
{
if (IsPrintingOrPP()) {
if (!IsNavigationAllowed()) {
return NS_OK; // JS may not handle returning of an error code
}
nsresult rv;
@ -2702,7 +2719,7 @@ nsDocShell::GoForward()
NS_IMETHODIMP nsDocShell::GotoIndex(PRInt32 aIndex)
{
if (IsPrintingOrPP()) {
if (!IsNavigationAllowed()) {
return NS_OK; // JS may not handle returning of an error code
}
nsresult rv;
@ -2723,7 +2740,7 @@ nsDocShell::LoadURI(const PRUnichar * aURI,
nsIInputStream * aPostStream,
nsIInputStream * aHeaderStream)
{
if (IsPrintingOrPP()) {
if (!IsNavigationAllowed()) {
return NS_OK; // JS may not handle returning of an error code
}
nsCOMPtr<nsIURI> uri;
@ -3107,7 +3124,7 @@ nsDocShell::LoadErrorPage(nsIURI *aURI, const PRUnichar *aURL,
NS_IMETHODIMP
nsDocShell::Reload(PRUint32 aReloadFlags)
{
if (IsPrintingOrPP()) {
if (!IsNavigationAllowed()) {
return NS_OK; // JS may not handle returning of an error code
}
nsresult rv;

View File

@ -380,6 +380,7 @@ protected:
const PRUnichar *aPage,
const PRUnichar *aDescription,
nsIChannel* aFailedChannel);
PRBool IsNavigationAllowed(PRBool aDisplayPrintErrorDialog = PR_TRUE);
PRBool IsPrintingOrPP(PRBool aDisplayErrorDialog = PR_TRUE);
nsresult SetBaseUrlForWyciwyg(nsIContentViewer * aContentViewer);

View File

@ -68,7 +68,7 @@ interface nsILayoutHistoryState;
interface nsISecureBrowserUI;
interface nsIDOMStorage;
[scriptable, uuid(db67b973-ba1a-49fa-b5b4-7670d203fa0e)]
[scriptable, uuid(10ed386d-8598-408c-b571-e75ad18edeb0)]
interface nsIDocShell : nsISupports
{
/**
@ -184,6 +184,9 @@ interface nsIDocShell : nsISupports
* Notify the associated content viewer and all child docshells that they are
* about to be hidden. If |isUnload| is true, then the document is being
* unloaded as well.
*
* @param isUnload if true, fire the unload event in addition to the pagehide
* event.
*/
[noscript] void firePageHideNotification(in boolean isUnload);
@ -438,5 +441,12 @@ interface nsIDocShell : nsISupports
* Set the offset of this child in its container.
*/
[noscript] void setChildOffset(in unsigned long offset);
/**
* Find out whether the docshell is currently in the middle of a page
* transition (after the onunload event has fired, but before the new
* document has been set up)
*/
readonly attribute boolean isInUnload;
};

View File

@ -768,6 +768,11 @@ nsWebShell::OnLinkClick(nsIContent* aContent,
nsIInputStream* aHeadersDataStream)
{
NS_ASSERTION(NS_IsMainThread(), "wrong thread");
if (mFiredUnloadEvent) {
return NS_OK;
}
nsCOMPtr<nsIRunnable> ev =
new OnLinkClickEvent(this, aContent, aURI, aTargetSpec,
aPostDataStream, aHeadersDataStream);
@ -791,6 +796,10 @@ nsWebShell::OnLinkClickSync(nsIContent *aContent,
*aRequest = nsnull;
}
if (mFiredUnloadEvent) {
return NS_OK;
}
{
// defer to an external protocol handler if necessary...
nsCOMPtr<nsIExternalProtocolService> extProtService = do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID);