diff --git a/docshell/shistory/PSHistory.ipdl b/docshell/shistory/PSHistory.ipdl index 5f5b7c398579..470450912ce1 100644 --- a/docshell/shistory/PSHistory.ipdl +++ b/docshell/shistory/PSHistory.ipdl @@ -26,7 +26,7 @@ struct LoadSHEntryData union LoadSHEntryResult { nsresult; - LoadSHEntryData; + LoadSHEntryData[]; }; sync protocol PSHistory { diff --git a/docshell/shistory/SHistoryChild.cpp b/docshell/shistory/SHistoryChild.cpp index 95414629ef8d..42ccb639eb62 100644 --- a/docshell/shistory/SHistoryChild.cpp +++ b/docshell/shistory/SHistoryChild.cpp @@ -369,23 +369,27 @@ SHistoryChild::CreateEntry(nsISHEntry** aEntry) { return NS_OK; } -nsresult SHistoryChild::LoadURI(LoadSHEntryData& aLoadData) { - if (NS_WARN_IF(aLoadData.browsingContext().IsNullOrDiscarded())) { - return NS_ERROR_FAILURE; +nsresult SHistoryChild::LoadURI(nsTArray& aLoadData) { + for (LoadSHEntryData& l : aLoadData) { + if (l.browsingContext().IsNullOrDiscarded()) { + continue; + } + + nsCOMPtr docShell = l.browsingContext().get()->GetDocShell(); + if (!docShell) { + continue; + } + + RefPtr entry; + if (l.shEntry()) { + entry = l.shEntry()->ToSHEntryChild(); + } + + // FIXME Should this be sent through IPC? + l.loadState()->SetSHEntry(entry); + docShell->LoadURI(l.loadState(), false); } - - nsCOMPtr docShell = - aLoadData.browsingContext().get()->GetDocShell(); - NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE); - - RefPtr entry; - if (aLoadData.shEntry()) { - entry = aLoadData.shEntry()->ToSHEntryChild(); - } - - // FIXME Should this be sent through IPC? - aLoadData.loadState()->SetSHEntry(entry); - return docShell->LoadURI(aLoadData.loadState(), false); + return NS_OK; } } // namespace dom diff --git a/docshell/shistory/SHistoryChild.h b/docshell/shistory/SHistoryChild.h index a24a24da8fa1..a3893d8d2614 100644 --- a/docshell/shistory/SHistoryChild.h +++ b/docshell/shistory/SHistoryChild.h @@ -69,7 +69,7 @@ class SHistoryChild final : public PSHistoryChild, ~SHistoryChild() = default; - nsresult LoadURI(LoadSHEntryData& aLoadData); + nsresult LoadURI(nsTArray& aLoadData); // Track all bfcache entries and evict on expiration. mozilla::UniquePtr mHistoryTracker; diff --git a/docshell/shistory/SHistoryParent.cpp b/docshell/shistory/SHistoryParent.cpp index a9b67f05e4c7..5deb83f756ec 100644 --- a/docshell/shistory/SHistoryParent.cpp +++ b/docshell/shistory/SHistoryParent.cpp @@ -24,13 +24,19 @@ LegacySHistory::LegacySHistory(SHistoryParent* aSHistoryParent, aRootBC->SetSessionHistory(this); } -static void FillInLoadResult(nsresult aRv, - const nsSHistory::LoadEntryResult& aLoadResult, - LoadSHEntryResult* aResult) { +static void FillInLoadResult( + nsresult aRv, const nsTArray& aLoadResults, + LoadSHEntryResult* aResult) { if (NS_SUCCEEDED(aRv)) { - *aResult = LoadSHEntryData( - static_cast(aLoadResult.mLoadState->SHEntry()), - aLoadResult.mBrowsingContext, aLoadResult.mLoadState); + nsTArray data; + data.SetCapacity(aLoadResults.Length()); + for (const nsSHistory::LoadEntryResult& l : aLoadResults) { + data.AppendElement( + LoadSHEntryData(static_cast(l.mLoadState->SHEntry()), + l.mBrowsingContext, l.mLoadState)); + } + + *aResult = data; } else { *aResult = aRv; } @@ -95,12 +101,10 @@ bool SHistoryParent::RecvPurgeHistory(int32_t aNumEntries, nsresult* aResult) { } bool SHistoryParent::RecvReloadCurrentEntry(LoadSHEntryResult* aLoadResult) { - nsSHistory::LoadEntryResult loadResult; - nsresult rv = mHistory->ReloadCurrentEntry(loadResult); + nsTArray loadResults; + nsresult rv = mHistory->ReloadCurrentEntry(loadResults); if (NS_SUCCEEDED(rv)) { - *aLoadResult = LoadSHEntryData( - static_cast(loadResult.mLoadState->SHEntry()), - loadResult.mBrowsingContext, loadResult.mLoadState); + FillInLoadResult(rv, loadResults, aLoadResult); } else { *aLoadResult = rv; } @@ -109,9 +113,9 @@ bool SHistoryParent::RecvReloadCurrentEntry(LoadSHEntryResult* aLoadResult) { bool SHistoryParent::RecvGotoIndex(int32_t aIndex, LoadSHEntryResult* aLoadResult) { - nsSHistory::LoadEntryResult loadResult; - nsresult rv = mHistory->GotoIndex(aIndex, loadResult); - FillInLoadResult(rv, loadResult, aLoadResult); + nsTArray loadResults; + nsresult rv = mHistory->GotoIndex(aIndex, loadResults); + FillInLoadResult(rv, loadResults, aLoadResult); return true; } @@ -193,12 +197,12 @@ bool SHistoryParent::RecvRemoveFrameEntries(PSHEntryParent* aEntry) { bool SHistoryParent::RecvReload(const uint32_t& aReloadFlags, LoadSHEntryResult* aLoadResult) { - Maybe loadResult; - nsresult rv = mHistory->Reload(aReloadFlags, loadResult); - if (NS_SUCCEEDED(rv) && !loadResult) { + nsTArray loadResults; + nsresult rv = mHistory->Reload(aReloadFlags, loadResults); + if (NS_SUCCEEDED(rv) && loadResults.IsEmpty()) { *aLoadResult = NS_OK; } else { - FillInLoadResult(rv, loadResult.ref(), aLoadResult); + FillInLoadResult(rv, loadResults, aLoadResult); } return true; } diff --git a/docshell/shistory/nsSHistory.cpp b/docshell/shistory/nsSHistory.cpp index 8ca293570bca..5e42b432cad0 100644 --- a/docshell/shistory/nsSHistory.cpp +++ b/docshell/shistory/nsSHistory.cpp @@ -830,27 +830,29 @@ nsSHistory::EvictAllContentViewers() { return NS_OK; } -static nsresult LoadURI(nsSHistory::LoadEntryResult& aLoadResult) { - return aLoadResult.mBrowsingContext->LoadURI(nullptr, aLoadResult.mLoadState, - false); +static void LoadURIs(nsTArray& aLoadResults) { + for (nsSHistory::LoadEntryResult& loadEntry : aLoadResults) { + loadEntry.mBrowsingContext->LoadURI(nullptr, loadEntry.mLoadState, false); + } } NS_IMETHODIMP nsSHistory::Reload(uint32_t aReloadFlags) { - Maybe loadResult; - nsresult rv = Reload(aReloadFlags, loadResult); + nsTArray loadResults; + nsresult rv = Reload(aReloadFlags, loadResults); NS_ENSURE_SUCCESS(rv, rv); - if (!loadResult) { + if (loadResults.IsEmpty()) { return NS_OK; } - return LoadURI(loadResult.ref()); + LoadURIs(loadResults); + return NS_OK; } nsresult nsSHistory::Reload(uint32_t aReloadFlags, - Maybe& aLoadResult) { - MOZ_ASSERT(!aLoadResult.isSome()); + nsTArray& aLoadResults) { + MOZ_ASSERT(aLoadResults.IsEmpty()); uint32_t loadType; if (aReloadFlags & nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY && @@ -878,10 +880,9 @@ nsresult nsSHistory::Reload(uint32_t aReloadFlags, return NS_OK; } - aLoadResult.emplace(); - nsresult rv = LoadEntry(mIndex, loadType, HIST_CMD_RELOAD, aLoadResult.ref()); + nsresult rv = LoadEntry(mIndex, loadType, HIST_CMD_RELOAD, aLoadResults); if (NS_FAILED(rv)) { - aLoadResult.reset(); + aLoadResults.Clear(); return rv; } @@ -890,18 +891,20 @@ nsresult nsSHistory::Reload(uint32_t aReloadFlags, NS_IMETHODIMP nsSHistory::ReloadCurrentEntry() { - LoadEntryResult loadResult; - nsresult rv = ReloadCurrentEntry(loadResult); + nsTArray loadResults; + nsresult rv = ReloadCurrentEntry(loadResults); NS_ENSURE_SUCCESS(rv, rv); - return LoadURI(loadResult); + LoadURIs(loadResults); + return NS_OK; } -nsresult nsSHistory::ReloadCurrentEntry(LoadEntryResult& aLoadResult) { +nsresult nsSHistory::ReloadCurrentEntry( + nsTArray& aLoadResults) { // Notify listeners NOTIFY_LISTENERS(OnHistoryGotoIndex, ()); - return LoadEntry(mIndex, LOAD_HISTORY, HIST_CMD_RELOAD, aLoadResult); + return LoadEntry(mIndex, LOAD_HISTORY, HIST_CMD_RELOAD, aLoadResults); } void nsSHistory::EvictOutOfRangeWindowContentViewers(int32_t aIndex) { @@ -1382,11 +1385,12 @@ nsSHistory::UpdateIndex() { NS_IMETHODIMP nsSHistory::GotoIndex(int32_t aIndex) { - LoadEntryResult loadResult; - nsresult rv = GotoIndex(aIndex, loadResult); + nsTArray loadResults; + nsresult rv = GotoIndex(aIndex, loadResults); NS_ENSURE_SUCCESS(rv, rv); - return LoadURI(loadResult); + LoadURIs(loadResults); + return NS_OK; } NS_IMETHODIMP_(void) @@ -1397,26 +1401,27 @@ nsSHistory::EnsureCorrectEntryAtCurrIndex(nsISHEntry* aEntry) { } } -nsresult nsSHistory::GotoIndex(int32_t aIndex, LoadEntryResult& aLoadResult) { - return LoadEntry(aIndex, LOAD_HISTORY, HIST_CMD_GOTOINDEX, aLoadResult); +nsresult nsSHistory::GotoIndex(int32_t aIndex, + nsTArray& aLoadResults) { + return LoadEntry(aIndex, LOAD_HISTORY, HIST_CMD_GOTOINDEX, aLoadResults); } -nsresult nsSHistory::LoadNextPossibleEntry(int32_t aNewIndex, long aLoadType, - uint32_t aHistCmd, - LoadEntryResult& aLoadResult) { +nsresult nsSHistory::LoadNextPossibleEntry( + int32_t aNewIndex, long aLoadType, uint32_t aHistCmd, + nsTArray& aLoadResults) { mRequestedIndex = -1; if (aNewIndex < mIndex) { - return LoadEntry(aNewIndex - 1, aLoadType, aHistCmd, aLoadResult); + return LoadEntry(aNewIndex - 1, aLoadType, aHistCmd, aLoadResults); } if (aNewIndex > mIndex) { - return LoadEntry(aNewIndex + 1, aLoadType, aHistCmd, aLoadResult); + return LoadEntry(aNewIndex + 1, aLoadType, aHistCmd, aLoadResults); } return NS_ERROR_FAILURE; } nsresult nsSHistory::LoadEntry(int32_t aIndex, long aLoadType, uint32_t aHistCmd, - LoadEntryResult& aLoadResult) { + nsTArray& aLoadResults) { if (!mRootBC) { return NS_ERROR_FAILURE; } @@ -1457,16 +1462,16 @@ nsresult nsSHistory::LoadEntry(int32_t aIndex, long aLoadType, if (mRequestedIndex == mIndex) { // Possibly a reload case - return InitiateLoad(nextEntry, mRootBC, aLoadType, aLoadResult); + return InitiateLoad(nextEntry, mRootBC, aLoadType, aLoadResults); } // Going back or forward. bool differenceFound = false; nsresult rv = LoadDifferingEntries(prevEntry, nextEntry, mRootBC, aLoadType, - differenceFound, aLoadResult); + differenceFound, aLoadResults); if (!differenceFound) { // We did not find any differences. Go further in the history. - return LoadNextPossibleEntry(aIndex, aLoadType, aHistCmd, aLoadResult); + return LoadNextPossibleEntry(aIndex, aLoadType, aHistCmd, aLoadResults); } return rv; @@ -1474,7 +1479,8 @@ nsresult nsSHistory::LoadEntry(int32_t aIndex, long aLoadType, nsresult nsSHistory::LoadDifferingEntries( nsISHEntry* aPrevEntry, nsISHEntry* aNextEntry, BrowsingContext* aParent, - long aLoadType, bool& aDifferenceFound, LoadEntryResult& aLoadResult) { + long aLoadType, bool& aDifferenceFound, + nsTArray& aLoadResults) { if (!aPrevEntry || !aNextEntry || !aParent) { return NS_ERROR_FAILURE; } @@ -1489,7 +1495,7 @@ nsresult nsSHistory::LoadDifferingEntries( // Set the Subframe flag if not navigating the root docshell. aNextEntry->SetIsSubFrame(aParent != mRootBC); - return InitiateLoad(aNextEntry, aParent, aLoadType, aLoadResult); + return InitiateLoad(aNextEntry, aParent, aLoadType, aLoadResults); } // The entries are the same, so compare any child frames @@ -1543,17 +1549,18 @@ nsresult nsSHistory::LoadDifferingEntries( // This will either load a new page to shell or some subshell or // do nothing. LoadDifferingEntries(pChild, nChild, bcChild, aLoadType, aDifferenceFound, - aLoadResult); + aLoadResults); } return result; } nsresult nsSHistory::InitiateLoad(nsISHEntry* aFrameEntry, BrowsingContext* aFrameBC, long aLoadType, - LoadEntryResult& aLoadResult) { + nsTArray& aLoadResults) { NS_ENSURE_STATE(aFrameBC && aFrameEntry); - aLoadResult.mBrowsingContext = aFrameBC; + LoadEntryResult* loadResult = aLoadResults.AppendElement(); + loadResult->mBrowsingContext = aFrameBC; nsCOMPtr newURI = aFrameEntry->GetURI(); RefPtr loadState = new nsDocShellLoadState(newURI); @@ -1580,7 +1587,7 @@ nsresult nsSHistory::InitiateLoad(nsISHEntry* aFrameEntry, nsCOMPtr csp = aFrameEntry->GetCsp(); loadState->SetCsp(csp); - aLoadResult.mLoadState = std::move(loadState); + loadResult->mLoadState = std::move(loadState); return NS_OK; } diff --git a/docshell/shistory/nsSHistory.h b/docshell/shistory/nsSHistory.h index 97625eea3e3e..64afbd928d4a 100644 --- a/docshell/shistory/nsSHistory.h +++ b/docshell/shistory/nsSHistory.h @@ -140,9 +140,10 @@ class nsSHistory : public mozilla::LinkedListElement, // If this doesn't return an error then either aLoadResult is set to nothing, // in which case the caller should ignore the load, or it returns a valid // LoadEntryResult in aLoadResult which the caller should use to do the load. - nsresult Reload(uint32_t aReloadFlags, Maybe& aLoadResult); - nsresult ReloadCurrentEntry(LoadEntryResult& aLoadResult); - nsresult GotoIndex(int32_t aIndex, LoadEntryResult& aLoadResult); + nsresult Reload(uint32_t aReloadFlags, + nsTArray& aLoadResults); + nsresult ReloadCurrentEntry(nsTArray& aLoadResults); + nsresult GotoIndex(int32_t aIndex, nsTArray& aLoadResults); void WindowIndices(int32_t aIndex, int32_t* aOutStartIndex, int32_t* aOutEndIndex); @@ -160,13 +161,13 @@ class nsSHistory : public mozilla::LinkedListElement, nsresult LoadDifferingEntries(nsISHEntry* aPrevEntry, nsISHEntry* aNextEntry, mozilla::dom::BrowsingContext* aRootBC, long aLoadType, bool& aDifferenceFound, - LoadEntryResult& aLoadResult); + nsTArray& aLoadResults); nsresult InitiateLoad(nsISHEntry* aFrameEntry, mozilla::dom::BrowsingContext* aFrameBC, long aLoadType, - LoadEntryResult& aLoadResult); + nsTArray& aLoadResult); nsresult LoadEntry(int32_t aIndex, long aLoadType, uint32_t aHistCmd, - LoadEntryResult& aLoad); + nsTArray& aLoadResults); #ifdef DEBUG nsresult PrintHistory(); @@ -190,7 +191,7 @@ class nsSHistory : public mozilla::LinkedListElement, nsresult LoadNextPossibleEntry(int32_t aNewIndex, long aLoadType, uint32_t aHistCmd, - LoadEntryResult& aLoadResult); + nsTArray& aLoadResults); // aIndex is the index of the entry which may be removed. // If aKeepNext is true, aIndex is compared to aIndex + 1, diff --git a/docshell/test/navigation/file_bug1609475.html b/docshell/test/navigation/file_bug1609475.html new file mode 100644 index 000000000000..083430fb3a71 --- /dev/null +++ b/docshell/test/navigation/file_bug1609475.html @@ -0,0 +1,51 @@ + + + + + + + + + \ No newline at end of file diff --git a/docshell/test/navigation/mochitest.ini b/docshell/test/navigation/mochitest.ini index 9de539d22c03..2564de7f6e15 100644 --- a/docshell/test/navigation/mochitest.ini +++ b/docshell/test/navigation/mochitest.ini @@ -57,6 +57,7 @@ support-files = file_bug1375833-frame1.html file_bug1375833-frame2.html test_bug145971.html + file_bug1609475.html [test_bug13871.html] [test_bug270414.html] diff --git a/docshell/test/navigation/test_sessionhistory.html b/docshell/test/navigation/test_sessionhistory.html index df32422e4802..d6402b4ae3cb 100644 --- a/docshell/test/navigation/test_sessionhistory.html +++ b/docshell/test/navigation/test_sessionhistory.html @@ -34,6 +34,7 @@ var testFiles = "file_bug1300461.html", "file_bug1326251.html", "file_bug1379762-1.html", + "file_bug1609475.html", ]; var testCount = 0; // Used by the test files.