Bug 534178, remove dublicate nsSHTransactions, r=bz, a=blocking

--HG--
extra : rebase_source : a963bc21f3d2fd2038d6b26e50ad9aa50f6bc3e4
This commit is contained in:
Olli Pettay 2010-09-05 21:10:35 +03:00
Родитель 78bd6f138d
Коммит 848473ad4e
5 изменённых файлов: 126 добавлений и 4 удалений

Просмотреть файл

@ -2166,6 +2166,37 @@ nsDocShell::HistoryPurged(PRInt32 aNumEntries)
return NS_OK;
}
nsresult
nsDocShell::HistoryTransactionRemoved(PRInt32 aIndex)
{
// These indices are used for fastback cache eviction, to determine
// which session history entries are candidates for content viewer
// eviction. We need to adjust by the number of entries that we
// just purged from history, so that we look at the right session history
// entries during eviction.
if (aIndex == mPreviousTransIndex) {
mPreviousTransIndex = -1;
} else if (aIndex < mPreviousTransIndex) {
--mPreviousTransIndex;
}
if (mLoadedTransIndex == aIndex) {
mLoadedTransIndex = 0;
} else if (aIndex < mLoadedTransIndex) {
--mLoadedTransIndex;
}
PRInt32 count = mChildList.Count();
for (PRInt32 i = 0; i < count; ++i) {
nsCOMPtr<nsIDocShell> shell = do_QueryInterface(ChildAt(i));
if (shell) {
static_cast<nsDocShell*>(shell.get())->
HistoryTransactionRemoved(aIndex);
}
}
return NS_OK;
}
static
nsresult
GetPrincipalDomain(nsIPrincipal* aPrincipal, nsACString& aDomain)
@ -9628,7 +9659,7 @@ nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle,
AddURIVisit(newURI, oldURI, oldURI, 0);
}
else {
FireOnLocationChange(this, nsnull, mCurrentURI);
FireDummyOnLocationChange();
}
return NS_OK;

Просмотреть файл

@ -269,6 +269,13 @@ public:
friend class OnLinkClickEvent;
// We need dummy OnLocationChange in some cases to update the UI.
void FireDummyOnLocationChange()
{
FireOnLocationChange(this, nsnull, mCurrentURI);
}
nsresult HistoryTransactionRemoved(PRInt32 aIndex);
protected:
// Object Management
virtual ~nsDocShell();

Просмотреть файл

@ -111,10 +111,12 @@ nsSHTransaction::GetNext(nsISHTransaction * * aResult)
NS_IMETHODIMP
nsSHTransaction::SetNext(nsISHTransaction * aNext)
{
NS_ENSURE_SUCCESS(aNext->SetPrev(this), NS_ERROR_FAILURE);
if (aNext) {
NS_ENSURE_SUCCESS(aNext->SetPrev(this), NS_ERROR_FAILURE);
}
mNext = aNext;
return NS_OK;
mNext = aNext;
return NS_OK;
}
NS_IMETHODIMP

Просмотреть файл

@ -62,6 +62,7 @@
#include "mozilla/Services.h"
#include "nsTArray.h"
#include "nsCOMArray.h"
#include "nsDocShell.h"
// For calculating max history entries and max cachable contentviewers
#include "nspr.h"
@ -1137,13 +1138,91 @@ PRBool RemoveChildEntries(nsISHistory* aHistory, PRInt32 aIndex,
return root ? RemoveFromSessionHistoryContainer(root, aEntryIDs) : PR_FALSE;
}
PRBool IsSameTree(nsISHEntry* aEntry1, nsISHEntry* aEntry2)
{
if (!aEntry1 && !aEntry2) {
return PR_TRUE;
}
if ((!aEntry1 && aEntry2) || (aEntry1 && !aEntry2)) {
return PR_FALSE;
}
PRUint32 id1, id2;
aEntry1->GetID(&id1);
aEntry2->GetID(&id2);
if (id1 != id2) {
return PR_FALSE;
}
nsCOMPtr<nsISHContainer> container1 = do_QueryInterface(aEntry1);
nsCOMPtr<nsISHContainer> container2 = do_QueryInterface(aEntry2);
PRInt32 count1, count2;
container1->GetChildCount(&count1);
container2->GetChildCount(&count2);
// We allow null entries in the end of the child list.
PRInt32 count = PR_MAX(count1, count2);
for (PRInt32 i = 0; i < count; ++i) {
nsCOMPtr<nsISHEntry> child1, child2;
container1->GetChildAt(i, getter_AddRefs(child1));
container2->GetChildAt(i, getter_AddRefs(child2));
if (!IsSameTree(child1, child2)) {
return PR_FALSE;
}
}
return PR_TRUE;
}
PRBool
nsSHistory::RemoveDuplicate(PRInt32 aIndex)
{
NS_ASSERTION(aIndex > 0, "aIndex must be > 0!");
nsCOMPtr<nsIHistoryEntry> rootHE1, rootHE2;
GetEntryAtIndex(aIndex, PR_FALSE, getter_AddRefs(rootHE1));
GetEntryAtIndex(aIndex - 1, PR_FALSE, getter_AddRefs(rootHE2));
nsCOMPtr<nsISHEntry> root1 = do_QueryInterface(rootHE1);
nsCOMPtr<nsISHEntry> root2 = do_QueryInterface(rootHE2);
if (IsSameTree(root1, root2)) {
nsCOMPtr<nsISHTransaction> txToRemove, txToKeep, txNext;
GetTransactionAtIndex(aIndex, getter_AddRefs(txToRemove));
GetTransactionAtIndex(aIndex - 1, getter_AddRefs(txToKeep));
NS_ENSURE_TRUE(txToRemove, PR_FALSE);
NS_ENSURE_TRUE(txToKeep, PR_FALSE);
txToRemove->GetNext(getter_AddRefs(txNext));
txToRemove->SetNext(nsnull);
txToRemove->SetPrev(nsnull);
// If txNext is non-null, this will set txNext's .prev
txToKeep->SetNext(txNext);
static_cast<nsDocShell*>(mRootDocShell)->HistoryTransactionRemoved(aIndex);
if (mIndex >= aIndex) {
mIndex = mIndex - 1;
}
--mLength;
return PR_TRUE;
}
return PR_FALSE;
}
NS_IMETHODIMP_(void)
nsSHistory::RemoveEntries(nsTArray<PRUint64>& aIDs, PRInt32 aStartIndex)
{
PRInt32 index = aStartIndex;
while(index >= 0 && RemoveChildEntries(this, --index, aIDs));
// Nothing was removed from minIndex if it is > 0!
PRInt32 minIndex = index >= 0 ? index : 0;
index = aStartIndex;
while(index >= 0 && RemoveChildEntries(this, index++, aIDs));
// We need to remove duplicate nsSHEntry trees.
PRBool didRemove = PR_FALSE;
while (index && index > minIndex) {
didRemove = RemoveDuplicate(index--) || didRemove;
}
if (didRemove && mRootDocShell) {
nsRefPtr<nsIRunnable> ev =
NS_NewRunnableMethod(static_cast<nsDocShell*>(mRootDocShell),
&nsDocShell::FireDummyOnLocationChange);
NS_DispatchToCurrentThread(ev);
}
}
void

Просмотреть файл

@ -116,6 +116,9 @@ protected:
nsresult LoadNextPossibleEntry(PRInt32 aNewIndex, long aLoadType, PRUint32 aHistCmd);
protected:
// Note, aIndex must be > 0, since it is compared to aIndex - 1.
PRBool RemoveDuplicate(PRInt32 aIndex);
nsCOMPtr<nsISHTransaction> mListRoot;
PRInt32 mIndex;
PRInt32 mLength;