summaryrefslogtreecommitdiffstats
path: root/editor/libeditor/EditorBase.cpp
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2020-04-17 05:47:12 -0400
committerMatt A. Tobin <email@mattatobin.com>2020-04-17 05:47:12 -0400
commit32e8155127126c187ce32f7368742057bcaf69da (patch)
tree61fd4472558f959f7695b3940e7ed5ea7628e5ed /editor/libeditor/EditorBase.cpp
parent2e2190a5044943bde31679996afdc3558d22231b (diff)
downloadUXP-32e8155127126c187ce32f7368742057bcaf69da.tar
UXP-32e8155127126c187ce32f7368742057bcaf69da.tar.gz
UXP-32e8155127126c187ce32f7368742057bcaf69da.tar.lz
UXP-32e8155127126c187ce32f7368742057bcaf69da.tar.xz
UXP-32e8155127126c187ce32f7368742057bcaf69da.zip
Bug 1372829 - Part 2: mozilla::EditorBase should cache raw pointer of nsISelectionController and nsIDocument with nsWeakPtr
Tag #1375
Diffstat (limited to 'editor/libeditor/EditorBase.cpp')
-rw-r--r--editor/libeditor/EditorBase.cpp214
1 files changed, 124 insertions, 90 deletions
diff --git a/editor/libeditor/EditorBase.cpp b/editor/libeditor/EditorBase.cpp
index f068e9179..5df4ff2c4 100644
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -37,6 +37,7 @@
#include "mozilla/TextComposition.h" // for TextComposition
#include "mozilla/TextEvents.h"
#include "mozilla/dom/Element.h" // for Element, nsINode::AsElement
+#include "mozilla/dom/HTMLBodyElement.h"
#include "mozilla/dom/Text.h"
#include "mozilla/dom/Event.h"
#include "mozilla/mozalloc.h" // for operator new, etc.
@@ -71,7 +72,6 @@
#include "nsIDOMNode.h" // for nsIDOMNode, etc.
#include "nsIDOMNodeList.h" // for nsIDOMNodeList
#include "nsIDOMText.h" // for nsIDOMText
-#include "nsIDocument.h" // for nsIDocument
#include "nsIDocumentStateListener.h" // for nsIDocumentStateListener
#include "nsIEditActionListener.h" // for nsIEditActionListener
#include "nsIEditorObserver.h" // for nsIEditorObserver
@@ -151,7 +151,8 @@ EditorBase::EditorBase()
EditorBase::~EditorBase()
{
- NS_ASSERTION(!mDocWeak || mDidPreDestroy, "Why PreDestroy hasn't been called?");
+ MOZ_ASSERT(!IsInitialized() || mDidPreDestroy,
+ "Why PreDestroy hasn't been called?");
if (mComposition) {
mComposition->OnEditorDestroyed();
@@ -220,20 +221,21 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(EditorBase)
NS_IMETHODIMP
-EditorBase::Init(nsIDOMDocument* aDoc,
+EditorBase::Init(nsIDOMDocument* aDOMDocument,
nsIContent* aRoot,
- nsISelectionController* aSelCon,
+ nsISelectionController* aSelectionController,
uint32_t aFlags,
const nsAString& aValue)
{
MOZ_ASSERT(mAction == EditAction::none,
"Initializing during an edit action is an error");
- MOZ_ASSERT(aDoc);
- if (!aDoc)
+ MOZ_ASSERT(aDOMDocument);
+ if (!aDOMDocument) {
return NS_ERROR_NULL_POINTER;
+ }
// First only set flags, but other stuff shouldn't be initialized now.
- // Don't move this call after initializing mDocWeak.
+ // Don't move this call after initializing mDocumentWeak.
// SetFlags() can check whether it's called during initialization or not by
// them. Note that SetFlags() will be called by PostCreate().
#ifdef DEBUG
@@ -242,19 +244,21 @@ EditorBase::Init(nsIDOMDocument* aDoc,
SetFlags(aFlags);
NS_ASSERTION(NS_SUCCEEDED(rv), "SetFlags() failed");
- mDocWeak = do_GetWeakReference(aDoc); // weak reference to doc
+ nsCOMPtr<nsIDocument> document = do_QueryInterface(aDOMDocument);
+ mDocumentWeak = document.get();
// HTML editors currently don't have their own selection controller,
// so they'll pass null as aSelCon, and we'll get the selection controller
// off of the presshell.
- nsCOMPtr<nsISelectionController> selCon;
- if (aSelCon) {
- mSelConWeak = do_GetWeakReference(aSelCon); // weak reference to selectioncontroller
- selCon = aSelCon;
+ nsCOMPtr<nsISelectionController> selectionController;
+ if (aSelectionController) {
+ mSelectionControllerWeak = aSelectionController;
+ selectionController = aSelectionController;
} else {
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
- selCon = do_QueryInterface(presShell);
+ selectionController = do_QueryInterface(presShell);
}
- NS_ASSERTION(selCon, "Selection controller should be available at this point");
+ MOZ_ASSERT(selectionController,
+ "Selection controller should be available at this point");
//set up root element if we are passed one.
if (aRoot)
@@ -271,13 +275,14 @@ EditorBase::Init(nsIDOMDocument* aDoc,
mIMETextNode = nullptr;
}
- /* Show the caret */
- selCon->SetCaretReadOnly(false);
- selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
-
- selCon->SetSelectionFlags(nsISelectionDisplay::DISPLAY_ALL);//we want to see all the selection reflected to user
+ // Show the caret.
+ selectionController->SetCaretReadOnly(false);
+ selectionController->SetDisplaySelection(
+ nsISelectionController::SELECTION_ON);
+ // Show all the selection reflected to user.
+ selectionController->SetSelectionFlags(nsISelectionDisplay::DISPLAY_ALL);
- NS_POSTCONDITION(mDocWeak, "bad state");
+ MOZ_ASSERT(IsInitialized());
// Make sure that the editor will be destroyed properly
mDidPreDestroy = false;
@@ -356,8 +361,9 @@ EditorBase::CreateEventListeners()
nsresult
EditorBase::InstallEventListeners()
{
- NS_ENSURE_TRUE(mDocWeak && mEventListener,
- NS_ERROR_NOT_INITIALIZED);
+ if (NS_WARN_IF(!IsInitialized()) || NS_WARN_IF(!mEventListener)) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
// Initialize the event target.
nsCOMPtr<nsIContent> rootContent = GetRoot();
@@ -378,7 +384,7 @@ EditorBase::InstallEventListeners()
void
EditorBase::RemoveEventListeners()
{
- if (!mDocWeak || !mEventListener) {
+ if (!IsInitialized() || !mEventListener) {
return;
}
reinterpret_cast<EditorEventListener*>(mEventListener.get())->Disconnect();
@@ -501,7 +507,7 @@ EditorBase::SetFlags(uint32_t aFlags)
bool spellcheckerWasEnabled = CanEnableSpellCheck();
mFlags = aFlags;
- if (!mDocWeak) {
+ if (!IsInitialized()) {
// If we're initializing, we shouldn't do anything now.
// SetFlags() will be called by PostCreate(),
// we should synchronize some stuff for the flags at that time.
@@ -567,17 +573,15 @@ EditorBase::GetIsDocumentEditable(bool* aIsDocumentEditable)
already_AddRefed<nsIDocument>
EditorBase::GetDocument()
{
- NS_PRECONDITION(mDocWeak, "bad state, mDocWeak weak pointer not initialized");
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
- return doc.forget();
+ nsCOMPtr<nsIDocument> document = mDocumentWeak.get();
+ return document.forget();
}
already_AddRefed<nsIDOMDocument>
EditorBase::GetDOMDocument()
{
- NS_PRECONDITION(mDocWeak, "bad state, mDocWeak weak pointer not initialized");
- nsCOMPtr<nsIDOMDocument> doc = do_QueryReferent(mDocWeak);
- return doc.forget();
+ nsCOMPtr<nsIDOMDocument> domDocument = do_QueryInterface(mDocumentWeak);
+ return domDocument.forget();
}
NS_IMETHODIMP
@@ -590,11 +594,12 @@ EditorBase::GetDocument(nsIDOMDocument** aDoc)
already_AddRefed<nsIPresShell>
EditorBase::GetPresShell()
{
- NS_PRECONDITION(mDocWeak, "bad state, null mDocWeak");
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
- NS_ENSURE_TRUE(doc, nullptr);
- nsCOMPtr<nsIPresShell> ps = doc->GetShell();
- return ps.forget();
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ if (NS_WARN_IF(!document)) {
+ return nullptr;
+ }
+ nsCOMPtr<nsIPresShell> presShell = document->GetShell();
+ return presShell.forget();
}
already_AddRefed<nsIWidget>
@@ -640,14 +645,14 @@ EditorBase::GetSelectionController(nsISelectionController** aSel)
already_AddRefed<nsISelectionController>
EditorBase::GetSelectionController()
{
- nsCOMPtr<nsISelectionController> selCon;
- if (mSelConWeak) {
- selCon = do_QueryReferent(mSelConWeak);
+ nsCOMPtr<nsISelectionController> selectionController;
+ if (mSelectionControllerWeak) {
+ selectionController = mSelectionControllerWeak.get();
} else {
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
- selCon = do_QueryInterface(presShell);
+ selectionController = do_QueryInterface(presShell);
}
- return selCon.forget();
+ return selectionController.forget();
}
NS_IMETHODIMP
@@ -1065,7 +1070,8 @@ EditorBase::GetDocumentIsEmpty(bool* aDocumentIsEmpty)
NS_IMETHODIMP
EditorBase::SelectAll()
{
- if (!mDocWeak) {
+ // XXX Why doesn't this check if the document is alive?
+ if (!IsInitialized()) {
return NS_ERROR_NOT_INITIALIZED;
}
ForceCompositionEnd();
@@ -1078,7 +1084,8 @@ EditorBase::SelectAll()
NS_IMETHODIMP
EditorBase::BeginningOfDocument()
{
- if (!mDocWeak) {
+ // XXX Why doesn't this check if the document is alive?
+ if (!IsInitialized()) {
return NS_ERROR_NOT_INITIALIZED;
}
@@ -1115,7 +1122,10 @@ EditorBase::BeginningOfDocument()
NS_IMETHODIMP
EditorBase::EndOfDocument()
{
- NS_ENSURE_TRUE(mDocWeak, NS_ERROR_NOT_INITIALIZED);
+ // XXX Why doesn't this check if the document is alive?
+ if (NS_WARN_IF(!IsInitialized())) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
// get selection
RefPtr<Selection> selection = GetSelection();
@@ -1150,20 +1160,22 @@ EditorBase::GetDocumentModified(bool* outDocModified)
NS_IMETHODIMP
EditorBase::GetDocumentCharacterSet(nsACString& characterSet)
{
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
- NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
-
- characterSet = doc->GetDocumentCharacterSet();
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ if (NS_WARN_IF(!document)) {
+ return NS_ERROR_UNEXPECTED;
+ }
+ characterSet = document->GetDocumentCharacterSet();
return NS_OK;
}
NS_IMETHODIMP
EditorBase::SetDocumentCharacterSet(const nsACString& characterSet)
{
- nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocWeak);
- NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
-
- doc->SetDocumentCharacterSet(characterSet);
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ if (NS_WARN_IF(!document)) {
+ return NS_ERROR_UNEXPECTED;
+ }
+ document->SetDocumentCharacterSet(characterSet);
return NS_OK;
}
@@ -2004,12 +2016,17 @@ NS_IMETHODIMP
EditorBase::DebugDumpContent()
{
#ifdef DEBUG
- nsCOMPtr<nsIDOMHTMLDocument> doc = do_QueryReferent(mDocWeak);
- NS_ENSURE_TRUE(doc, NS_ERROR_NOT_INITIALIZED);
-
- nsCOMPtr<nsIDOMHTMLElement>bodyElem;
- doc->GetBody(getter_AddRefs(bodyElem));
- nsCOMPtr<nsIContent> content = do_QueryInterface(bodyElem);
+ nsCOMPtr<nsIDocument> document = GetDocument();
+ if (NS_WARN_IF(!document)) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ nsCOMPtr<nsIDOMHTMLDocument> domHTMLDocument = do_QueryInterface(document);
+ if (NS_WARN_IF(!domHTMLDocument)) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ nsCOMPtr<nsIDOMHTMLElement> bodyElement;
+ domHTMLDocument->GetBody(getter_AddRefs(bodyElement));
+ nsCOMPtr<nsIContent> content = do_QueryInterface(bodyElement);
if (content) {
content->List();
}
@@ -2323,18 +2340,20 @@ EditorBase::CloneAttributes(Element* aDest,
NS_IMETHODIMP
EditorBase::ScrollSelectionIntoView(bool aScrollToAnchor)
{
- nsCOMPtr<nsISelectionController> selCon;
- if (NS_SUCCEEDED(GetSelectionController(getter_AddRefs(selCon))) && selCon) {
- int16_t region = nsISelectionController::SELECTION_FOCUS_REGION;
-
- if (aScrollToAnchor) {
- region = nsISelectionController::SELECTION_ANCHOR_REGION;
- }
-
- selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
- region, nsISelectionController::SCROLL_OVERFLOW_HIDDEN);
+ nsCOMPtr<nsISelectionController> selectionController =
+ GetSelectionController();
+ if (!selectionController) {
+ return NS_OK;
}
+ int16_t region = nsISelectionController::SELECTION_FOCUS_REGION;
+ if (aScrollToAnchor) {
+ region = nsISelectionController::SELECTION_ANCHOR_REGION;
+ }
+ selectionController->ScrollSelectionIntoView(
+ nsISelectionController::SELECTION_NORMAL,
+ region,
+ nsISelectionController::SCROLL_OVERFLOW_HIDDEN);
return NS_OK;
}
@@ -4784,22 +4803,27 @@ EditorBase::InitializeSelection(nsIDOMEventTarget* aFocusEventTarget)
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_INITIALIZED);
- nsCOMPtr<nsISelectionController> selCon;
- nsresult rv = GetSelectionController(getter_AddRefs(selCon));
- NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsISelectionController> selectionController =
+ GetSelectionController();
+ if (NS_WARN_IF(!selectionController)) {
+ return NS_ERROR_FAILURE;
+ }
// Init the caret
RefPtr<nsCaret> caret = presShell->GetCaret();
NS_ENSURE_TRUE(caret, NS_ERROR_UNEXPECTED);
caret->SetIgnoreUserModify(false);
caret->SetSelection(selection);
- selCon->SetCaretReadOnly(IsReadonly());
- selCon->SetCaretEnabled(true);
+ selectionController->SetCaretReadOnly(IsReadonly());
+ selectionController->SetCaretEnabled(true);
// Init selection
- selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
- selCon->SetSelectionFlags(nsISelectionDisplay::DISPLAY_ALL);
- selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL);
+ selectionController->SetDisplaySelection(
+ nsISelectionController::SELECTION_ON);
+ selectionController->SetSelectionFlags(
+ nsISelectionDisplay::DISPLAY_ALL);
+ selectionController->RepaintSelection(
+ nsISelectionController::SELECTION_NORMAL);
// If the computed selection root isn't root content, we should set it
// as selection ancestor limit. However, if that is root element, it means
// there is not limitation of the selection, then, we must set nullptr.
@@ -4867,9 +4891,11 @@ private:
NS_IMETHODIMP
EditorBase::FinalizeSelection()
{
- nsCOMPtr<nsISelectionController> selCon;
- nsresult rv = GetSelectionController(getter_AddRefs(selCon));
- NS_ENSURE_SUCCESS(rv, rv);
+ nsCOMPtr<nsISelectionController> selectionController =
+ GetSelectionController();
+ if (NS_WARN_IF(!selectionController)) {
+ return NS_ERROR_FAILURE;
+ }
RefPtr<Selection> selection = GetSelection();
NS_ENSURE_STATE(selection);
@@ -4879,7 +4905,7 @@ EditorBase::FinalizeSelection()
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_INITIALIZED);
- selCon->SetCaretEnabled(false);
+ selectionController->SetCaretEnabled(false);
nsFocusManager* fm = nsFocusManager::GetFocusManager();
NS_ENSURE_TRUE(fm, NS_ERROR_NOT_INITIALIZED);
@@ -4894,29 +4920,33 @@ EditorBase::FinalizeSelection()
ErrorResult ret;
if (!doc || !doc->HasFocus(ret)) {
// If the document already lost focus, mark the selection as disabled.
- selCon->SetDisplaySelection(nsISelectionController::SELECTION_DISABLED);
+ selectionController->SetDisplaySelection(
+ nsISelectionController::SELECTION_DISABLED);
} else {
// Otherwise, mark selection as normal because outside of a
// contenteditable element should be selected with normal selection
// color after here.
- selCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
+ selectionController->SetDisplaySelection(
+ nsISelectionController::SELECTION_ON);
}
} else if (IsFormWidget() || IsPasswordEditor() ||
IsReadonly() || IsDisabled() || IsInputFiltered()) {
// In <input> or <textarea>, the independent selection should be hidden
// while this editor doesn't have focus.
- selCon->SetDisplaySelection(nsISelectionController::SELECTION_HIDDEN);
+ selectionController->SetDisplaySelection(
+ nsISelectionController::SELECTION_HIDDEN);
} else {
// Otherwise, although we're not sure how this case happens, the
// independent selection should be marked as disabled.
- selCon->SetDisplaySelection(nsISelectionController::SELECTION_DISABLED);
+ selectionController->SetDisplaySelection(
+ nsISelectionController::SELECTION_DISABLED);
}
// FinalizeSelection might be called from ContentRemoved even if selection
// isn't updated. So we need to call RepaintSelection after updated it.
nsContentUtils::AddScriptRunner(
- new RepaintSelectionRunner(selCon));
+ new RepaintSelectionRunner(selectionController));
return NS_OK;
}
@@ -5127,8 +5157,11 @@ EditorBase::IsActiveInDOMWindow()
nsFocusManager* fm = nsFocusManager::GetFocusManager();
NS_ENSURE_TRUE(fm, 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();
nsCOMPtr<nsPIDOMWindowOuter> win;
nsIContent* content =
nsFocusManager::GetFocusedDescendant(ourWindow, false,
@@ -5236,10 +5269,11 @@ EditorBase::GetIMESelectionStartOffsetIn(nsINode* aTextNode)
{
MOZ_ASSERT(aTextNode, "aTextNode must not be nullptr");
- nsCOMPtr<nsISelectionController> selectionController;
- nsresult rv = GetSelectionController(getter_AddRefs(selectionController));
- NS_ENSURE_SUCCESS(rv, -1);
- NS_ENSURE_TRUE(selectionController, -1);
+ nsCOMPtr<nsISelectionController> selectionController =
+ GetSelectionController();
+ if (NS_WARN_IF(!selectionController)) {
+ return -1;
+ }
int32_t minOffset = INT32_MAX;
static const SelectionType kIMESelectionTypes[] = {