Copied from upstream: https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/532544c91db7 # HG changeset patch # User Dragana Damjanovic # Date 1456962626 28800 # Node ID 532544c91db7f13c39be1b7b7c4461cd03126e9c # Parent f4220254d5bd0851a439467da39ba431e0ce2804 Bug 1185256 - Save originURI to the history. r=bz ba=ritu MozReview-Commit-ID: Lvh9C84RQUc diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -1020,16 +1020,17 @@ nsDocShell::DestroyChildren() //***************************************************************************** // nsDocShell::nsISupports //***************************************************************************** NS_IMPL_ADDREF_INHERITED(nsDocShell, nsDocLoader) NS_IMPL_RELEASE_INHERITED(nsDocShell, nsDocLoader) NS_INTERFACE_MAP_BEGIN(nsDocShell) + NS_INTERFACE_MAP_ENTRY(nsIDocShell_ESR38_2) NS_INTERFACE_MAP_ENTRY(nsIDocShell_ESR38) NS_INTERFACE_MAP_ENTRY(nsIDocShell) NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem) NS_INTERFACE_MAP_ENTRY(nsIWebNavigation) NS_INTERFACE_MAP_ENTRY(nsIBaseWindow) NS_INTERFACE_MAP_ENTRY(nsIScrollable) NS_INTERFACE_MAP_ENTRY(nsITextScroll) NS_INTERFACE_MAP_ENTRY(nsIDocCharset) @@ -1372,16 +1373,17 @@ nsDocShell::LoadURI(nsIURI* aURI, return NS_OK; // JS may not handle returning of an error code } if (DoAppRedirectIfNeeded(aURI, aLoadInfo, aFirstParty)) { return NS_OK; } nsCOMPtr referrer; + nsCOMPtr originalURI; nsCOMPtr postStream; nsCOMPtr headersStream; nsCOMPtr owner; bool inheritOwner = false; bool ownerIsExplicit = false; bool sendReferrer = true; uint32_t referrerPolicy = mozilla::net::RP_Default; bool isSrcdoc = false; @@ -1398,16 +1400,20 @@ nsDocShell::LoadURI(nsIURI* aURI, if (!StartupTimeline::HasRecord(StartupTimeline::FIRST_LOAD_URI) && mItemType == typeContent && !NS_IsAboutBlank(aURI)) { StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI); } // Extract the info from the DocShellLoadInfo struct... if (aLoadInfo) { aLoadInfo->GetReferrer(getter_AddRefs(referrer)); + nsCOMPtr liESR38 = do_QueryInterface(aLoadInfo); + if (liESR38) { + liESR38->GetOriginalURI(getter_AddRefs(originalURI)); + } nsDocShellInfoLoadType lt = nsIDocShellLoadInfo::loadNormal; aLoadInfo->GetLoadType(<); // Get the appropriate loadType from nsIDocShellLoadInfo type loadType = ConvertDocShellLoadInfoToLoadType(lt); aLoadInfo->GetOwner(getter_AddRefs(owner)); aLoadInfo->GetInheritOwner(&inheritOwner); @@ -1652,34 +1658,35 @@ nsDocShell::LoadURI(nsIURI* aURI, if (aLoadFlags & LOAD_FLAGS_FORCE_ALLOW_COOKIES) { flags |= INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES; } if (isSrcdoc) { flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC; } - return InternalLoad(aURI, - referrer, - referrerPolicy, - owner, - flags, - target.get(), - nullptr, // No type hint - NullString(), // No forced download - postStream, - headersStream, - loadType, - nullptr, // No SHEntry - aFirstParty, - srcdoc, - sourceDocShell, - baseURI, - nullptr, // No nsIDocShell - nullptr); // No nsIRequest + return InternalLoad2(aURI, + originalURI, + referrer, + referrerPolicy, + owner, + flags, + target.get(), + nullptr, // No type hint + NullString(), // No forced download + postStream, + headersStream, + loadType, + nullptr, // No SHEntry + aFirstParty, + srcdoc, + sourceDocShell, + baseURI, + nullptr, // No nsIDocShell + nullptr); // No nsIRequest } NS_IMETHODIMP nsDocShell::LoadStream(nsIInputStream* aStream, nsIURI* aURI, const nsACString& aContentType, const nsACString& aContentCharset, nsIDocShellLoadInfo* aLoadInfo) { @@ -5398,21 +5405,21 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, // end of the URL, so append it last. errorPageUrl.AppendLiteral("&d="); errorPageUrl.AppendASCII(escapedDescription.get()); nsCOMPtr errorPageURI; rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl); NS_ENSURE_SUCCESS(rv, rv); - return InternalLoad(errorPageURI, nullptr, mozilla::net::RP_Default, - nullptr, INTERNAL_LOAD_FLAGS_INHERIT_OWNER, nullptr, - nullptr, NullString(), nullptr, nullptr, LOAD_ERROR_PAGE, - nullptr, true, NullString(), this, nullptr, nullptr, - nullptr); + return InternalLoad2(errorPageURI, nullptr, nullptr, mozilla::net::RP_Default, + nullptr, INTERNAL_LOAD_FLAGS_INHERIT_OWNER, nullptr, + nullptr, NullString(), nullptr, nullptr, LOAD_ERROR_PAGE, + nullptr, true, NullString(), this, nullptr, nullptr, + nullptr); } NS_IMETHODIMP nsDocShell::Reload(uint32_t aReloadFlags) { if (!IsNavigationAllowed()) { return NS_OK; // JS may not handle returning of an error code } @@ -5448,44 +5455,54 @@ nsDocShell::Reload(uint32_t aReloadFlags nsCOMPtr doc(GetDocument()); // Do not inherit owner from document uint32_t flags = INTERNAL_LOAD_FLAGS_NONE; nsAutoString srcdoc; nsIPrincipal* principal = nullptr; nsAutoString contentTypeHint; nsCOMPtr baseURI; + nsCOMPtr originalURI; if (doc) { principal = doc->NodePrincipal(); doc->GetContentType(contentTypeHint); if (doc->IsSrcdocDocument()) { doc->GetSrcdocData(srcdoc); flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC; baseURI = doc->GetBaseURI(); } - } - rv = InternalLoad(mCurrentURI, - mReferrerURI, - mReferrerPolicy, - principal, - flags, - nullptr, // No window target - NS_LossyConvertUTF16toASCII(contentTypeHint).get(), - NullString(), // No forced download - nullptr, // No post data - nullptr, // No headers data - loadType, // Load type - nullptr, // No SHEntry - true, - srcdoc, // srcdoc argument for iframe - this, // For reloads we are the source - baseURI, - nullptr, // No nsIDocShell - nullptr); // No nsIRequest + nsCOMPtr chan = doc->GetChannel(); + if (chan) { + nsCOMPtr httpChan(do_QueryInterface(chan)); + if (httpChan) { + httpChan->GetOriginalURI(getter_AddRefs(originalURI)); + } + } + } + + rv = InternalLoad2(mCurrentURI, + originalURI, + mReferrerURI, + mReferrerPolicy, + principal, + flags, + nullptr, // No window target + NS_LossyConvertUTF16toASCII(contentTypeHint).get(), + NullString(), // No forced download + nullptr, // No post data + nullptr, // No headers data + loadType, // Load type + nullptr, // No SHEntry + true, + srcdoc, // srcdoc argument for iframe + this, // For reloads we are the source + baseURI, + nullptr, // No nsIDocShell + nullptr); // No nsIRequest } return rv; } NS_IMETHODIMP nsDocShell::Stop(uint32_t aStopFlags) { @@ -9463,27 +9480,28 @@ CopyFavicon(nsIURI* aOldURI, nsIURI* aNe #endif } } // anonymous namespace class InternalLoadEvent : public nsRunnable { public: - InternalLoadEvent(nsDocShell* aDocShell, nsIURI* aURI, + InternalLoadEvent(nsDocShell* aDocShell, nsIURI* aURI, nsIURI* aOriginalURI, nsIURI* aReferrer, uint32_t aReferrerPolicy, nsISupports* aOwner, uint32_t aFlags, const char* aTypeHint, nsIInputStream* aPostData, nsIInputStream* aHeadersData, uint32_t aLoadType, nsISHEntry* aSHEntry, bool aFirstParty, const nsAString& aSrcdoc, nsIDocShell* aSourceDocShell, nsIURI* aBaseURI) : mSrcdoc(aSrcdoc) , mDocShell(aDocShell) , mURI(aURI) + , mOriginalURI(aOriginalURI) , mReferrer(aReferrer) , mReferrerPolicy(aReferrerPolicy) , mOwner(aOwner) , mPostData(aPostData) , mHeadersData(aHeadersData) , mSHEntry(aSHEntry) , mFlags(aFlags) , mLoadType(aLoadType) @@ -9494,34 +9512,36 @@ public: // Make sure to keep null things null as needed if (aTypeHint) { mTypeHint = aTypeHint; } } NS_IMETHOD Run() { - return mDocShell->InternalLoad(mURI, mReferrer, - mReferrerPolicy, - mOwner, mFlags, - nullptr, mTypeHint.get(), - NullString(), mPostData, mHeadersData, - mLoadType, mSHEntry, mFirstParty, - mSrcdoc, mSourceDocShell, mBaseURI, - nullptr, nullptr); + return mDocShell->InternalLoad2(mURI, mOriginalURI, + mReferrer, + mReferrerPolicy, + mOwner, mFlags, + nullptr, mTypeHint.get(), + NullString(), mPostData, mHeadersData, + mLoadType, mSHEntry, mFirstParty, + mSrcdoc, mSourceDocShell, mBaseURI, + nullptr, nullptr); } private: // Use IDL strings so .get() returns null by default nsXPIDLString mWindowTarget; nsXPIDLCString mTypeHint; nsString mSrcdoc; nsRefPtr mDocShell; nsCOMPtr mURI; + nsCOMPtr mOriginalURI; nsCOMPtr mReferrer; uint32_t mReferrerPolicy; nsCOMPtr mOwner; nsCOMPtr mPostData; nsCOMPtr mHeadersData; nsCOMPtr mSHEntry; uint32_t mFlags; uint32_t mLoadType; @@ -9584,16 +9604,43 @@ nsDocShell::InternalLoad(nsIURI* aURI, nsISHEntry* aSHEntry, bool aFirstParty, const nsAString& aSrcdoc, nsIDocShell* aSourceDocShell, nsIURI* aBaseURI, nsIDocShell** aDocShell, nsIRequest** aRequest) { + return InternalLoad2(aURI, nullptr, aReferrer, aReferrerPolicy, aOwner, + aFlags, aWindowTarget, aTypeHint, aFileName, aPostData, + aHeadersData, aLoadType, aSHEntry, aFirstParty, aSrcdoc, + aSourceDocShell, aBaseURI, aDocShell, aRequest); +} + +NS_IMETHODIMP +nsDocShell::InternalLoad2(nsIURI* aURI, + nsIURI* aOriginalURI, + nsIURI* aReferrer, + uint32_t aReferrerPolicy, + nsISupports* aOwner, + uint32_t aFlags, + const char16_t* aWindowTarget, + const char* aTypeHint, + const nsAString& aFileName, + nsIInputStream* aPostData, + nsIInputStream* aHeadersData, + uint32_t aLoadType, + nsISHEntry* aSHEntry, + bool aFirstParty, + const nsAString& aSrcdoc, + nsIDocShell* aSourceDocShell, + nsIURI* aBaseURI, + nsIDocShell** aDocShell, + nsIRequest** aRequest) +{ nsresult rv = NS_OK; mOriginalUriString.Truncate(); #ifdef PR_LOGGING if (gDocShellLeakLog && PR_LOG_TEST(gDocShellLeakLog, PR_LOG_DEBUG)) { nsAutoCString spec; if (aURI) { aURI->GetSpec(spec); @@ -9831,34 +9878,58 @@ nsDocShell::InternalLoad(nsIURI* aURI, targetDocShell = do_QueryInterface(webNav); } // // Transfer the load to the target DocShell... Pass nullptr as the // window target name from to prevent recursive retargeting! // if (NS_SUCCEEDED(rv) && targetDocShell) { - rv = targetDocShell->InternalLoad(aURI, - aReferrer, - aReferrerPolicy, - owner, - aFlags, - nullptr, // No window target - aTypeHint, - NullString(), // No forced download - aPostData, - aHeadersData, - aLoadType, - aSHEntry, - aFirstParty, - aSrcdoc, - aSourceDocShell, - aBaseURI, - aDocShell, - aRequest); + nsCOMPtr dsESR38 = do_QueryInterface(targetDocShell); + if (dsESR38) { + rv = dsESR38->InternalLoad2(aURI, + aOriginalURI, + aReferrer, + aReferrerPolicy, + owner, + aFlags, + nullptr, // No window target + aTypeHint, + NullString(), // No forced download + aPostData, + aHeadersData, + aLoadType, + aSHEntry, + aFirstParty, + aSrcdoc, + aSourceDocShell, + aBaseURI, + aDocShell, + aRequest); + } else { + rv = targetDocShell->InternalLoad(aURI, + aReferrer, + aReferrerPolicy, + owner, + aFlags, + nullptr, // No window target + aTypeHint, + NullString(), // No forced download + aPostData, + aHeadersData, + aLoadType, + aSHEntry, + aFirstParty, + aSrcdoc, + aSourceDocShell, + aBaseURI, + aDocShell, + aRequest); + } + if (rv == NS_ERROR_NO_CONTENT) { // XXXbz except we never reach this code! if (isNewWindow) { // // At this point, a new window has been created, but the // URI did not have any data associated with it... // // So, the best we can do, is to tear down the new window @@ -9913,17 +9984,17 @@ nsDocShell::InternalLoad(nsIURI* aURI, // the unload event also a replace load, so we don't // create extra history entries. if (LOAD_TYPE_HAS_FLAGS(aLoadType, LOAD_FLAGS_REPLACE_HISTORY)) { mLoadType = LOAD_NORMAL_REPLACE; } // Do this asynchronously nsCOMPtr ev = - new InternalLoadEvent(this, aURI, aReferrer, + new InternalLoadEvent(this, aURI, aOriginalURI, aReferrer, aReferrerPolicy, aOwner, aFlags, aTypeHint, aPostData, aHeadersData, aLoadType, aSHEntry, aFirstParty, aSrcdoc, aSourceDocShell, aBaseURI); return NS_DispatchToCurrentThread(ev); } // Just ignore this load attempt @@ -10371,17 +10442,17 @@ nsDocShell::InternalLoad(nsIURI* aURI, } net::PredictorLearn(aURI, nullptr, nsINetworkPredictor::LEARN_LOAD_TOPLEVEL, this); net::PredictorPredict(aURI, nullptr, nsINetworkPredictor::PREDICT_LOAD, this, nullptr); nsCOMPtr req; - rv = DoURILoad(aURI, aReferrer, + rv = DoURILoad(aURI, aOriginalURI, aReferrer, !(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER), aReferrerPolicy, owner, aTypeHint, aFileName, aPostData, aHeadersData, aFirstParty, aDocShell, getter_AddRefs(req), (aFlags & INTERNAL_LOAD_FLAGS_FIRST_LOAD) != 0, (aFlags & INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER) != 0, (aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES) != 0, srcdoc, aBaseURI, contentType); @@ -10445,16 +10516,17 @@ nsDocShell::GetInheritedPrincipal(bool a return docPrincipal; } return nullptr; } nsresult nsDocShell::DoURILoad(nsIURI* aURI, + nsIURI* aOriginalURI, nsIURI* aReferrerURI, bool aSendReferrer, uint32_t aReferrerPolicy, nsISupports* aOwner, const char* aTypeHint, const nsAString& aFileName, nsIInputStream* aPostData, nsIInputStream* aHeadersData, @@ -10652,17 +10724,22 @@ nsDocShell::DoURILoad(nsIURI* aURI, } // Make sure to give the caller a channel if we managed to create one // This is important for correct error page/session history interaction if (aRequest) { NS_ADDREF(*aRequest = channel); } - channel->SetOriginalURI(aURI); + if (aOriginalURI) { + channel->SetOriginalURI(aOriginalURI); + } else { + channel->SetOriginalURI(aURI); + } + if (aTypeHint && *aTypeHint) { channel->SetContentType(nsDependentCString(aTypeHint)); mContentTypeHint = aTypeHint; } else { mContentTypeHint.Truncate(); } if (!aFileName.IsVoid()) { @@ -11624,16 +11701,20 @@ nsDocShell::AddState(JS::HandleSetURI(newURI); + nsCOMPtr entryESR38 = do_QueryInterface(newSHEntry); + if (entryESR38) { + entryESR38->SetOriginalURI(newURI); + } } // Step 4: Modify new/original session history entry and clear its POST // data, if there is any. newSHEntry->SetStateData(scContainer); newSHEntry->SetPostData(nullptr); // If this push/replaceState changed the document's current URI and the new @@ -11816,16 +11897,17 @@ nsDocShell::AddToSessionHistory(nsIURI* if (!entry) { return NS_ERROR_OUT_OF_MEMORY; } } // Get the post data & referrer nsCOMPtr inputStream; + nsCOMPtr originalURI; nsCOMPtr referrerURI; uint32_t referrerPolicy = mozilla::net::RP_Default; nsCOMPtr cacheKey; nsCOMPtr owner = aOwner; bool expired = false; bool discardLayoutState = false; nsCOMPtr cacheChannel; if (aChannel) { @@ -11843,16 +11925,17 @@ nsDocShell::AddToSessionHistory(nsIURI* if (!httpChannel) { GetHttpChannel(aChannel, getter_AddRefs(httpChannel)); } if (httpChannel) { nsCOMPtr uploadChannel(do_QueryInterface(httpChannel)); if (uploadChannel) { uploadChannel->GetUploadStream(getter_AddRefs(inputStream)); } + httpChannel->GetOriginalURI(getter_AddRefs(originalURI)); httpChannel->GetReferrer(getter_AddRefs(referrerURI)); httpChannel->GetReferrerPolicy(&referrerPolicy); discardLayoutState = ShouldDiscardLayoutState(httpChannel); } aChannel->GetOwner(getter_AddRefs(owner)); if (!owner) { nsCOMPtr loadInfo; @@ -11875,16 +11958,21 @@ nsDocShell::AddToSessionHistory(nsIURI* EmptyString(), // Title inputStream, // Post data stream nullptr, // LayoutHistory state cacheKey, // CacheKey mContentTypeHint, // Content-type owner, // Channel or provided owner mHistoryID, mDynamicallyCreated); + + nsCOMPtr entryESR38 = do_QueryInterface(entry); + if (entryESR38) { + entryESR38->SetOriginalURI(originalURI); + } entry->SetReferrerURI(referrerURI); entry->SetReferrerPolicy(referrerPolicy); nsCOMPtr inStrmChan = do_QueryInterface(aChannel); if (inStrmChan) { bool isSrcdocChannel; inStrmChan->GetIsSrcdocChannel(&isSrcdocChannel); if (isSrcdocChannel) { nsAutoString srcdoc; @@ -11976,25 +12064,32 @@ nsDocShell::AddToSessionHistory(nsIURI* nsresult nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType) { if (!IsNavigationAllowed()) { return NS_OK; } nsCOMPtr uri; + nsCOMPtr originalURI; nsCOMPtr postData; nsCOMPtr referrerURI; uint32_t referrerPolicy; nsAutoCString contentType; nsCOMPtr owner; NS_ENSURE_TRUE(aEntry, NS_ERROR_FAILURE); NS_ENSURE_SUCCESS(aEntry->GetURI(getter_AddRefs(uri)), NS_ERROR_FAILURE); + + nsCOMPtr entryESR38 = do_QueryInterface(aEntry); + if (entryESR38) { + NS_ENSURE_SUCCESS(entryESR38->GetOriginalURI(getter_AddRefs(originalURI)), + NS_ERROR_FAILURE); + } NS_ENSURE_SUCCESS(aEntry->GetReferrerURI(getter_AddRefs(referrerURI)), NS_ERROR_FAILURE); NS_ENSURE_SUCCESS(aEntry->GetReferrerPolicy(&referrerPolicy), NS_ERROR_FAILURE); NS_ENSURE_SUCCESS(aEntry->GetPostData(getter_AddRefs(postData)), NS_ERROR_FAILURE); NS_ENSURE_SUCCESS(aEntry->GetContentType(contentType), NS_ERROR_FAILURE); NS_ENSURE_SUCCESS(aEntry->GetOwner(getter_AddRefs(owner)), NS_ERROR_FAILURE); @@ -12064,34 +12159,35 @@ nsDocShell::LoadHistoryEntry(nsISHEntry* } else { srcdoc = NullString(); } // Passing nullptr as aSourceDocShell gives the same behaviour as before // aSourceDocShell was introduced. According to spec we should be passing // the source browsing context that was used when the history entry was // first created. bug 947716 has been created to address this issue. - rv = InternalLoad(uri, - referrerURI, - referrerPolicy, - owner, - flags, - nullptr, // No window target - contentType.get(), // Type hint - NullString(), // No forced file download - postData, // Post data stream - nullptr, // No headers stream - aLoadType, // Load type - aEntry, // SHEntry - true, - srcdoc, - nullptr, // Source docshell, see comment above - baseURI, - nullptr, // No nsIDocShell - nullptr); // No nsIRequest + rv = InternalLoad2(uri, + originalURI, + referrerURI, + referrerPolicy, + owner, + flags, + nullptr, // No window target + contentType.get(), // Type hint + NullString(), // No forced file download + postData, // Post data stream + nullptr, // No headers stream + aLoadType, // Load type + aEntry, // SHEntry + true, + srcdoc, + nullptr, // Source docshell, see comment above + baseURI, + nullptr, // No nsIDocShell + nullptr); // No nsIRequest return rv; } NS_IMETHODIMP nsDocShell::GetShouldSaveLayoutState(bool* aShould) { *aShould = false; if (mOSHE) { @@ -13527,35 +13623,36 @@ nsDocShell::OnLinkClickSync(nsIContent* // with it under InternalLoad; we do _not_ want to change the URI // our caller passed in. nsCOMPtr clonedURI; aURI->Clone(getter_AddRefs(clonedURI)); if (!clonedURI) { return NS_ERROR_OUT_OF_MEMORY; } - nsresult rv = InternalLoad(clonedURI, // New URI - referer, // Referer URI - refererPolicy, // Referer policy - aContent->NodePrincipal(), // Owner is our node's - // principal - flags, - target.get(), // Window target - NS_LossyConvertUTF16toASCII(typeHint).get(), - aFileName, // Download as file - aPostDataStream, // Post data stream - aHeadersDataStream, // Headers stream - LOAD_LINK, // Load type - nullptr, // No SHEntry - true, // first party site - NullString(), // No srcdoc - this, // We are the source - nullptr, // baseURI not needed - aDocShell, // DocShell out-param - aRequest); // Request out-param + nsresult rv = InternalLoad2(clonedURI, // New URI + nullptr, // Original URI + referer, // Referer URI + refererPolicy, // Referer policy + aContent->NodePrincipal(), // Owner is our node's + // principal + flags, + target.get(), // Window target + NS_LossyConvertUTF16toASCII(typeHint).get(), + aFileName, // Download as file + aPostDataStream, // Post data stream + aHeadersDataStream, // Headers stream + LOAD_LINK, // Load type + nullptr, // No SHEntry + true, // first party site + NullString(), // No srcdoc + this, // We are the source + nullptr, // baseURI not needed + aDocShell, // DocShell out-param + aRequest); // Request out-param if (NS_SUCCEEDED(rv)) { DispatchPings(aContent, aURI, referer, refererPolicy); } return rv; } NS_IMETHODIMP nsDocShell::OnOverLink(nsIContent* aContent, diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -132,17 +132,17 @@ enum eCharsetReloadState }; //***************************************************************************** //*** nsDocShell //***************************************************************************** class nsDocShell final : public nsDocLoader - , public nsIDocShell_ESR38 + , public nsIDocShell_ESR38_2 , public nsIWebNavigation , public nsIBaseWindow , public nsIScrollable , public nsITextScroll , public nsIDocCharset , public nsIContentViewerContainer , public nsIRefreshURI , public nsIWebProgressListener @@ -164,16 +164,17 @@ public: nsDocShell(); NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW virtual nsresult Init() override; NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIDOCSHELL_ESR38_2 NS_DECL_NSIDOCSHELL_ESR38 NS_DECL_NSIDOCSHELL NS_DECL_NSIDOCSHELLTREEITEM NS_DECL_NSIWEBNAVIGATION NS_DECL_NSIBASEWINDOW NS_DECL_NSISCROLLABLE NS_DECL_NSITEXTSCROLL NS_DECL_NSIDOCCHARSET @@ -312,17 +313,20 @@ protected: // at the parent. nsIPrincipal* GetInheritedPrincipal(bool aConsiderCurrentDocument); // Actually open a channel and perform a URI load. Note: whatever owner is // passed to this function will be set on the channel. Callers who wish to // not have an owner on the channel should just pass null. // If aSrcdoc is not void, the load will be considered as a srcdoc load, // and the contents of aSrcdoc will be loaded instead of aURI. + // aOriginalURI will be set as the originalURI on the channel that does the + // load. If aOriginalURI is null, aURI will be set as the originalURI. nsresult DoURILoad(nsIURI* aURI, + nsIURI* aOriginalURI, nsIURI* aReferrer, bool aSendReferrer, uint32_t aReferrerPolicy, nsISupports* aOwner, const char* aTypeHint, const nsAString& aFileName, nsIInputStream* aPostData, nsIInputStream* aHeadersData, diff --git a/docshell/base/nsDocShellLoadInfo.cpp b/docshell/base/nsDocShellLoadInfo.cpp --- a/docshell/base/nsDocShellLoadInfo.cpp +++ b/docshell/base/nsDocShellLoadInfo.cpp @@ -34,16 +34,17 @@ nsDocShellLoadInfo::~nsDocShellLoadInfo( // nsDocShellLoadInfo::nsISupports //***************************************************************************** NS_IMPL_ADDREF(nsDocShellLoadInfo) NS_IMPL_RELEASE(nsDocShellLoadInfo) NS_INTERFACE_MAP_BEGIN(nsDocShellLoadInfo) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocShellLoadInfo) + NS_INTERFACE_MAP_ENTRY(nsIDocShellLoadInfo_ESR38) NS_INTERFACE_MAP_ENTRY(nsIDocShellLoadInfo) NS_INTERFACE_MAP_END //***************************************************************************** // nsDocShellLoadInfo::nsIDocShellLoadInfo //***************************************************************************** NS_IMETHODIMP @@ -59,16 +60,33 @@ nsDocShellLoadInfo::GetReferrer(nsIURI** NS_IMETHODIMP nsDocShellLoadInfo::SetReferrer(nsIURI* aReferrer) { mReferrer = aReferrer; return NS_OK; } NS_IMETHODIMP +nsDocShellLoadInfo::GetOriginalURI(nsIURI** aOriginalURI) +{ + NS_ENSURE_ARG_POINTER(aOriginalURI); + + *aOriginalURI = mOriginalURI; + NS_IF_ADDREF(*aOriginalURI); + return NS_OK; +} + +NS_IMETHODIMP +nsDocShellLoadInfo::SetOriginalURI(nsIURI* aOriginalURI) +{ + mOriginalURI = aOriginalURI; + return NS_OK; +} + +NS_IMETHODIMP nsDocShellLoadInfo::GetOwner(nsISupports** aOwner) { NS_ENSURE_ARG_POINTER(aOwner); *aOwner = mOwner; NS_IF_ADDREF(*aOwner); return NS_OK; } diff --git a/docshell/base/nsDocShellLoadInfo.h b/docshell/base/nsDocShellLoadInfo.h --- a/docshell/base/nsDocShellLoadInfo.h +++ b/docshell/base/nsDocShellLoadInfo.h @@ -14,29 +14,31 @@ // Interfaces Needed #include "nsIDocShellLoadInfo.h" class nsIInputStream; class nsISHEntry; class nsIURI; class nsIDocShell; -class nsDocShellLoadInfo : public nsIDocShellLoadInfo +class nsDocShellLoadInfo : public nsIDocShellLoadInfo_ESR38 { public: nsDocShellLoadInfo(); NS_DECL_ISUPPORTS + NS_DECL_NSIDOCSHELLLOADINFO_ESR38 NS_DECL_NSIDOCSHELLLOADINFO protected: virtual ~nsDocShellLoadInfo(); protected: nsCOMPtr mReferrer; + nsCOMPtr mOriginalURI; nsCOMPtr mOwner; bool mInheritOwner; bool mOwnerIsExplicit; bool mSendReferrer; nsDocShellInfoReferrerPolicy mReferrerPolicy; nsDocShellInfoLoadType mLoadType; nsCOMPtr mSHEntry; nsString mTarget; diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl --- a/docshell/base/nsIDocShell.idl +++ b/docshell/base/nsIDocShell.idl @@ -1059,8 +1059,66 @@ interface nsIDocShell : nsIDocShellTreeI interface nsIDocShell_ESR38 : nsIDocShell { /** * True if new child docshells should allow content retargeting. * Setting allowContentRetargeting also overwrites this value. */ [infallible] attribute boolean allowContentRetargetingOnChildren; }; + +[scriptable, builtinclass, uuid(607604b6-8fe0-4d2c-8a6c-44f5f31a6e02)] +interface nsIDocShell_ESR38_2 : nsIDocShell_ESR38 +{ + /** + * Loads the given URI. This method is identical to loadURI(...) except + * that its parameter list is broken out instead of being packaged inside + * of an nsIDocShellLoadInfo object... + * + * @param aURI - The URI to load. + * @param aOriginalURI - The URI to set as the originalURI on the channel + * that does the load. If null, aURI will be set as + * the originalURI. + * @param aReferrer - Referring URI + * @param aReferrerPolicy - Referrer policy + * @param aOwner - Owner (security principal) + * @param aInheritOwner - Flag indicating whether the owner of the current + * document should be inherited if aOwner is null. + * @param aStopActiveDoc - Flag indicating whether loading the current + * document should be stopped. + * @param aWindowTarget - Window target for the load. + * @param aTypeHint - A hint as to the content-type of the resulting + * data. May be null or empty if no hint. + * @param aFileName - Non-null when the link should be downloaded as + the given filename. + * @param aPostDataStream - Post data stream (if POSTing) + * @param aHeadersStream - Stream containing "extra" request headers... + * @param aLoadFlags - Flags to modify load behaviour. Flags are defined + * in nsIWebNavigation. + * @param aSHEntry - Active Session History entry (if loading from SH) + * @param aSrcdoc When INTERNAL_LOAD_FLAGS_IS_SRCDOC is set, the + * contents of this parameter will be loaded instead + * of aURI. + * @param aSourceDocShell - The source browsing context for the navigation. + * @param aBaseURI - The base URI to be used for the load. Set in + * srcdoc loads as it cannot otherwise be inferred + * in certain situations such as view-source. + */ + [noscript]void internalLoad2(in nsIURI aURI, + in nsIURI aOriginalURI, + in nsIURI aReferrer, + in unsigned long aReferrerPolicy, + in nsISupports aOwner, + in uint32_t aFlags, + in wstring aWindowTarget, + in string aTypeHint, + in AString aFileName, + in nsIInputStream aPostDataStream, + in nsIInputStream aHeadersStream, + in unsigned long aLoadFlags, + in nsISHEntry aSHEntry, + in boolean firstParty, + in AString aSrcdoc, + in nsIDocShell aSourceDocShell, + in nsIURI aBaseURI, + out nsIDocShell aDocShell, + out nsIRequest aRequest); +}; diff --git a/docshell/base/nsIDocShellLoadInfo.idl b/docshell/base/nsIDocShellLoadInfo.idl --- a/docshell/base/nsIDocShellLoadInfo.idl +++ b/docshell/base/nsIDocShellLoadInfo.idl @@ -106,8 +106,17 @@ interface nsIDocShellLoadInfo : nsISuppo attribute nsIDocShell sourceDocShell; /** * Used for srcdoc loads to give view-source knowledge of the load's base * URI as this information isn't embedded in the load's URI. */ attribute nsIURI baseURI; }; + +[scriptable, uuid(9d3bc466-5efe-414d-ae8b-3830b45877bb)] +interface nsIDocShellLoadInfo_ESR38 : nsIDocShellLoadInfo +{ + /** + * The originalURI to be passed to nsIDocShell.internalLoad. May be null. + */ + attribute nsIURI originalURI; +}; diff --git a/docshell/shistory/public/nsISHEntry.idl b/docshell/shistory/public/nsISHEntry.idl --- a/docshell/shistory/public/nsISHEntry.idl +++ b/docshell/shistory/public/nsISHEntry.idl @@ -319,8 +319,18 @@ interface nsISHEntryInternal : nsISuppor #define NS_SHENTRY_CID \ {0xbfd1a791, 0xad9f, 0x11d3, {0xbd, 0xc7, 0x0, 0x50, 0x4, 0xa, 0x9b, 0x44}} #define NS_SHENTRY_CONTRACTID \ "@mozilla.org/browser/session-history-entry;1" %} +[scriptable, uuid(e45ab6ef-3485-449c-b91c-0846b2bf6faf)] +interface nsISHEntry_ESR38 : nsISHEntry +{ + /** + * A readonly property that returns the original URI of the current entry. + * If an entry is the result of a redirect this attribute holds original + * URI. The object returned is of type nsIURI + */ + attribute nsIURI originalURI; +}; diff --git a/docshell/shistory/src/nsSHEntry.cpp b/docshell/shistory/src/nsSHEntry.cpp --- a/docshell/shistory/src/nsSHEntry.cpp +++ b/docshell/shistory/src/nsSHEntry.cpp @@ -38,16 +38,17 @@ nsSHEntry::nsSHEntry() , mIsSrcdocEntry(false) { mShared = new nsSHEntryShared(); } nsSHEntry::nsSHEntry(const nsSHEntry &other) : mShared(other.mShared) , mURI(other.mURI) + , mOriginalURI(other.mOriginalURI) , mReferrerURI(other.mReferrerURI) , mReferrerPolicy(other.mReferrerPolicy) , mTitle(other.mTitle) , mPostData(other.mPostData) , mLoadType(0) // XXX why not copy? , mID(other.mID) , mScrollPositionX(0) // XXX why not copy? , mScrollPositionY(0) // XXX why not copy? @@ -74,17 +75,17 @@ nsSHEntry::~nsSHEntry() // Null out the mParent pointers on all our kids. mChildren.EnumerateForwards(ClearParentPtr, nullptr); } //***************************************************************************** // nsSHEntry: nsISupports //***************************************************************************** -NS_IMPL_ISUPPORTS(nsSHEntry, nsISHContainer, nsISHEntry, nsISHEntryInternal) +NS_IMPL_ISUPPORTS(nsSHEntry, nsISHContainer, nsISHEntry_ESR38, nsISHEntry, nsISHEntryInternal) //***************************************************************************** // nsSHEntry: nsISHEntry //***************************************************************************** NS_IMETHODIMP nsSHEntry::SetScrollPosition(int32_t x, int32_t y) { mScrollPositionX = x; @@ -119,16 +120,29 @@ NS_IMETHODIMP nsSHEntry::GetURI(nsIURI** } NS_IMETHODIMP nsSHEntry::SetURI(nsIURI* aURI) { mURI = aURI; return NS_OK; } +NS_IMETHODIMP nsSHEntry::GetOriginalURI(nsIURI** aOriginalURI) +{ + *aOriginalURI = mOriginalURI; + NS_IF_ADDREF(*aOriginalURI); + return NS_OK; +} + +NS_IMETHODIMP nsSHEntry::SetOriginalURI(nsIURI* aOriginalURI) +{ + mOriginalURI = aOriginalURI; + return NS_OK; +} + NS_IMETHODIMP nsSHEntry::GetReferrerURI(nsIURI **aReferrerURI) { *aReferrerURI = mReferrerURI; NS_IF_ADDREF(*aReferrerURI); return NS_OK; } NS_IMETHODIMP nsSHEntry::SetReferrerURI(nsIURI *aReferrerURI) diff --git a/docshell/shistory/src/nsSHEntry.h b/docshell/shistory/src/nsSHEntry.h --- a/docshell/shistory/src/nsSHEntry.h +++ b/docshell/shistory/src/nsSHEntry.h @@ -17,25 +17,26 @@ // Interfaces needed #include "nsISHEntry.h" #include "nsISHContainer.h" class nsSHEntryShared; class nsIInputStream; class nsIURI; -class nsSHEntry final : public nsISHEntry, +class nsSHEntry final : public nsISHEntry_ESR38, public nsISHContainer, public nsISHEntryInternal { public: nsSHEntry(); nsSHEntry(const nsSHEntry &other); NS_DECL_ISUPPORTS + NS_DECL_NSISHENTRY_ESR38 NS_DECL_NSISHENTRY NS_DECL_NSISHENTRYINTERNAL NS_DECL_NSISHCONTAINER void DropPresentationState(); static nsresult Startup(); static void Shutdown(); @@ -44,16 +45,17 @@ private: ~nsSHEntry(); // We share the state in here with other SHEntries which correspond to the // same document. nsRefPtr mShared; // See nsSHEntry.idl for comments on these members. nsCOMPtr mURI; + nsCOMPtr mOriginalURI; nsCOMPtr mReferrerURI; uint32_t mReferrerPolicy; nsString mTitle; nsCOMPtr mPostData; uint32_t mLoadType; uint32_t mID; int32_t mScrollPositionX; int32_t mScrollPositionY; diff --git a/docshell/shistory/src/nsSHistory.cpp b/docshell/shistory/src/nsSHistory.cpp --- a/docshell/shistory/src/nsSHistory.cpp +++ b/docshell/shistory/src/nsSHistory.cpp @@ -1779,16 +1779,26 @@ nsSHistory::InitiateLoad(nsISHEntry * aF * so that proper loadType is maintained through out a frameset */ aFrameEntry->SetLoadType(aLoadType); aFrameDS->CreateLoadInfo (getter_AddRefs(loadInfo)); loadInfo->SetLoadType(aLoadType); loadInfo->SetSHEntry(aFrameEntry); + nsCOMPtr originalURI; + nsCOMPtr feESR38 = do_QueryInterface(aFrameEntry); + if (feESR38) { + feESR38->GetOriginalURI(getter_AddRefs(originalURI)); + } + nsCOMPtr liESR38 = do_QueryInterface(loadInfo); + if (liESR38) { + liESR38->SetOriginalURI(originalURI); + } + nsCOMPtr nextURI; aFrameEntry->GetURI(getter_AddRefs(nextURI)); // Time to initiate a document load return aFrameDS->LoadURI(nextURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, false); }