Bug 432114. Change style sheet owner to the document being edited. r+sr=peterv
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;
}