Bug 596870 - ASSERTION: Detaching editor when it is already detached with iframes and contenteditable, r=bz, a=blocking
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Mon, 15 Nov 2010 12:11:51 +0200
changeset 57503 edf41ff32f08c95e8a01cbe583f37f88485f1419
parent 57502 90ee071c963eb8e33f6c4dc3cd57e76039f79226
child 57504 bc33b57acf78e5113ae9a314a30f179d92ba3bb7
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersbz, blocking
bugs596870
milestone2.0b8pre
Bug 596870 - ASSERTION: Detaching editor when it is already detached with iframes and contenteditable, r=bz, a=blocking
docshell/shistory/src/nsSHistory.cpp
docshell/shistory/src/nsSHistory.h
--- a/docshell/shistory/src/nsSHistory.cpp
+++ b/docshell/shistory/src/nsSHistory.cpp
@@ -1168,59 +1168,78 @@ PRBool IsSameTree(nsISHEntry* aEntry1, n
       return PR_FALSE;
     }
   }
   
   return PR_TRUE;
 }
 
 PRBool
-nsSHistory::RemoveDuplicate(PRInt32 aIndex)
+nsSHistory::RemoveDuplicate(PRInt32 aIndex, PRBool aKeepNext)
 {
-  NS_ASSERTION(aIndex > 0, "aIndex must be > 0!");
+  NS_ASSERTION(aIndex >= 0, "aIndex must be >= 0!");
+  NS_ASSERTION(aIndex != mIndex, "Shouldn't remove mIndex!");
+  PRInt32 compareIndex = aKeepNext ? aIndex + 1 : aIndex - 1;
   nsCOMPtr<nsIHistoryEntry> rootHE1, rootHE2;
   GetEntryAtIndex(aIndex, PR_FALSE, getter_AddRefs(rootHE1));
-  GetEntryAtIndex(aIndex - 1, PR_FALSE, getter_AddRefs(rootHE2));
+  GetEntryAtIndex(compareIndex, 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;
+    nsCOMPtr<nsISHTransaction> txToRemove, txToKeep, txNext, txPrev;
     GetTransactionAtIndex(aIndex, getter_AddRefs(txToRemove));
-    GetTransactionAtIndex(aIndex - 1, getter_AddRefs(txToKeep));
+    GetTransactionAtIndex(compareIndex, getter_AddRefs(txToKeep));
     NS_ENSURE_TRUE(txToRemove, PR_FALSE);
     NS_ENSURE_TRUE(txToKeep, PR_FALSE);
     txToRemove->GetNext(getter_AddRefs(txNext));
+    txToRemove->GetPrev(getter_AddRefs(txPrev));
     txToRemove->SetNext(nsnull);
     txToRemove->SetPrev(nsnull);
-    // If txNext is non-null, this will set txNext's .prev
-    txToKeep->SetNext(txNext);
+    if (aKeepNext) {
+      if (txPrev) {
+        txPrev->SetNext(txToKeep);
+      } else {
+        txToKeep->SetPrev(nsnull);
+      }
+    } else {
+      txToKeep->SetNext(txNext);
+    }
+
+    if (aIndex == 0 && aKeepNext) {
+      NS_ASSERTION(txToRemove == mListRoot,
+                   "Transaction at index 0 should be mListRoot!");
+      // We're removing the very first session history transaction!
+      mListRoot = txToKeep;
+    }
     static_cast<nsDocShell*>(mRootDocShell)->HistoryTransactionRemoved(aIndex);
-    if (mIndex >= 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;
+  PRInt32 minIndex = index;
   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;
+  while (index > minIndex) {
+    if (index != mIndex) {
+      didRemove = RemoveDuplicate(index, index < mIndex) || didRemove;
+    }
+    --index;
   }
   if (didRemove && mRootDocShell) {
     nsRefPtr<nsIRunnable> ev =
       NS_NewRunnableMethod(static_cast<nsDocShell*>(mRootDocShell),
                            &nsDocShell::FireDummyOnLocationChange);
     NS_DispatchToCurrentThread(ev);
   }
 }
--- a/docshell/shistory/src/nsSHistory.h
+++ b/docshell/shistory/src/nsSHistory.h
@@ -111,18 +111,20 @@ protected:
   // Calculates a max number of total
   // content viewers to cache, based on amount of total memory
   static PRUint32 CalcMaxTotalViewers();
 
   void RemoveDynEntries(PRInt32 aOldIndex, PRInt32 aNewIndex);
 
   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);
+  // aIndex is the index of the transaction which may be removed.
+  // If aKeepNext is PR_TRUE, aIndex is compared to aIndex + 1,
+  // otherwise comparison is done to aIndex - 1.
+  PRBool RemoveDuplicate(PRInt32 aIndex, PRBool aKeepNext);
 
   nsCOMPtr<nsISHTransaction> mListRoot;
   PRInt32 mIndex;
   PRInt32 mLength;
   PRInt32 mRequestedIndex;
   // Session History listener
   nsWeakPtr mListener;
   // Weak reference. Do not refcount this.