Bug 432114. Change style sheet owner to the document being edited. r+sr=peterv
authorChris Pearce <chris@pearce.org.nz>
Thu, 19 Feb 2009 20:52:54 +1300
changeset 25180 5302e1700561991b48e4c09f86a95552f0991333
parent 25179 07c015cadf1514479dbf06b719b84410858f3ce9
child 25181 2d759ec1998c9dd16a41d6939faf60b234775c33
push idunknown
push userunknown
push dateunknown
bugs432114
milestone1.9.2a1pre
Bug 432114. Change style sheet owner to the document being edited. r+sr=peterv
docshell/base/crashtests/432114-1.html
docshell/base/crashtests/432114-2.html
docshell/base/crashtests/crashtests.list
docshell/base/nsWebShell.cpp
editor/libeditor/base/nsEditor.cpp
editor/libeditor/html/nsHTMLEditor.cpp
new file mode 100644
--- /dev/null
+++ b/docshell/base/crashtests/432114-1.html
@@ -0,0 +1,8 @@
+<html>
+<head>
+<title>Bug - Crash [@ PL_DHashTableOperate] with DOMNodeInserted event listener removing window and frameset contenteditable</title>
+</head>
+<body>
+<iframe id="content" src="data:text/html;charset=utf-8,%3Cscript%3E%0Awindow.addEventListener%28%27DOMNodeInserted%27%2C%20function%28%29%20%7Bwindow.frameElement.parentNode.removeChild%28window.frameElement%29%3B%7D%2C%20true%29%3B%0A%3C/script%3E%0A%3Cframeset%20contenteditable%3D%22true%22%3E"></iframe>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/docshell/base/crashtests/432114-2.html
@@ -0,0 +1,9 @@
+<html>
+<head>
+<title>testcase2 Bug 432114  Crash [@ PL_DHashTableOperate] with DOMNodeInserted event listener removing window and frameset contenteditable</title>
+</head>
+<body>
+<iframe id="content" src="data:application/xhtml+xml;charset=utf-8,%3Chtml%20xmlns%3D%22http%3A//www.w3.org/1999/xhtml%22%3E%0A%3Cframeset%20contenteditable%3D%22true%22/%3E%0A%3Cscript%3E%0Afunction%20doExecCommand%28%29%7B%0Adocument.execCommand%28%27insertParagraph%27%2C%20false%2C%20%27%27%29%3B%0A%7D%0AsetTimeout%28doExecCommand%2C100%29%3B%0Awindow.addEventListener%28%27DOMNodeRemoved%27%2C%20function%28%29%20%7Bwindow.frameElement.parentNode.removeChild%28window.frameElement%29%3B%7D%2C%20true%29%3B%0A%3C/script%3E%0A%3C/html%3E" style="width:1000px;height: 200px;"></iframe>
+
+</body>
+</html>
--- a/docshell/base/crashtests/crashtests.list
+++ b/docshell/base/crashtests/crashtests.list
@@ -1,4 +1,6 @@
 load 40929-1.html
 load 369126-1.html
 load 403574-1.xhtml
+load 432114-1.html
+load 432114-2.html
 load 436900-1.html
--- a/docshell/base/nsWebShell.cpp
+++ b/docshell/base/nsWebShell.cpp
@@ -585,28 +585,26 @@ void nsWebShell::InitFrameData()
   SetMarginHeight(-1);
 }
 
 nsresult
 nsWebShell::EnsureCommandHandler()
 {
   if (!mCommandManager)
   {
-    mCommandManager = do_CreateInstance("@mozilla.org/embedcomp/command-manager;1");
-    if (!mCommandManager) return NS_ERROR_OUT_OF_MEMORY;
-    
-    nsCOMPtr<nsPICommandUpdater>       commandUpdater = do_QueryInterface(mCommandManager);
-    if (!commandUpdater) return NS_ERROR_FAILURE;
+    nsCOMPtr<nsPICommandUpdater> commandUpdater =
+      do_CreateInstance("@mozilla.org/embedcomp/command-manager;1");
+    if (!commandUpdater) return NS_ERROR_OUT_OF_MEMORY;
     
-    nsCOMPtr<nsIDOMWindow> domWindow = do_GetInterface(static_cast<nsIInterfaceRequestor *>(this));
-#ifdef DEBUG
-    nsresult rv =
-#endif
-    commandUpdater->Init(domWindow);
-    NS_ASSERTION(NS_SUCCEEDED(rv), "Initting command manager failed");
+    nsCOMPtr<nsIDOMWindow> domWindow =
+      do_GetInterface(static_cast<nsIInterfaceRequestor *>(this));
+
+    nsresult rv = commandUpdater->Init(domWindow);
+    if (NS_SUCCEEDED(rv))
+      mCommandManager = do_QueryInterface(commandUpdater);
   }
   
   return mCommandManager ? NS_OK : NS_ERROR_FAILURE;
 }
 
 
 
 NS_IMPL_ADDREF_INHERITED(nsWebShell, nsDocShell)
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -4339,17 +4339,17 @@ nsresult nsEditor::EndUpdateViewBatch()
     if (mViewManager)
     {
       PRUint32 updateFlag = NS_VMREFRESH_IMMEDIATE;
 
       // If we're doing async updates, use NS_VMREFRESH_DEFERRED here, so that
       // the reflows we caused will get processed before the invalidates.
       if (flags & nsIPlaintextEditor::eEditorUseAsyncUpdatesMask) {
         updateFlag = NS_VMREFRESH_DEFERRED;
-      } else {
+      } else if (presShell) {
         // Flush out layout.  Need to do this because if we have no invalidates
         // to flush the viewmanager code won't flush our reflow here, and we
         // have selection code that does sync caret scrolling in this case.
         presShell->FlushPendingNotifications(Flush_Layout);
       }
       mBatch.EndUpdateViewBatch(updateFlag);
     }
 
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -3608,22 +3608,16 @@ nsHTMLEditor::AddOverrideStyleSheet(cons
   nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
   if (!ps)
     return NS_ERROR_NOT_INITIALIZED;
 
   // Add the override style sheet
   // (This checks if already exists)
   ps->AddOverrideStyleSheet(sheet);
 
-  // Save doc pointer to be able to use nsIStyleSheet::SetEnabled()
-  nsIDocument *document = ps->GetDocument();
-  if (!document)
-    return NS_ERROR_NULL_POINTER;
-  sheet->SetOwningDocument(document);
-
   ps->ReconstructStyleData();
 
   // Save as the last-loaded sheet
   mLastOverrideStyleSheetURL = aURL;
 
   //Add URL and style sheet to our lists
   return AddNewStyleSheetToList(aURL, sheet);
 }
@@ -3678,31 +3672,40 @@ nsHTMLEditor::EnableStyleSheet(const nsA
   nsCOMPtr<nsICSSStyleSheet> sheet;
   nsresult rv = GetStyleSheetForURL(aURL, getter_AddRefs(sheet));
   NS_ENSURE_SUCCESS(rv, rv);
   if (!sheet)
     return NS_OK; // Don't fail if sheet not found
 
   nsCOMPtr<nsIDOMStyleSheet> domSheet(do_QueryInterface(sheet));
   NS_ASSERTION(domSheet, "Sheet not implementing nsIDOMStyleSheet!");
+
+  // Ensure the style sheet is owned by our document.
+  nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocWeak);
+  rv = sheet->SetOwningDocument(doc);
+  NS_ENSURE_SUCCESS(rv, rv);
   
   return domSheet->SetDisabled(!aEnable);
 }
 
-
 PRBool
 nsHTMLEditor::EnableExistingStyleSheet(const nsAString &aURL)
 {
   nsCOMPtr<nsICSSStyleSheet> sheet;
   nsresult rv = GetStyleSheetForURL(aURL, getter_AddRefs(sheet));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Enable sheet if already loaded.
   if (sheet)
   {
+    // Ensure the style sheet is owned by our document.
+    nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocWeak);
+    rv = sheet->SetOwningDocument(doc);
+    NS_ENSURE_SUCCESS(rv, rv);
+
     nsCOMPtr<nsIDOMStyleSheet> domSheet(do_QueryInterface(sheet));
     NS_ASSERTION(domSheet, "Sheet not implementing nsIDOMStyleSheet!");
     
     domSheet->SetDisabled(PR_FALSE);
     return PR_TRUE;
   }
   return PR_FALSE;
 }