/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/EditorBase.h" #include "mozilla/DebugOnly.h" // for DebugOnly #include // for nullptr, stdout #include // for strcmp #include "ChangeAttributeTransaction.h" // for ChangeAttributeTransaction #include "CompositionTransaction.h" // for CompositionTransaction #include "CreateElementTransaction.h" // for CreateElementTransaction #include "DeleteNodeTransaction.h" // for DeleteNodeTransaction #include "DeleteRangeTransaction.h" // for DeleteRangeTransaction #include "DeleteTextTransaction.h" // for DeleteTextTransaction #include "EditAggregateTransaction.h" // for EditAggregateTransaction #include "EditorEventListener.h" // for EditorEventListener #include "InsertNodeTransaction.h" // for InsertNodeTransaction #include "InsertTextTransaction.h" // for InsertTextTransaction #include "JoinNodeTransaction.h" // for JoinNodeTransaction #include "PlaceholderTransaction.h" // for PlaceholderTransaction #include "SplitNodeTransaction.h" // for SplitNodeTransaction #include "StyleSheetTransactions.h" // for AddStyleSheetTransaction, etc. #include "TextEditUtils.h" // for TextEditUtils #include "mozFlushType.h" // for mozFlushType::Flush_Frames #include "mozInlineSpellChecker.h" // for mozInlineSpellChecker #include "mozilla/CheckedInt.h" // for CheckedInt #include "mozilla/EditorUtils.h" // for AutoRules, etc. #include "mozilla/EditTransactionBase.h" // for EditTransactionBase #include "mozilla/IMEStateManager.h" // for IMEStateManager #include "mozilla/Preferences.h" // for Preferences #include "mozilla/dom/Selection.h" // for Selection, etc. #include "mozilla/Services.h" // for GetObserverService #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. #include "nsAString.h" // for nsAString_internal::Length, etc. #include "nsCCUncollectableMarker.h" // for nsCCUncollectableMarker #include "nsCaret.h" // for nsCaret #include "nsCaseTreatment.h" #include "nsCharTraits.h" // for NS_IS_HIGH_SURROGATE, etc. #include "nsComponentManagerUtils.h" // for do_CreateInstance #include "nsComputedDOMStyle.h" // for nsComputedDOMStyle #include "nsContentUtils.h" // for nsContentUtils #include "nsDOMString.h" // for DOMStringIsNull #include "nsDebug.h" // for NS_ENSURE_TRUE, etc. #include "nsError.h" // for NS_OK, etc. #include "nsFocusManager.h" // for nsFocusManager #include "nsFrameSelection.h" // for nsFrameSelection #include "nsGkAtoms.h" // for nsGkAtoms, nsGkAtoms::dir #include "nsIAbsorbingTransaction.h" // for nsIAbsorbingTransaction #include "nsIAtom.h" // for nsIAtom #include "nsIContent.h" // for nsIContent #include "nsIDOMAttr.h" // for nsIDOMAttr #include "nsIDOMCharacterData.h" // for nsIDOMCharacterData #include "nsIDOMDocument.h" // for nsIDOMDocument #include "nsIDOMElement.h" // for nsIDOMElement #include "nsIDOMEvent.h" // for nsIDOMEvent #include "nsIDOMEventListener.h" // for nsIDOMEventListener #include "nsIDOMEventTarget.h" // for nsIDOMEventTarget #include "nsIDOMHTMLElement.h" // for nsIDOMHTMLElement #include "nsIDOMKeyEvent.h" // for nsIDOMKeyEvent, etc. #include "nsIDOMMozNamedAttrMap.h" // for nsIDOMMozNamedAttrMap #include "nsIDOMMouseEvent.h" // for nsIDOMMouseEvent #include "nsIDOMNode.h" // for nsIDOMNode, etc. #include "nsIDOMNodeList.h" // for nsIDOMNodeList #include "nsIDOMText.h" // for nsIDOMText #include "nsIDocumentStateListener.h" // for nsIDocumentStateListener #include "nsIEditActionListener.h" // for nsIEditActionListener #include "nsIEditorObserver.h" // for nsIEditorObserver #include "nsIEditorSpellCheck.h" // for nsIEditorSpellCheck #include "nsIFrame.h" // for nsIFrame #include "nsIHTMLDocument.h" // for nsIHTMLDocument #include "nsIInlineSpellChecker.h" // for nsIInlineSpellChecker, etc. #include "nsNameSpaceManager.h" // for kNameSpaceID_None, etc. #include "nsINode.h" // for nsINode, etc. #include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc. #include "nsIPresShell.h" // for nsIPresShell #include "nsISelectionController.h" // for nsISelectionController, etc. #include "nsISelectionDisplay.h" // for nsISelectionDisplay, etc. #include "nsISupportsBase.h" // for nsISupports #include "nsISupportsUtils.h" // for NS_ADDREF, NS_IF_ADDREF #include "nsITransaction.h" // for nsITransaction #include "nsITransactionManager.h" #include "nsIWeakReference.h" // for nsISupportsWeakReference #include "nsIWidget.h" // for nsIWidget, IMEState, etc. #include "nsPIDOMWindow.h" // for nsPIDOMWindow #include "nsPresContext.h" // for nsPresContext #include "nsRange.h" // for nsRange #include "nsReadableUtils.h" // for EmptyString, ToNewCString #include "nsString.h" // for nsAutoString, nsString, etc. #include "nsStringFwd.h" // for nsAFlatString #include "nsStyleConsts.h" // for NS_STYLE_DIRECTION_RTL, etc. #include "nsStyleContext.h" // for nsStyleContext #include "nsStyleStruct.h" // for nsStyleDisplay, nsStyleText, etc. #include "nsStyleStructFwd.h" // for nsIFrame::StyleUIReset, etc. #include "nsTextNode.h" // for nsTextNode #include "nsThreadUtils.h" // for nsRunnable #include "nsTransactionManager.h" // for nsTransactionManager #include "prtime.h" // for PR_Now class nsIOutputStream; class nsITransferable; #ifdef DEBUG #include "nsIDOMHTMLDocument.h" // for nsIDOMHTMLDocument #endif namespace mozilla { using namespace dom; using namespace widget; /***************************************************************************** * mozilla::EditorBase *****************************************************************************/ EditorBase::EditorBase() : mPlaceholderName(nullptr) , mSelState(nullptr) , mPhonetic(nullptr) , mModCount(0) , mFlags(0) , mUpdateCount(0) , mPlaceholderBatch(0) , mAction(EditAction::none) , mIMETextOffset(0) , mIMETextLength(0) , mDirection(eNone) , mDocDirtyState(-1) , mSpellcheckCheckboxState(eTriUnset) , mShouldTxnSetSelection(true) , mDidPreDestroy(false) , mDidPostCreate(false) , mDispatchInputEvent(true) , mIsInEditAction(false) , mHidingCaret(false) { } EditorBase::~EditorBase() { MOZ_ASSERT(!IsInitialized() || mDidPreDestroy, "Why PreDestroy hasn't been called?"); if (mComposition) { mComposition->OnEditorDestroyed(); mComposition = nullptr; } // If this editor is still hiding the caret, we need to restore it. HideCaret(false); mTxnMgr = nullptr; delete mPhonetic; } NS_IMPL_CYCLE_COLLECTION_CLASS(EditorBase) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(EditorBase) NS_IMPL_CYCLE_COLLECTION_UNLINK(mRootElement) NS_IMPL_CYCLE_COLLECTION_UNLINK(mInlineSpellChecker) NS_IMPL_CYCLE_COLLECTION_UNLINK(mTxnMgr) NS_IMPL_CYCLE_COLLECTION_UNLINK(mIMETextNode) NS_IMPL_CYCLE_COLLECTION_UNLINK(mActionListeners) NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditorObservers) NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocStateListeners) NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventTarget) if (tmp->mEventListener) { EditorEventListener* listener = reinterpret_cast(tmp->mEventListener.get()); listener->Disconnect(); tmp->mEventListener = nullptr; } NS_IMPL_CYCLE_COLLECTION_UNLINK(mSavedSel); NS_IMPL_CYCLE_COLLECTION_UNLINK(mRangeUpdater); NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(EditorBase) nsIDocument* currentDoc = tmp->mRootElement ? tmp->mRootElement->GetUncomposedDoc() : nullptr; if (currentDoc && nsCCUncollectableMarker::InGeneration(cb, currentDoc->GetMarkedCCGeneration())) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRootElement) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInlineSpellChecker) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTxnMgr) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIMETextNode) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mActionListeners) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEditorObservers) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocStateListeners) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventTarget) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventListener) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSavedSel); NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRangeUpdater); NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EditorBase) NS_INTERFACE_MAP_ENTRY(nsIPhonetic) NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) NS_INTERFACE_MAP_ENTRY(nsIEditorIMESupport) NS_INTERFACE_MAP_ENTRY(nsIEditor) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIEditor) NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTING_ADDREF(EditorBase) NS_IMPL_CYCLE_COLLECTING_RELEASE(EditorBase) NS_IMETHODIMP EditorBase::Init(nsIDOMDocument* aDOMDocument, nsIContent* aRoot, nsISelectionController* aSelectionController, uint32_t aFlags, const nsAString& aValue) { MOZ_ASSERT(mAction == EditAction::none, "Initializing during an edit action is an error"); 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 mDocumentWeak. // SetFlags() can check whether it's called during initialization or not by // them. Note that SetFlags() will be called by PostCreate(). #ifdef DEBUG nsresult rv = #endif SetFlags(aFlags); NS_ASSERTION(NS_SUCCEEDED(rv), "SetFlags() failed"); nsCOMPtr 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 selectionController; if (aSelectionController) { mSelectionControllerWeak = aSelectionController; selectionController = aSelectionController; } else { nsCOMPtr presShell = GetPresShell(); selectionController = do_QueryInterface(presShell); } MOZ_ASSERT(selectionController, "Selection controller should be available at this point"); //set up root element if we are passed one. if (aRoot) mRootElement = do_QueryInterface(aRoot); mUpdateCount=0; // If this is an editor for or