Bug 1363036 - Part 2: Reject AddEntry / ReplaceEntry if the entry has been associated to another SHistory. Cleanup mHistoryTracker if root docshell changes. r=smaug

MozReview-Commit-ID: 9s4dQG18JUN

--HG--
extra : rebase_source : 728dcdc63c11aaf177faa4e093750a69da8175e4
This commit is contained in:
Samael Wang 2017-05-22 15:36:06 +08:00
parent ecbe18e933
commit cb393d1f72
3 changed files with 40 additions and 2 deletions

View File

@ -335,9 +335,11 @@ interface nsISHEntry : nsISupports
readonly attribute boolean loadedInThisProcess;
/**
* Set the session history it belongs to. It's only set on root entries.
* The session history it belongs to. It's usually only set on root entries.
* SHEntry is strictly bound to the SHistory it belongs to; it should not be
* changed once set to a non-null value.
*/
[noscript] void setSHistory(in nsISHistory aSHistory);
[noscript] attribute nsISHistory SHistory;
};
[scriptable, uuid(bb66ac35-253b-471f-a317-3ece940f04c5)]

View File

@ -974,6 +974,14 @@ nsSHEntry::SetLastTouched(uint32_t aLastTouched)
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetSHistory(nsISHistory** aSHistory)
{
nsCOMPtr<nsISHistory> shistory(do_QueryReferent(mShared->mSHistory));
shistory.forget(aSHistory);
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetSHistory(nsISHistory* aSHistory)
{

View File

@ -385,6 +385,15 @@ nsSHistory::AddEntry(nsISHEntry* aSHEntry, bool aPersist)
{
NS_ENSURE_ARG(aSHEntry);
nsCOMPtr<nsISHistory> shistoryOfEntry;
aSHEntry->GetSHistory(getter_AddRefs(shistoryOfEntry));
if (shistoryOfEntry && shistoryOfEntry != this) {
NS_WARNING("The entry has been associated to another nsISHistory instance. "
"Try nsISHEntry.clone() and nsISHEntry.abandonBFCacheEntry() "
"first if you're copying an entry from another nsISHistory.");
return NS_ERROR_FAILURE;
}
aSHEntry->SetSHistory(this);
// If we have a root docshell, update the docshell id of the root shentry to
@ -867,6 +876,17 @@ nsSHistory::ReplaceEntry(int32_t aIndex, nsISHEntry* aReplaceEntry)
rv = GetTransactionAtIndex(aIndex, getter_AddRefs(currentTxn));
if (currentTxn) {
nsCOMPtr<nsISHistory> shistoryOfEntry;
aReplaceEntry->GetSHistory(getter_AddRefs(shistoryOfEntry));
if (shistoryOfEntry && shistoryOfEntry != this) {
NS_WARNING("The entry has been associated to another nsISHistory instance. "
"Try nsISHEntry.clone() and nsISHEntry.abandonBFCacheEntry() "
"first if you're copying an entry from another nsISHistory.");
return NS_ERROR_FAILURE;
}
aReplaceEntry->SetSHistory(this);
NOTIFY_LISTENERS(OnHistoryReplaceEntry, (aIndex));
// Set the replacement entry in the transaction
@ -1938,6 +1958,14 @@ nsSHistory::SetRootDocShell(nsIDocShell* aDocShell)
return NS_ERROR_UNEXPECTED;
}
// Seamonkey moves shistory between <xul:browser>s when restoring a tab.
// Let's try not to break our friend too badly...
if (mHistoryTracker) {
NS_WARNING("Change the root docshell of a shistory is unsafe and "
"potentially problematic.");
mHistoryTracker->AgeAllGenerations();
}
RefPtr<mozilla::dom::TabGroup> tabGroup = win->TabGroup();
mHistoryTracker = mozilla::MakeUnique<HistoryTracker>(
this,