Bug 1372829 - Part 2: mozilla::EditorBase should cache raw pointer of nsISelectionController and nsIDocument with nsWeakPtr

Tag #1375
This commit is contained in:
Matt A. Tobin
2020-04-17 05:47:12 -04:00
committed by Roy Tam
parent 5d444ef68a
commit 4e14355697
8 changed files with 288 additions and 164 deletions
+94 -66
View File
@@ -165,7 +165,7 @@ HTMLEditor::~HTMLEditor()
// free any default style propItems
RemoveAllDefaultProperties();
if (mLinkHandler && mDocWeak) {
if (mLinkHandler && IsInitialized()) {
nsCOMPtr<nsIPresShell> ps = GetPresShell();
if (ps && ps->GetPresContext()) {
@@ -335,7 +335,7 @@ HTMLEditor::PreDestroy(bool aDestroyingFrames)
return NS_OK;
}
nsCOMPtr<nsINode> document = do_QueryReferent(mDocWeak);
nsCOMPtr<nsIDocument> document = GetDocument();
if (document) {
document->RemoveMutationObserver(this);
}
@@ -365,7 +365,7 @@ HTMLEditor::UpdateRootElement()
} else {
// If there is no HTML body element,
// we should use the document root element instead.
nsCOMPtr<nsIDOMDocument> doc = do_QueryReferent(mDocWeak);
nsCOMPtr<nsIDOMDocument> doc = GetDOMDocument();
if (doc) {
doc->GetDocumentElement(getter_AddRefs(rootElement));
}
@@ -430,8 +430,9 @@ HTMLEditor::CreateEventListeners()
nsresult
HTMLEditor::InstallEventListeners()
{
NS_ENSURE_TRUE(mDocWeak && mEventListener,
NS_ERROR_NOT_INITIALIZED);
if (NS_WARN_IF(!IsInitialized()) || NS_WARN_IF(!mEventListener)) {
return NS_ERROR_NOT_INITIALIZED;
}
// NOTE: HTMLEditor doesn't need to initialize mEventTarget here because
// the target must be document node and it must be referenced as weak pointer.
@@ -444,7 +445,7 @@ HTMLEditor::InstallEventListeners()
void
HTMLEditor::RemoveEventListeners()
{
if (!mDocWeak) {
if (!IsInitialized()) {
return;
}
@@ -506,7 +507,8 @@ HTMLEditor::InitRules()
NS_IMETHODIMP
HTMLEditor::BeginningOfDocument()
{
if (!mDocWeak) {
// XXX Why doesn't this check if the document is alive?
if (!IsInitialized()) {
return NS_ERROR_NOT_INITIALIZED;
}
@@ -1183,11 +1185,13 @@ HTMLEditor::ReplaceHeadContentsWithHTML(const nsAString& aSourceToInsert)
// Do not use AutoRules -- rules code won't let us insert in <head>. Use
// the head node as a parent and delete/insert directly.
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
nsCOMPtr<nsIDocument> document = GetDocument();
if (NS_WARN_IF(!document)) {
return NS_ERROR_NOT_INITIALIZED;
}
RefPtr<nsContentList> nodeList =
doc->GetElementsByTagName(NS_LITERAL_STRING("head"));
document->GetElementsByTagName(NS_LITERAL_STRING("head"));
NS_ENSURE_TRUE(nodeList, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsIContent> headNode = nodeList->Item(0);
@@ -2705,7 +2709,7 @@ HTMLEditor::InsertLinkAroundSelection(nsIDOMElement* aAnchorElement)
nsresult
HTMLEditor::SetHTMLBackgroundColor(const nsAString& aColor)
{
NS_PRECONDITION(mDocWeak, "Missing Editor DOM Document");
MOZ_ASSERT(IsInitialized(), "The HTMLEditor hasn't been initialized yet");
// Find a selected or enclosing table element to set background on
nsCOMPtr<nsIDOMElement> element;
@@ -2753,7 +2757,7 @@ HTMLEditor::SetBodyAttribute(const nsAString& aAttribute,
{
// TODO: Check selection for Cell, Row, Column or table and do color on appropriate level
NS_ASSERTION(mDocWeak, "Missing Editor DOM Document");
MOZ_ASSERT(IsInitialized(), "The HTMLEditor hasn't been initialized yet");
// Set the background color attribute on the body tag
nsCOMPtr<nsIDOMElement> bodyElement = do_QueryInterface(GetRoot());
@@ -2832,7 +2836,9 @@ HTMLEditor::ReplaceStyleSheet(const nsAString& aURL)
}
// Make sure the pres shell doesn't disappear during the load.
NS_ENSURE_TRUE(mDocWeak, NS_ERROR_NOT_INITIALIZED);
if (NS_WARN_IF(!IsInitialized())) {
return NS_ERROR_NOT_INITIALIZED;
}
nsCOMPtr<nsIPresShell> ps = GetPresShell();
NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
@@ -2941,7 +2947,9 @@ HTMLEditor::RemoveOverrideStyleSheet(const nsAString& aURL)
NS_ENSURE_TRUE(sheet, NS_OK); /// Don't fail if sheet not found
NS_ENSURE_TRUE(mDocWeak, NS_ERROR_NOT_INITIALIZED);
if (NS_WARN_IF(!IsInitialized())) {
return NS_ERROR_NOT_INITIALIZED;
}
nsCOMPtr<nsIPresShell> ps = GetPresShell();
NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
@@ -2960,8 +2968,8 @@ HTMLEditor::EnableStyleSheet(const nsAString& aURL,
NS_ENSURE_TRUE(sheet, NS_OK); // Don't fail if sheet not found
// Ensure the style sheet is owned by our document.
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
sheet->SetAssociatedDocument(doc, StyleSheet::NotOwnedByDocument);
nsCOMPtr<nsIDocument> document = GetDocument();
sheet->SetAssociatedDocument(document, StyleSheet::NotOwnedByDocument);
if (sheet->IsServo()) {
// XXXheycam ServoStyleSheets don't support being enabled/disabled yet.
@@ -2982,8 +2990,8 @@ HTMLEditor::EnableExistingStyleSheet(const nsAString& aURL)
}
// Ensure the style sheet is owned by our document.
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
sheet->SetAssociatedDocument(doc, StyleSheet::NotOwnedByDocument);
nsCOMPtr<nsIDocument> document = GetDocument();
sheet->SetAssociatedDocument(document, StyleSheet::NotOwnedByDocument);
if (sheet->IsServo()) {
// XXXheycam ServoStyleSheets don't support being enabled/disabled yet.
@@ -3374,13 +3382,12 @@ HTMLEditor::GetIsSelectionEditable(bool* aIsSelectionEditable)
static nsresult
SetSelectionAroundHeadChildren(Selection* aSelection,
nsIWeakReference* aDocWeak)
nsCOMPtr<nsIDocument>& aDocument)
{
// Set selection around <head> node
nsCOMPtr<nsIDocument> doc = do_QueryReferent(aDocWeak);
NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
MOZ_ASSERT(aDocument);
dom::Element* headNode = doc->GetHeadElement();
// Set selection around <head> node
dom::Element* headNode = aDocument->GetHeadElement();
NS_ENSURE_STATE(headNode);
// Collapse selection to before first child of the head,
@@ -3401,7 +3408,11 @@ HTMLEditor::GetHeadContentsAsHTML(nsAString& aOutputString)
// Save current selection
AutoSelectionRestorer selectionRestorer(selection, this);
nsresult rv = SetSelectionAroundHeadChildren(selection, mDocWeak);
nsCOMPtr<nsIDocument> document = GetDocument();
if (NS_WARN_IF(!document)) {
return NS_ERROR_NOT_INITIALIZED;
}
nsresult rv = SetSelectionAroundHeadChildren(selection, document);
NS_ENSURE_SUCCESS(rv, rv);
rv = OutputToString(NS_LITERAL_STRING("text/html"),
@@ -4275,10 +4286,11 @@ HTMLEditor::IsVisTextNode(nsIContent* aNode,
uint32_t length = aNode->TextLength();
if (aSafeToAskFrames) {
nsCOMPtr<nsISelectionController> selCon;
nsresult rv = GetSelectionController(getter_AddRefs(selCon));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE);
nsCOMPtr<nsISelectionController> selectionController =
GetSelectionController();
if (NS_WARN_IF(!selectionController)) {
return NS_ERROR_FAILURE;
}
bool isVisible = false;
// ask the selection controller for information about whether any
// of the data in the node is really rendered. This is really
@@ -4286,7 +4298,8 @@ HTMLEditor::IsVisTextNode(nsIContent* aNode,
// So we put a call in the selection controller interface, since it's already
// in bed with frames anyway. (this is a fix for bug 22227, and a
// partial fix for bug 46209)
rv = selCon->CheckVisibilityContent(aNode, 0, length, &isVisible);
nsresult rv = selectionController->CheckVisibilityContent(aNode, 0, length,
&isVisible);
NS_ENSURE_SUCCESS(rv, rv);
if (isVisible) {
*outIsEmptyNode = false;
@@ -4802,7 +4815,9 @@ HTMLEditor::GetElementOrigin(nsIDOMElement* aElement,
aX = 0;
aY = 0;
NS_ENSURE_TRUE(mDocWeak, NS_ERROR_NOT_INITIALIZED);
if (NS_WARN_IF(!IsInitialized())) {
return NS_ERROR_NOT_INITIALIZED;
}
nsCOMPtr<nsIPresShell> ps = GetPresShell();
NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
@@ -4944,28 +4959,29 @@ HTMLEditor::GetReturnInParagraphCreatesNewParagraph(bool* aCreatesNewParagraph)
already_AddRefed<nsIContent>
HTMLEditor::GetFocusedContent()
{
NS_ENSURE_TRUE(mDocWeak, nullptr);
nsFocusManager* fm = nsFocusManager::GetFocusManager();
NS_ENSURE_TRUE(fm, nullptr);
nsCOMPtr<nsIContent> focusedContent = fm->GetFocusedContent();
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
bool inDesignMode = doc->HasFlag(NODE_IS_EDITABLE);
nsCOMPtr<nsIDocument> document = GetDocument();
if (NS_WARN_IF(!document)) {
return nullptr;
}
bool inDesignMode = document->HasFlag(NODE_IS_EDITABLE);
if (!focusedContent) {
// in designMode, nobody gets focus in most cases.
if (inDesignMode && OurWindowHasFocus()) {
nsCOMPtr<nsIContent> docRoot = doc->GetRootElement();
return docRoot.forget();
nsCOMPtr<nsIContent> rootContent = document->GetRootElement();
return rootContent.forget();
}
return nullptr;
}
if (inDesignMode) {
return OurWindowHasFocus() &&
nsContentUtils::ContentIsDescendantOf(focusedContent, doc) ?
focusedContent.forget() : nullptr;
nsContentUtils::ContentIsDescendantOf(focusedContent, document) ?
focusedContent.forget() : nullptr;
}
// We're HTML editor for contenteditable
@@ -4988,28 +5004,32 @@ HTMLEditor::GetFocusedContentForIME()
return nullptr;
}
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
NS_ENSURE_TRUE(doc, nullptr);
return doc->HasFlag(NODE_IS_EDITABLE) ? nullptr : focusedContent.forget();
nsCOMPtr<nsIDocument> document = GetDocument();
if (NS_WARN_IF(!document)) {
return nullptr;
}
return document->HasFlag(NODE_IS_EDITABLE) ? nullptr :
focusedContent.forget();
}
bool
HTMLEditor::IsActiveInDOMWindow()
{
NS_ENSURE_TRUE(mDocWeak, false);
nsFocusManager* fm = nsFocusManager::GetFocusManager();
NS_ENSURE_TRUE(fm, false);
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
bool inDesignMode = doc->HasFlag(NODE_IS_EDITABLE);
nsCOMPtr<nsIDocument> document = GetDocument();
if (NS_WARN_IF(!document)) {
return false;
}
bool inDesignMode = document->HasFlag(NODE_IS_EDITABLE);
// If we're in designMode, we're always active in the DOM window.
if (inDesignMode) {
return true;
}
nsPIDOMWindowOuter* ourWindow = doc->GetWindow();
nsPIDOMWindowOuter* ourWindow = document->GetWindow();
nsCOMPtr<nsPIDOMWindowOuter> win;
nsIContent* content =
nsFocusManager::GetFocusedDescendant(ourWindow, false,
@@ -5032,12 +5052,12 @@ HTMLEditor::IsActiveInDOMWindow()
Element*
HTMLEditor::GetActiveEditingHost()
{
NS_ENSURE_TRUE(mDocWeak, nullptr);
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
NS_ENSURE_TRUE(doc, nullptr);
if (doc->HasFlag(NODE_IS_EDITABLE)) {
return doc->GetBodyElement();
nsCOMPtr<nsIDocument> document = GetDocument();
if (NS_WARN_IF(!document)) {
return nullptr;
}
if (document->HasFlag(NODE_IS_EDITABLE)) {
return document->GetBodyElement();
}
// We're HTML editor for contenteditable
@@ -5066,8 +5086,8 @@ HTMLEditor::GetDOMEventTarget()
// Don't use getDocument here, because we have no way of knowing
// whether Init() was ever called. So we need to get the document
// ourselves, if it exists.
NS_PRECONDITION(mDocWeak, "This editor has not been initialized yet");
nsCOMPtr<mozilla::dom::EventTarget> target = do_QueryReferent(mDocWeak);
MOZ_ASSERT(IsInitialized(), "The HTMLEditor has not been initialized yet");
nsCOMPtr<mozilla::dom::EventTarget> target = GetDocument();
return target.forget();
}
@@ -5121,12 +5141,16 @@ HTMLEditor::NotifyRootChanged()
nsresult
HTMLEditor::GetBodyElement(nsIDOMHTMLElement** aBody)
{
NS_PRECONDITION(mDocWeak, "bad state, null mDocWeak");
nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryReferent(mDocWeak);
if (!htmlDoc) {
MOZ_ASSERT(IsInitialized(), "The HTMLEditor hasn't been initialized yet");
nsCOMPtr<nsIDocument> document = GetDocument();
if (NS_WARN_IF(!document)) {
return NS_ERROR_NOT_INITIALIZED;
}
return htmlDoc->GetBody(aBody);
nsCOMPtr<nsIDOMHTMLDocument> domHTMLDocument = do_QueryInterface(document);
if (!domHTMLDocument) {
return NS_ERROR_NOT_INITIALIZED;
}
return domHTMLDocument->GetBody(aBody);
}
already_AddRefed<nsINode>
@@ -5146,14 +5170,13 @@ HTMLEditor::GetFocusedNode()
return node.forget();
}
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
return doc.forget();
nsCOMPtr<nsIDocument> document = GetDocument();
return document.forget();
}
bool
HTMLEditor::OurWindowHasFocus()
{
NS_ENSURE_TRUE(mDocWeak, false);
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
NS_ENSURE_TRUE(fm, false);
nsCOMPtr<mozIDOMWindowProxy> focusedWindow;
@@ -5161,8 +5184,11 @@ HTMLEditor::OurWindowHasFocus()
if (!focusedWindow) {
return false;
}
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
nsPIDOMWindowOuter* ourWindow = doc->GetWindow();
nsCOMPtr<nsIDocument> document = GetDocument();
if (NS_WARN_IF(!document)) {
return false;
}
nsPIDOMWindowOuter* ourWindow = document->GetWindow();
return ourWindow == focusedWindow;
}
@@ -5180,12 +5206,14 @@ HTMLEditor::IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent)
return true;
}
NS_ENSURE_TRUE(mDocWeak, false);
nsCOMPtr<nsIDOMEventTarget> target = aGUIEvent->GetDOMEventTarget();
NS_ENSURE_TRUE(target, false);
nsCOMPtr<nsIDocument> document = do_QueryReferent(mDocWeak);
nsCOMPtr<nsIDocument> document = GetDocument();
if (NS_WARN_IF(!document)) {
return false;
}
if (document->HasFlag(NODE_IS_EDITABLE)) {
// If this editor is in designMode and the event target is the document,
// the event is for this editor.