From a5ed4e41140784b09a313d3acf735f3a6b38df70 Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Tue, 1 Feb 2011 09:19:35 -0800 Subject: [PATCH] Fix bug 691359. r=jst@mozilla.com, a=blocker --- dom/base/nsDOMClassInfo.cpp | 18 ++++------ dom/base/nsGlobalWindow.cpp | 11 +++---- dom/base/nsGlobalWindow.h | 2 +- dom/base/nsHistory.cpp | 66 +++++++++++++++++++++++-------------- dom/base/nsHistory.h | 20 ++++++++--- 5 files changed, 69 insertions(+), 48 deletions(-) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 81154dd4d7fc..08b1719980d3 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -10041,20 +10041,14 @@ nsHistorySH::PreCreate(nsISupports *nativeObj, JSContext *cx, JSObject *globalObj, JSObject **parentObj) { nsHistory *history = (nsHistory *)nativeObj; - nsIDocShell *ds = history->GetDocShell(); - if (!ds) { - NS_WARNING("Refusing to create a history object in the wrong scope"); - return NS_ERROR_UNEXPECTED; + nsCOMPtr innerWindow; + history->GetWindow(getter_AddRefs(innerWindow)); + if (!innerWindow) { + NS_WARNING("refusing to create history object in the wrong scope"); + return NS_ERROR_FAILURE; } - nsCOMPtr sgo = do_GetInterface(ds); - if (!sgo) { - NS_WARNING("Refusing to create a history object in the wrong scope because the " - "docshell is being destroyed"); - return NS_ERROR_UNEXPECTED; - } - - *parentObj = sgo->GetGlobalJSObject(); + *parentObj = static_cast(innerWindow.get())->FastGetGlobalJSObject(); return NS_OK; } diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 6d9263ea68b2..8fb122b9ad9c 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -1084,7 +1084,6 @@ nsGlobalWindow::CleanUp(PRBool aIgnoreModalDialog) mNavigator = nsnull; mScreen = nsnull; - mHistory = nsnull; mMenubar = nsnull; mToolbar = nsnull; mLocationbar = nsnull; @@ -1092,6 +1091,7 @@ nsGlobalWindow::CleanUp(PRBool aIgnoreModalDialog) mStatusbar = nsnull; mScrollbars = nsnull; mLocation = nsnull; + mHistory = nsnull; mFrames = nsnull; mApplicationCache = nsnull; mIndexedDB = nsnull; @@ -1236,6 +1236,7 @@ nsGlobalWindow::FreeInnerObjects(PRBool aClearScope) } mLocation = nsnull; + mHistory = nsnull; if (mDocument) { NS_ASSERTION(mDoc, "Why is mDoc null?"); @@ -2388,8 +2389,6 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell) if (mNavigator) mNavigator->SetDocShell(aDocShell); - if (mHistory) - mHistory->SetDocShell(aDocShell); if (mFrames) mFrames->SetDocShell(aDocShell); if (mScreen) @@ -2910,12 +2909,12 @@ nsGlobalWindow::GetScreen(nsIDOMScreen** aScreen) NS_IMETHODIMP nsGlobalWindow::GetHistory(nsIDOMHistory** aHistory) { - FORWARD_TO_OUTER(GetHistory, (aHistory), NS_ERROR_NOT_INITIALIZED); + FORWARD_TO_INNER(GetHistory, (aHistory), NS_ERROR_NOT_INITIALIZED); *aHistory = nsnull; - if (!mHistory && mDocShell) { - mHistory = new nsHistory(mDocShell); + if (!mHistory) { + mHistory = new nsHistory(this); if (!mHistory) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index f99d5c62b889..3aa0243f8ae2 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -902,7 +902,6 @@ protected: nsCOMPtr mArgumentsOrigin; nsRefPtr mNavigator; nsRefPtr mScreen; - nsRefPtr mHistory; nsRefPtr mFrames; nsRefPtr mMenubar; nsRefPtr mToolbar; @@ -933,6 +932,7 @@ protected: PRUint32 mTimeoutPublicIdCounter; PRUint32 mTimeoutFiringDepth; nsRefPtr mLocation; + nsRefPtr mHistory; // Holder of the dummy java plugin, used to expose window.java and // window.packages. diff --git a/dom/base/nsHistory.cpp b/dom/base/nsHistory.cpp index 18b13f0f9150..1f1b7c528310 100644 --- a/dom/base/nsHistory.cpp +++ b/dom/base/nsHistory.cpp @@ -1,4 +1,5 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 sw=2 et tw=78: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -68,7 +69,8 @@ static const char* sAllowReplaceStatePrefStr = // // History class implementation // -nsHistory::nsHistory(nsIDocShell* aDocShell) : mDocShell(aDocShell) +nsHistory::nsHistory(nsPIDOMWindow* aInnerWindow) + : mInnerWindow(do_GetWeakReference(aInnerWindow)) { } @@ -91,19 +93,13 @@ NS_IMPL_ADDREF(nsHistory) NS_IMPL_RELEASE(nsHistory) -void -nsHistory::SetDocShell(nsIDocShell *aDocShell) -{ - mDocShell = aDocShell; // Weak Reference -} - NS_IMETHODIMP nsHistory::GetLength(PRInt32* aLength) { nsCOMPtr sHistory; // Get session History from docshell - GetSessionHistoryFromDocShell(mDocShell, getter_AddRefs(sHistory)); + GetSessionHistoryFromDocShell(GetDocShell(), getter_AddRefs(sHistory)); NS_ENSURE_TRUE(sHistory, NS_ERROR_FAILURE); return sHistory->GetCount(aLength); } @@ -111,12 +107,15 @@ nsHistory::GetLength(PRInt32* aLength) NS_IMETHODIMP nsHistory::GetCurrent(nsAString& aCurrent) { + if (!nsContentUtils::IsCallerTrustedForRead()) + return NS_ERROR_DOM_SECURITY_ERR; + PRInt32 curIndex=0; nsCAutoString curURL; nsCOMPtr sHistory; // Get SessionHistory from docshell - GetSessionHistoryFromDocShell(mDocShell, getter_AddRefs(sHistory)); + GetSessionHistoryFromDocShell(GetDocShell(), getter_AddRefs(sHistory)); NS_ENSURE_TRUE(sHistory, NS_ERROR_FAILURE); // Get the current index at session History @@ -140,12 +139,15 @@ nsHistory::GetCurrent(nsAString& aCurrent) NS_IMETHODIMP nsHistory::GetPrevious(nsAString& aPrevious) { + if (!nsContentUtils::IsCallerTrustedForRead()) + return NS_ERROR_DOM_SECURITY_ERR; + PRInt32 curIndex; nsCAutoString prevURL; nsCOMPtr sHistory; // Get session History from docshell - GetSessionHistoryFromDocShell(mDocShell, getter_AddRefs(sHistory)); + GetSessionHistoryFromDocShell(GetDocShell(), getter_AddRefs(sHistory)); NS_ENSURE_TRUE(sHistory, NS_ERROR_FAILURE); // Get the current index at session History @@ -174,7 +176,7 @@ nsHistory::GetNext(nsAString& aNext) nsCOMPtr sHistory; // Get session History from docshell - GetSessionHistoryFromDocShell(mDocShell, getter_AddRefs(sHistory)); + GetSessionHistoryFromDocShell(GetDocShell(), getter_AddRefs(sHistory)); NS_ENSURE_TRUE(sHistory, NS_ERROR_FAILURE); // Get the current index at session History @@ -200,7 +202,7 @@ nsHistory::Back() { nsCOMPtr sHistory; - GetSessionHistoryFromDocShell(mDocShell, getter_AddRefs(sHistory)); + GetSessionHistoryFromDocShell(GetDocShell(), getter_AddRefs(sHistory)); NS_ENSURE_TRUE(sHistory, NS_ERROR_FAILURE); //QI SHistory to WebNavigation @@ -216,7 +218,7 @@ nsHistory::Forward() { nsCOMPtr sHistory; - GetSessionHistoryFromDocShell(mDocShell, getter_AddRefs(sHistory)); + GetSessionHistoryFromDocShell(GetDocShell(), getter_AddRefs(sHistory)); NS_ENSURE_TRUE(sHistory, NS_ERROR_FAILURE); //QI SHistory to WebNavigation @@ -231,7 +233,7 @@ NS_IMETHODIMP nsHistory::Go(PRInt32 aDelta) { if (aDelta == 0) { - nsCOMPtr window(do_GetInterface(mDocShell)); + nsCOMPtr window(do_GetInterface(GetDocShell())); if (window && window->IsHandlingResizeEvent()) { // history.go(0) (aka location.reload()) was called on a window @@ -257,7 +259,7 @@ nsHistory::Go(PRInt32 aDelta) nsCOMPtr session_history; - GetSessionHistoryFromDocShell(mDocShell, getter_AddRefs(session_history)); + GetSessionHistoryFromDocShell(GetDocShell(), getter_AddRefs(session_history)); NS_ENSURE_TRUE(session_history, NS_ERROR_FAILURE); // QI SHistory to nsIWebNavigation @@ -288,15 +290,22 @@ nsHistory::PushState(nsIVariant *aData, const nsAString& aTitle, if (!nsContentUtils::GetBoolPref(sAllowPushStatePrefStr, PR_FALSE)) return NS_OK; - NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); + nsCOMPtr win(do_QueryReferent(mInnerWindow)); + if (!win) + return NS_ERROR_NOT_AVAILABLE; + + if (!nsContentUtils::CanCallerAccess(win->GetOuterWindow())) + return NS_ERROR_DOM_SECURITY_ERR; // AddState might run scripts, so we need to hold a strong reference to the // docShell here to keep it from going away. - nsCOMPtr docShell = mDocShell; + nsCOMPtr docShell = win->GetDocShell(); + + NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); // PR_FALSE tells the docshell to add a new history entry instead of // modifying the current one. - nsresult rv = mDocShell->AddState(aData, aTitle, aURL, PR_FALSE); + nsresult rv = docShell->AddState(aData, aTitle, aURL, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; @@ -310,15 +319,22 @@ nsHistory::ReplaceState(nsIVariant *aData, const nsAString& aTitle, if (!nsContentUtils::GetBoolPref(sAllowReplaceStatePrefStr, PR_FALSE)) return NS_OK; - NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); + nsCOMPtr win(do_QueryReferent(mInnerWindow)); + if (!win) + return NS_ERROR_NOT_AVAILABLE; - // As in PushState(), we need to keep a strong reference to the docShell - // here. - nsCOMPtr docShell = mDocShell; + if (!nsContentUtils::CanCallerAccess(win->GetOuterWindow())) + return NS_ERROR_DOM_SECURITY_ERR; + + // AddState might run scripts, so we need to hold a strong reference to the + // docShell here to keep it from going away. + nsCOMPtr docShell = win->GetDocShell(); + + NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); // PR_TRUE tells the docshell to modify the current SHEntry, rather than // create a new one. - return mDocShell->AddState(aData, aTitle, aURL, PR_TRUE); + return docShell->AddState(aData, aTitle, aURL, PR_TRUE); } NS_IMETHODIMP @@ -332,7 +348,7 @@ nsHistory::Item(PRUint32 aIndex, nsAString& aReturn) nsresult rv = NS_OK; nsCOMPtr session_history; - GetSessionHistoryFromDocShell(mDocShell, getter_AddRefs(session_history)); + GetSessionHistoryFromDocShell(GetDocShell(), getter_AddRefs(session_history)); NS_ENSURE_TRUE(session_history, NS_ERROR_FAILURE); nsCOMPtr sh_entry; @@ -367,7 +383,7 @@ nsHistory::GetSessionHistoryFromDocShell(nsIDocShell * aDocShell, */ // QI mDocShell to nsIDocShellTreeItem - nsCOMPtr dsTreeItem(do_QueryInterface(mDocShell)); + nsCOMPtr dsTreeItem(do_QueryInterface(aDocShell)); NS_ENSURE_TRUE(dsTreeItem, NS_ERROR_FAILURE); // Get the root DocShell from it diff --git a/dom/base/nsHistory.h b/dom/base/nsHistory.h index 8daa825cde63..c345f8bbf88a 100644 --- a/dom/base/nsHistory.h +++ b/dom/base/nsHistory.h @@ -1,4 +1,5 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 sw=2 et tw=79: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -42,6 +43,8 @@ #include "nscore.h" #include "nsIScriptContext.h" #include "nsISHistory.h" +#include "nsIWeakReference.h" +#include "nsPIDOMWindow.h" class nsIDocShell; @@ -49,7 +52,7 @@ class nsIDocShell; class nsHistory : public nsIDOMHistory { public: - nsHistory(nsIDocShell* aDocShell); + nsHistory(nsPIDOMWindow* aInnerWindow); virtual ~nsHistory(); // nsISupports @@ -58,14 +61,23 @@ public: // nsIDOMHistory NS_DECL_NSIDOMHISTORY - nsIDocShell *GetDocShell() { return mDocShell; } - void SetDocShell(nsIDocShell *aDocShell); + nsIDocShell *GetDocShell() { + nsCOMPtr win(do_QueryReferent(mInnerWindow)); + if (!win) + return nsnull; + return win->GetDocShell(); + } + + void GetWindow(nsPIDOMWindow **aWindow) { + nsCOMPtr win(do_QueryReferent(mInnerWindow)); + *aWindow = win.forget().get(); + } protected: nsresult GetSessionHistoryFromDocShell(nsIDocShell * aDocShell, nsISHistory ** aReturn); - nsIDocShell* mDocShell; + nsCOMPtr mInnerWindow; }; #endif /* nsHistory_h___ */