diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 65b8d014a5a1..a8e9dc0a2e5d 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -6119,7 +6119,8 @@ nsDocShell::AddToSessionHistory(nsIURI * aURI, } else { // This is a subframe. - if (mLoadType != LOAD_NORMAL_REPLACE) + if ((mLoadType != LOAD_NORMAL_REPLACE) || + (mLoadType == LOAD_NORMAL_REPLACE && !mOSHE)) rv = AddChildSHEntry(nsnull, entry, mChildOffset); } diff --git a/dom/src/base/nsGlobalWindow.h b/dom/src/base/nsGlobalWindow.h index 33c24dbe6f28..f0370a5b0269 100644 --- a/dom/src/base/nsGlobalWindow.h +++ b/dom/src/base/nsGlobalWindow.h @@ -486,6 +486,7 @@ protected: nsresult GetSourceDocument(JSContext* cx, nsIDocument** aDocument); nsresult CheckURL(nsIURI *url, nsIDocShellLoadInfo** aLoadInfo); + nsresult FindUsableBaseURI(nsIURI * aBaseURI, nsIDocShell * aParent, nsIURI ** aUsableURI); nsIDocShell *mDocShell; // Weak Reference }; diff --git a/dom/src/base/nsLocation.cpp b/dom/src/base/nsLocation.cpp index 47c87ac6d093..fc9d286be816 100644 --- a/dom/src/base/nsLocation.cpp +++ b/dom/src/base/nsLocation.cpp @@ -65,7 +65,7 @@ #include "nsDOMError.h" #include "nsDOMClassInfo.h" #include "nsCRT.h" - +#include "nsIProtocolHandler.h" static nsresult GetDocumentCharacterSetForURI(const nsAString& aHref, nsACString& aCharset) { @@ -200,6 +200,63 @@ LocationImpl::CheckURL(nsIURI* aURI, nsIDocShellLoadInfo** aLoadInfo) return NS_OK; } +// Walk up the docshell hierarchy and find a usable base URI. Basically +// anything that would allow a relative uri. + +nsresult +LocationImpl::FindUsableBaseURI(nsIURI * aBaseURI, nsIDocShell * aParent, nsIURI ** aUsableURI) +{ + if (!aBaseURI || !aParent) + return NS_ERROR_FAILURE; + NS_ENSURE_ARG_POINTER(aUsableURI); + + *aUsableURI = nsnull; + nsresult rv = NS_OK; + nsCOMPtr parentDS = aParent; + nsCOMPtr baseURI = aBaseURI; + nsCOMPtr ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv)); + + while(NS_SUCCEEDED(rv) && baseURI && ioService) { + // Check if the current base uri supports relative uris. + // We make this check by looking at the protocol flags of + // the protocol handler. If the protocol flags has URI_NORELATIVE, + // it means that the base uri does not support relative uris. + nsCAutoString scheme; + baseURI->GetScheme(scheme); + nsCOMPtr protocolHandler; + // Get the protocol handler for the base uri. + ioService->GetProtocolHandler(scheme.get(), getter_AddRefs(protocolHandler)); + if (!protocolHandler) + return NS_ERROR_FAILURE; + PRUint32 pFlags; // Is there a default value for the protocol flags? + protocolHandler->GetProtocolFlags(&pFlags); + if (!(pFlags & nsIProtocolHandler::URI_NORELATIVE)) { + *aUsableURI = baseURI; + NS_ADDREF(*aUsableURI); + return NS_OK; + } + + // Get the same type parent docshell + nsCOMPtr docShellAsTreeItem(do_QueryInterface(parentDS)); + if (!docShellAsTreeItem) + return NS_ERROR_FAILURE; + nsCOMPtr parentDSTreeItem; + docShellAsTreeItem->GetSameTypeParent(getter_AddRefs(parentDSTreeItem)); + nsCOMPtr webNav(do_QueryInterface(parentDSTreeItem)); + + // Get the parent docshell's uri + if (webNav) { + rv = webNav->GetCurrentURI(getter_AddRefs(baseURI)); + parentDS = do_QueryInterface(parentDSTreeItem); + } + else + return NS_ERROR_FAILURE; + } // while + + return rv; +} + + nsresult LocationImpl::GetURI(nsIURI** aURI) { @@ -475,13 +532,18 @@ LocationImpl::SetHrefWithBase(const nsAString& aHref, nsIURI* aBase, PRBool aReplace) { nsresult result; - nsCOMPtr newUri; + nsCOMPtr newUri, baseURI; + + // Make sure the base url is something that will be useful. + result = FindUsableBaseURI(aBase, mDocShell, getter_AddRefs(baseURI)); + if (!baseURI) + return NS_ERROR_FAILURE; nsCAutoString docCharset; if (NS_SUCCEEDED(GetDocumentCharacterSetForURI(aHref, docCharset))) - result = NS_NewURI(getter_AddRefs(newUri), aHref, docCharset.get(), aBase); + result = NS_NewURI(getter_AddRefs(newUri), aHref, docCharset.get(), baseURI); else - result = NS_NewURI(getter_AddRefs(newUri), aHref, nsnull, aBase); + result = NS_NewURI(getter_AddRefs(newUri), aHref, nsnull, baseURI); if (newUri && mDocShell) { nsCOMPtr loadInfo;