Allow certain restricted loads in unload events. Bug 409888, r+sr=jst

git-svn-id: svn://10.0.0.236/trunk@243999 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
bzbarsky%mit.edu
2008-01-25 20:31:44 +00:00
parent 2c0808c1ca
commit 5982fb6110
3 changed files with 129 additions and 9 deletions

View File

@@ -678,7 +678,9 @@ nsDocShell::LoadURI(nsIURI * aURI,
PRUint32 aLoadFlags,
PRBool aFirstParty)
{
if (!IsNavigationAllowed()) {
// Note: we allow loads to get through here even if mFiredUnloadEvent is
// true; that case will get handled in LoadInternal or LoadHistoryEntry.
if (IsPrintingOrPP()) {
return NS_OK; // JS may not handle returning of an error code
}
nsresult rv;
@@ -3603,6 +3605,10 @@ nsDocShell::Destroy()
}
}
// Make sure to blow away our mLoadingURI just in case. No loads
// from inside this pagehide.
mLoadingURI = nsnull;
// Fire unload event before we blow anything away.
(void) FirePageHideNotification(PR_TRUE);
@@ -5138,6 +5144,10 @@ nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal)
mSavingOldViewer = CanSavePresentation(LOAD_NORMAL, nsnull, nsnull);
// Make sure to blow away our mLoadingURI just in case. No loads
// from inside this pagehide.
mLoadingURI = nsnull;
// Notify the current document that it is about to be unloaded!!
//
// It is important to fire the unload() notification *before* any state
@@ -5554,6 +5564,10 @@ nsDocShell::RestoreFromHistory()
// pagehide or unload.
nsCOMPtr<nsISHEntry> origLSHE = mLSHE;
// Make sure to blow away our mLoadingURI just in case. No loads
// from inside this pagehide.
mLoadingURI = nsnull;
// Notify the old content viewer that it's being hidden.
FirePageHideNotification(!mSavingOldViewer);
@@ -5916,7 +5930,14 @@ nsDocShell::CreateContentViewer(const char *aContentType,
mSavingOldViewer = CanSavePresentation(mLoadType, request, doc);
}
NS_ASSERTION(!mLoadingURI, "Re-entering unload?");
nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(request);
if (aOpenedChannel) {
aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI));
}
FirePageHideNotification(!mSavingOldViewer);
mLoadingURI = nsnull;
// Set mFiredUnloadEvent = PR_FALSE so that the unload handler for the
// *new* document will fire.
@@ -5927,8 +5948,6 @@ nsDocShell::CreateContentViewer(const char *aContentType,
// notifications before we've called Embed(). See bug 284993.
mURIResultedInDocument = PR_TRUE;
nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(request);
PRBool onLocationChangeNeeded = OnLoadingSite(aOpenedChannel, PR_FALSE);
// let's try resetting the load group if we need to...
@@ -6450,6 +6469,60 @@ nsDocShell::CheckLoadingPermissions()
//*****************************************************************************
// nsDocShell: Site Loading
//*****************************************************************************
class InternalLoadEvent : public nsRunnable
{
public:
InternalLoadEvent(nsDocShell* aDocShell, nsIURI * aURI, nsIURI * aReferrer,
nsISupports * aOwner, PRUint32 aFlags,
const PRUnichar *aWindowTarget, const char* aTypeHint,
nsIInputStream * aPostData,
nsIInputStream * aHeadersData, PRUint32 aLoadType,
nsISHEntry * aSHEntry, PRBool aFirstParty) :
mDocShell(aDocShell),
mURI(aURI),
mReferrer(aReferrer),
mOwner(aOwner),
mFlags(aFlags),
mPostData(aPostData),
mHeadersData(aHeadersData),
mLoadType(aLoadType),
mSHEntry(aSHEntry),
mFirstParty(aFirstParty)
{
// Make sure to keep null things null as needed
if (aWindowTarget) {
mWindowTarget = aWindowTarget;
}
if (aTypeHint) {
mTypeHint = aTypeHint;
}
}
NS_IMETHOD Run() {
return mDocShell->InternalLoad(mURI, mReferrer, mOwner, mFlags,
mWindowTarget.get(), mTypeHint.get(),
mPostData, mHeadersData, mLoadType,
mSHEntry, mFirstParty, nsnull, nsnull);
}
private:
nsRefPtr<nsDocShell> mDocShell;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIURI> mReferrer;
nsCOMPtr<nsISupports> mOwner;
PRUint32 mFlags;
// Use IDL strings so .get() returns null by default
nsXPIDLString mWindowTarget;
nsXPIDLCString mTypeHint;
nsCOMPtr<nsIInputStream> mPostData;
nsCOMPtr<nsIInputStream> mHeadersData;
PRUint32 mLoadType;
nsCOMPtr<nsISHEntry> mSHEntry;
PRBool mFirstParty;
};
NS_IMETHODIMP
nsDocShell::InternalLoad(nsIURI * aURI,
nsIURI * aReferrer,
@@ -6465,10 +6538,6 @@ nsDocShell::InternalLoad(nsIURI * aURI,
nsIDocShell** aDocShell,
nsIRequest** aRequest)
{
if (mFiredUnloadEvent) {
return NS_OK; // JS may not handle returning of an error code
}
nsresult rv = NS_OK;
#ifdef PR_LOGGING
@@ -6496,6 +6565,21 @@ nsDocShell::InternalLoad(nsIURI * aURI,
NS_ENSURE_TRUE(!mIsBeingDestroyed, NS_ERROR_NOT_AVAILABLE);
if (mFiredUnloadEvent) {
if (IsOKToLoadURI(aURI)) {
// Do this asynchronously
nsCOMPtr<nsIRunnable> ev =
new InternalLoadEvent(this, aURI, aReferrer, aOwner, aFlags,
aWindowTarget, aTypeHint,
aPostData, aHeadersData, aLoadType,
aSHEntry, aFirstParty);
return NS_DispatchToCurrentThread(ev);
}
// Just ignore this load attempt
return NS_OK;
}
// wyciwyg urls can only be loaded through history. Any normal load of
// wyciwyg through docshell is illegal. Disallow such loads.
if (aLoadType & LOAD_CMD_NORMAL) {
@@ -8064,6 +8148,10 @@ nsDocShell::AddToSessionHistory(nsIURI * aURI,
NS_IMETHODIMP
nsDocShell::LoadHistoryEntry(nsISHEntry * aEntry, PRUint32 aLoadType)
{
if (!IsNavigationAllowed()) {
return NS_OK;
}
nsCOMPtr<nsIURI> uri;
nsCOMPtr<nsIInputStream> postData;
nsCOMPtr<nsIURI> referrerURI;
@@ -9211,6 +9299,26 @@ nsDocShell::IsAboutBlank(nsIURI* aURI)
return str.EqualsLiteral("about:blank");
}
PRBool
nsDocShell::IsOKToLoadURI(nsIURI* aURI)
{
NS_PRECONDITION(aURI, "Must have a URI!");
if (!mFiredUnloadEvent) {
return PR_TRUE;
}
if (!mLoadingURI) {
return PR_FALSE;
}
nsCOMPtr<nsIScriptSecurityManager> secMan =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
return
secMan &&
NS_SUCCEEDED(secMan->CheckSameOriginURI(aURI, mLoadingURI, PR_FALSE));
}
//*****************************************************************************
// nsClassifierCallback
//*****************************************************************************