| File: | root/firefox-clang/obj-x86_64-pc-linux-gnu/editor/libeditor/./../../../editor/libeditor/TextEditor.cpp |
| Warning: | line 703, column 12 Value stored to 'rv' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| 4 | |
| 5 | #include "TextEditor.h" |
| 6 | |
| 7 | #include <algorithm> |
| 8 | |
| 9 | #include "EditAction.h" |
| 10 | #include "EditAggregateTransaction.h" |
| 11 | #include "EditorDOMPoint.h" |
| 12 | #include "EditorUtils.h" |
| 13 | #include "HTMLEditor.h" |
| 14 | #include "InternetCiter.h" |
| 15 | #include "PlaceholderTransaction.h" |
| 16 | #include "gfxFontUtils.h" |
| 17 | |
| 18 | #include "mozilla/dom/DocumentInlines.h" |
| 19 | #include "mozilla/Assertions.h" |
| 20 | #include "mozilla/ContentIterator.h" |
| 21 | #include "mozilla/IMEStateManager.h" |
| 22 | #include "mozilla/Logging.h" |
| 23 | #include "mozilla/LookAndFeel.h" |
| 24 | #include "mozilla/mozalloc.h" |
| 25 | #include "mozilla/Preferences.h" |
| 26 | #include "mozilla/PresShell.h" |
| 27 | #include "mozilla/StaticPrefs_dom.h" |
| 28 | #include "mozilla/StaticPrefs_editor.h" |
| 29 | #include "mozilla/TextComposition.h" |
| 30 | #include "mozilla/TextEvents.h" |
| 31 | #include "mozilla/TextServicesDocument.h" |
| 32 | #include "mozilla/Try.h" |
| 33 | #include "mozilla/dom/CharacterDataBuffer.h" |
| 34 | #include "mozilla/dom/Event.h" |
| 35 | #include "mozilla/dom/Element.h" |
| 36 | #include "mozilla/dom/Selection.h" |
| 37 | #include "mozilla/dom/StaticRange.h" |
| 38 | |
| 39 | #include "nsAString.h" |
| 40 | #include "nsCRT.h" |
| 41 | #include "nsCaret.h" |
| 42 | #include "nsCharTraits.h" |
| 43 | #include "nsComponentManagerUtils.h" |
| 44 | #include "mozilla/dom/ContentList.h" |
| 45 | #include "mozilla/Utf16.h" |
| 46 | #include "nsDebug.h" |
| 47 | #include "nsDependentSubstring.h" |
| 48 | #include "nsError.h" |
| 49 | #include "nsFocusManager.h" |
| 50 | #include "nsGkAtoms.h" |
| 51 | #include "nsIContent.h" |
| 52 | #include "nsINode.h" |
| 53 | #include "nsIPrincipal.h" |
| 54 | #include "nsISelectionController.h" |
| 55 | #include "nsISupportsPrimitives.h" |
| 56 | #include "nsITransferable.h" |
| 57 | #include "nsIWeakReferenceUtils.h" |
| 58 | #include "nsNameSpaceManager.h" |
| 59 | #include "nsLiteralString.h" |
| 60 | #include "nsPresContext.h" |
| 61 | #include "nsReadableUtils.h" |
| 62 | #include "nsServiceManagerUtils.h" |
| 63 | #include "nsString.h" |
| 64 | #include "nsStringFwd.h" |
| 65 | #include "nsTextNode.h" |
| 66 | #include "nsUnicharUtils.h" |
| 67 | #include "nsXPCOM.h" |
| 68 | |
| 69 | class nsIOutputStream; |
| 70 | class nsISupports; |
| 71 | |
| 72 | namespace mozilla { |
| 73 | |
| 74 | // This logs the important things for the lifecycle of the TextEditor. |
| 75 | LazyLogModule gTextEditorLog("TextEditor"); |
| 76 | |
| 77 | static void LogOrWarn(const TextEditor* aTextEditor, LazyLogModule& aLog, |
| 78 | LogLevel aLogLevel, const char* aStr) { |
| 79 | #ifdef DEBUG1 |
| 80 | if (MOZ_LOG_TEST(aLog, aLogLevel)(__builtin_expect(!!(mozilla::detail::log_test(aLog, aLogLevel )), 0))) { |
| 81 | MOZ_LOG(aLog, aLogLevel, ("%p: %s", aTextEditor, aStr))do { const ::mozilla::LogModule* moz_real_module = aLog; if ( (__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , aLogLevel)), 0))) { mozilla::detail::log_print(moz_real_module , aLogLevel, "%p: %s", aTextEditor, aStr); } } while (0); |
| 82 | } else { |
| 83 | NS_WARNING(aStr)NS_DebugBreak(NS_DEBUG_WARNING, aStr, nullptr, "./../../../editor/libeditor/TextEditor.cpp" , 83); |
| 84 | } |
| 85 | #else |
| 86 | MOZ_LOG(aLog, aLogLevel, ("%p: %s", aTextEditor, aStr))do { const ::mozilla::LogModule* moz_real_module = aLog; if ( (__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , aLogLevel)), 0))) { mozilla::detail::log_print(moz_real_module , aLogLevel, "%p: %s", aTextEditor, aStr); } } while (0); |
| 87 | #endif |
| 88 | } |
| 89 | |
| 90 | using namespace dom; |
| 91 | |
| 92 | template EditorDOMPoint TextEditor::FindBetterInsertionPoint( |
| 93 | const EditorDOMPoint& aPoint) const; |
| 94 | template EditorRawDOMPoint TextEditor::FindBetterInsertionPoint( |
| 95 | const EditorRawDOMPoint& aPoint) const; |
| 96 | |
| 97 | TextEditor::TextEditor() : EditorBase(EditorBase::EditorType::Text) { |
| 98 | // printf("Size of TextEditor: %zu\n", sizeof(TextEditor)); |
| 99 | static_assert( |
| 100 | sizeof(TextEditor) <= 512, |
| 101 | "TextEditor instance should be allocatable in the quantum class bins"); |
| 102 | MOZ_LOG(gTextEditorLog, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: New instance is created", this); } } while (0) |
| 103 | ("%p: New instance is created", this))do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: New instance is created", this); } } while (0); |
| 104 | } |
| 105 | |
| 106 | TextEditor::~TextEditor() { |
| 107 | // Remove event listeners. Note that if we had an HTML editor, |
| 108 | // it installed its own instead of these |
| 109 | RemoveEventListeners(); |
| 110 | |
| 111 | MOZ_LOG(gTextEditorLog, LogLevel::Info, ("%p: Deleted", this))do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: Deleted", this); } } while (0); |
| 112 | } |
| 113 | |
| 114 | NS_IMPL_CYCLE_COLLECTION_CLASS(TextEditor)TextEditor::cycleCollection TextEditor::_cycleCollectorGlobal ; |
| 115 | |
| 116 | NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TextEditor, EditorBase)void TextEditor::cycleCollection::Unlink(void* p) { TextEditor * tmp = DowncastCCParticipant<TextEditor>(p); nsISupports * s = static_cast<nsISupports*>(p); EditorBase::cycleCollection ::Unlink(s); |
| 117 | if (tmp->mPasswordMaskData) { |
| 118 | tmp->mPasswordMaskData->CancelTimer(PasswordMaskData::ReleaseTimer::No); |
| 119 | NS_IMPL_CYCLE_COLLECTION_UNLINK(mPasswordMaskData->mTimer)ImplCycleCollectionUnlink(tmp->mPasswordMaskData->mTimer ); |
| 120 | } |
| 121 | NS_IMPL_CYCLE_COLLECTION_UNLINK_END(void)tmp; } |
| 122 | |
| 123 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TextEditor, EditorBase)nsresult TextEditor::cycleCollection::TraverseNative( void* p , nsCycleCollectionTraversalCallback& cb) { TextEditor* tmp = DowncastCCParticipant<TextEditor>(p); nsISupports* s = static_cast<nsISupports*>(p); if (EditorBase::cycleCollection ::TraverseNative(s, cb) == NS_SUCCESS_INTERRUPTED_TRAVERSE) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } |
| 124 | if (tmp->mPasswordMaskData) { |
| 125 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPasswordMaskData->mTimer)ImplCycleCollectionTraverse(cb, tmp->mPasswordMaskData-> mTimer, "mPasswordMaskData->mTimer", 0); |
| 126 | } |
| 127 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END(void)tmp; return NS_OK; } |
| 128 | |
| 129 | NS_IMPL_ADDREF_INHERITED(TextEditor, EditorBase)MozExternalRefCountType TextEditor::AddRef(void) { static_assert (!std::is_destructible_v<TextEditor>, "Reference-counted class " "TextEditor" " should not have a public destructor. " "Make this class's destructor non-public" ); nsrefcnt r = EditorBase::AddRef(); if constexpr (::mozilla ::detail::ShouldLogInheritedRefcnt<TextEditor>) { NS_LogAddRef ((this), (r), ("TextEditor"), (uint32_t)(sizeof(*this))); } return r; } |
| 130 | NS_IMPL_RELEASE_INHERITED(TextEditor, EditorBase)MozExternalRefCountType TextEditor::Release(void) { nsrefcnt r = EditorBase::Release(); if constexpr (::mozilla::detail::ShouldLogInheritedRefcnt <TextEditor>) { NS_LogRelease((this), (r), ("TextEditor" )); } return r; } |
| 131 | |
| 132 | NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TextEditor)nsresult TextEditor::QueryInterface(const nsIID& aIID, void ** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak( NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!" , "aInstancePtr", "./../../../editor/libeditor/TextEditor.cpp" , 132); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface ; if (TopThreeWordsEquals( aIID, (nsXPCOMCycleCollectionParticipant ::kIID), (nsCycleCollectionISupports::kIID)) && (LowWordEquals (aIID, (nsXPCOMCycleCollectionParticipant::kIID)) || LowWordEquals (aIID, (nsCycleCollectionISupports::kIID)))) { if (LowWordEquals (aIID, (nsXPCOMCycleCollectionParticipant::kIID))) { *aInstancePtr = TextEditor::cycleCollection::GetParticipant(); return NS_OK ; } if (LowWordEquals(aIID, (nsCycleCollectionISupports::kIID ))) { *aInstancePtr = TextEditor::cycleCollection::Upcast(this ); return NS_OK; } foundInterface = nullptr; } else |
| 133 | NS_INTERFACE_MAP_ENTRY(nsITimerCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsITimerCallback>)) foundInterface = static_cast<nsITimerCallback*>(this); else |
| 134 | NS_INTERFACE_MAP_ENTRY(nsINamed)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t <decltype(*this)>, nsINamed>)) foundInterface = static_cast <nsINamed*>(this); else |
| 135 | NS_INTERFACE_MAP_END_INHERITING(EditorBase)foundInterface = 0; nsresult status; if (!foundInterface) status = EditorBase::QueryInterface(aIID, (void**)&foundInterface ); else { (foundInterface)->AddRef(); status = NS_OK; } *aInstancePtr = foundInterface; return status; } |
| 136 | |
| 137 | NS_IMETHODIMPnsresult TextEditor::EndOfDocument() { |
| 138 | AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing); |
| 139 | if (NS_WARN_IF(!editActionData.CanHandle())NS_warn_if_impl(!editActionData.CanHandle(), "!editActionData.CanHandle()" , "./../../../editor/libeditor/TextEditor.cpp", 139)) { |
| 140 | return NS_ERROR_NOT_INITIALIZED; |
| 141 | } |
| 142 | nsresult rv = CollapseSelectionToEndOfTextNode(); |
| 143 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::CollapseSelectionToEndOfTextNode() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 144); } } while (false) |
| 144 | "TextEditor::CollapseSelectionToEndOfTextNode() failed")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::CollapseSelectionToEndOfTextNode() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 144); } } while (false); |
| 145 | // This is low level API for embedders and chrome script so that we can return |
| 146 | // raw error code here. |
| 147 | return rv; |
| 148 | } |
| 149 | |
| 150 | nsresult TextEditor::CollapseSelectionToEndOfTextNode() { |
| 151 | MOZ_ASSERT(IsEditActionDataAvailable())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsEditActionDataAvailable())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsEditActionDataAvailable()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsEditActionDataAvailable()" , "./../../../editor/libeditor/TextEditor.cpp", 151); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "IsEditActionDataAvailable()" ")"); do { MOZ_CrashSequence (__null, 151); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
| 152 | |
| 153 | Element* anonymousDivElement = GetRoot(); |
| 154 | if (NS_WARN_IF(!anonymousDivElement)NS_warn_if_impl(!anonymousDivElement, "!anonymousDivElement", "./../../../editor/libeditor/TextEditor.cpp", 154)) { |
| 155 | return NS_ERROR_NULL_POINTER; |
| 156 | } |
| 157 | |
| 158 | RefPtr<Text> textNode = |
| 159 | Text::FromNodeOrNull(anonymousDivElement->GetFirstChild()); |
| 160 | MOZ_ASSERT(textNode)do { static_assert( mozilla::detail::AssertionConditionType< decltype(textNode)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(textNode))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("textNode", "./../../../editor/libeditor/TextEditor.cpp" , 160); AnnotateMozCrashReason("MOZ_ASSERT" "(" "textNode" ")" ); do { MOZ_CrashSequence(__null, 160); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
| 161 | nsresult rv = CollapseSelectionToEndOf(*textNode); |
| 162 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::CollapseSelectionToEndOf() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 163); } } while (false) |
| 163 | "EditorBase::CollapseSelectionToEndOf() failed")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::CollapseSelectionToEndOf() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 163); } } while (false); |
| 164 | return rv; |
| 165 | } |
| 166 | |
| 167 | nsresult TextEditor::Init(Document& aDocument, Element& aAnonymousDivElement, |
| 168 | nsISelectionController& aSelectionController, |
| 169 | uint32_t aFlags, |
| 170 | UniquePtr<PasswordMaskData>&& aPasswordMaskData) { |
| 171 | MOZ_ASSERT(!mInitSucceeded,do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mInitSucceeded)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mInitSucceeded))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mInitSucceeded" " (" "TextEditor::Init() called again without calling PreDestroy()?" ")", "./../../../editor/libeditor/TextEditor.cpp", 172); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!mInitSucceeded" ") (" "TextEditor::Init() called again without calling PreDestroy()?" ")"); do { MOZ_CrashSequence(__null, 172); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
| 172 | "TextEditor::Init() called again without calling PreDestroy()?")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mInitSucceeded)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mInitSucceeded))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mInitSucceeded" " (" "TextEditor::Init() called again without calling PreDestroy()?" ")", "./../../../editor/libeditor/TextEditor.cpp", 172); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!mInitSucceeded" ") (" "TextEditor::Init() called again without calling PreDestroy()?" ")"); do { MOZ_CrashSequence(__null, 172); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
| 173 | MOZ_ASSERT(!(aFlags & nsIEditor::eEditorPasswordMask) == !aPasswordMaskData)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!(aFlags & nsIEditor::eEditorPasswordMask) == !aPasswordMaskData )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(!(aFlags & nsIEditor::eEditorPasswordMask) == !aPasswordMaskData ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "!(aFlags & nsIEditor::eEditorPasswordMask) == !aPasswordMaskData" , "./../../../editor/libeditor/TextEditor.cpp", 173); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "!(aFlags & nsIEditor::eEditorPasswordMask) == !aPasswordMaskData" ")"); do { MOZ_CrashSequence(__null, 173); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
| 174 | |
| 175 | MOZ_LOG(gTextEditorLog, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: Init(aDocument=%p, aAnonymousDivElement=%s, " "aSelectionController=%p, aPasswordMaskData=%p)", this, & aDocument, ToString(RefPtr{&aAnonymousDivElement}).c_str( ), &aSelectionController, aPasswordMaskData.get()); } } while (0) |
| 176 | ("%p: Init(aDocument=%p, aAnonymousDivElement=%s, "do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: Init(aDocument=%p, aAnonymousDivElement=%s, " "aSelectionController=%p, aPasswordMaskData=%p)", this, & aDocument, ToString(RefPtr{&aAnonymousDivElement}).c_str( ), &aSelectionController, aPasswordMaskData.get()); } } while (0) |
| 177 | "aSelectionController=%p, aPasswordMaskData=%p)",do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: Init(aDocument=%p, aAnonymousDivElement=%s, " "aSelectionController=%p, aPasswordMaskData=%p)", this, & aDocument, ToString(RefPtr{&aAnonymousDivElement}).c_str( ), &aSelectionController, aPasswordMaskData.get()); } } while (0) |
| 178 | this, &aDocument, ToString(RefPtr{&aAnonymousDivElement}).c_str(),do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: Init(aDocument=%p, aAnonymousDivElement=%s, " "aSelectionController=%p, aPasswordMaskData=%p)", this, & aDocument, ToString(RefPtr{&aAnonymousDivElement}).c_str( ), &aSelectionController, aPasswordMaskData.get()); } } while (0) |
| 179 | &aSelectionController, aPasswordMaskData.get()))do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: Init(aDocument=%p, aAnonymousDivElement=%s, " "aSelectionController=%p, aPasswordMaskData=%p)", this, & aDocument, ToString(RefPtr{&aAnonymousDivElement}).c_str( ), &aSelectionController, aPasswordMaskData.get()); } } while (0); |
| 180 | |
| 181 | mPasswordMaskData = std::move(aPasswordMaskData); |
| 182 | |
| 183 | // Init the base editor |
| 184 | nsresult rv = InitInternal(aDocument, &aAnonymousDivElement, |
| 185 | aSelectionController, aFlags); |
| 186 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 187 | LogOrWarn(this, gTextEditorLog, LogLevel::Error, |
| 188 | "EditorBase::InitInternal() failed"); |
| 189 | return rv; |
| 190 | } |
| 191 | |
| 192 | AutoEditActionDataSetter editActionData(*this, EditAction::eInitializing); |
| 193 | if (MOZ_UNLIKELY(!editActionData.CanHandle())(__builtin_expect(!!(!editActionData.CanHandle()), 0))) { |
| 194 | LogOrWarn(this, gTextEditorLog, LogLevel::Error, |
| 195 | "AutoEditActionDataSetter::CanHandle() failed"); |
| 196 | return NS_ERROR_FAILURE; |
| 197 | } |
| 198 | |
| 199 | // We set the initialized state here rather than at the end of the function, |
| 200 | // since InitEditorContentAndSelection() can perform some transactions |
| 201 | // and can warn if mInitSucceeded is still false. |
| 202 | MOZ_ASSERT(!mInitSucceeded, "TextEditor::Init() shouldn't be nested")do { static_assert( mozilla::detail::AssertionConditionType< decltype(!mInitSucceeded)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!mInitSucceeded))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mInitSucceeded" " (" "TextEditor::Init() shouldn't be nested" ")", "./../../../editor/libeditor/TextEditor.cpp" , 202); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mInitSucceeded" ") (" "TextEditor::Init() shouldn't be nested" ")"); do { MOZ_CrashSequence (__null, 202); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
| 203 | mInitSucceeded = true; |
| 204 | editActionData.OnEditorInitialized(); |
| 205 | |
| 206 | rv = InitEditorContentAndSelection(); |
| 207 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 208 | LogOrWarn(this, gTextEditorLog, LogLevel::Error, |
| 209 | "TextEditor::InitEditorContentAndSelection() failed"); |
| 210 | // XXX Shouldn't we expose `NS_ERROR_EDITOR_DESTROYED` even though this |
| 211 | // is a public method? |
| 212 | mInitSucceeded = false; |
| 213 | editActionData.OnEditorDestroy(); |
| 214 | return EditorBase::ToGenericNSResult(rv); |
| 215 | } |
| 216 | |
| 217 | // Throw away the old transaction manager if this is not the first time that |
| 218 | // we're initializing the editor. |
| 219 | ClearUndoRedo(); |
| 220 | EnableUndoRedo(); |
| 221 | return NS_OK; |
| 222 | } |
| 223 | |
| 224 | nsresult TextEditor::InitEditorContentAndSelection() { |
| 225 | MOZ_ASSERT(IsEditActionDataAvailable())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsEditActionDataAvailable())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsEditActionDataAvailable()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsEditActionDataAvailable()" , "./../../../editor/libeditor/TextEditor.cpp", 225); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "IsEditActionDataAvailable()" ")"); do { MOZ_CrashSequence (__null, 225); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
| 226 | |
| 227 | MOZ_TRY(EnsureEmptyTextFirstChild())__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (EnsureEmptyTextFirstChild()); if ((__builtin_expect(!!(mozTryVarTempResult .isErr()), 0))) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult.unwrap(); }); |
| 228 | |
| 229 | // If the selection hasn't been set up yet, set it up collapsed to the end of |
| 230 | // our editable content. |
| 231 | if (!SelectionRef().RangeCount()) { |
| 232 | nsresult rv = CollapseSelectionToEndOfTextNode(); |
| 233 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 234 | LogOrWarn(this, gTextEditorLog, LogLevel::Error, |
| 235 | "EditorBase::CollapseSelectionToEndOfTextNode() failed"); |
| 236 | return rv; |
| 237 | } |
| 238 | } |
| 239 | |
| 240 | if (!IsSingleLineEditor()) { |
| 241 | nsresult rv = EnsurePaddingBRElementInMultilineEditor(); |
| 242 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 243 | LogOrWarn(this, gTextEditorLog, LogLevel::Error, |
| 244 | "EditorBase::EnsurePaddingBRElementInMultilineEditor() failed"); |
| 245 | return rv; |
| 246 | } |
| 247 | } |
| 248 | |
| 249 | return NS_OK; |
| 250 | } |
| 251 | |
| 252 | nsresult TextEditor::PostCreate() { |
| 253 | MOZ_LOG(gTextEditorLog, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: PostCreate(), mDidPostCreate=%s", this , TrueOrFalse(mDidPostCreate)); } } while (0) |
| 254 | ("%p: PostCreate(), mDidPostCreate=%s", this,do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: PostCreate(), mDidPostCreate=%s", this , TrueOrFalse(mDidPostCreate)); } } while (0) |
| 255 | TrueOrFalse(mDidPostCreate)))do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: PostCreate(), mDidPostCreate=%s", this , TrueOrFalse(mDidPostCreate)); } } while (0); |
| 256 | |
| 257 | AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing); |
| 258 | if (MOZ_UNLIKELY(!editActionData.CanHandle())(__builtin_expect(!!(!editActionData.CanHandle()), 0))) { |
| 259 | LogOrWarn(this, gTextEditorLog, LogLevel::Error, |
| 260 | "AutoEditActionDataSetter::CanHandle() failed"); |
| 261 | return NS_ERROR_NOT_INITIALIZED; |
| 262 | } |
| 263 | |
| 264 | nsresult rv = PostCreateInternal(); |
| 265 | |
| 266 | // Restore unmasked range if there is. |
| 267 | if (IsPasswordEditor() && !IsAllMasked()) { |
| 268 | DebugOnly<nsresult> rvIgnored = |
| 269 | SetUnmaskRangeAndNotify(UnmaskedStart(), UnmaskedLength()); |
| 270 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetUnmaskRangeAndNotify() failed to " "restore unmasked range, but ignored", "NS_SUCCEEDED(rvIgnored)" , "./../../../editor/libeditor/TextEditor.cpp", 272); } } while (false) |
| 271 | "TextEditor::SetUnmaskRangeAndNotify() failed to "do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetUnmaskRangeAndNotify() failed to " "restore unmasked range, but ignored", "NS_SUCCEEDED(rvIgnored)" , "./../../../editor/libeditor/TextEditor.cpp", 272); } } while (false) |
| 272 | "restore unmasked range, but ignored")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetUnmaskRangeAndNotify() failed to " "restore unmasked range, but ignored", "NS_SUCCEEDED(rvIgnored)" , "./../../../editor/libeditor/TextEditor.cpp", 272); } } while (false); |
| 273 | } |
| 274 | |
| 275 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 276 | LogOrWarn(this, gTextEditorLog, LogLevel::Error, |
| 277 | "EditorBase::PostCreateInternal() failed"); |
| 278 | return rv; |
| 279 | } |
| 280 | |
| 281 | return NS_OK; |
| 282 | } |
| 283 | |
| 284 | UniquePtr<PasswordMaskData> TextEditor::PreDestroy() { |
| 285 | MOZ_LOG(gTextEditorLog, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: PreDestroy() mDidPreDestroy=%s", this, TrueOrFalse(mDidPreDestroy)); } } while (0) |
| 286 | ("%p: PreDestroy() mDidPreDestroy=%s", this,do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: PreDestroy() mDidPreDestroy=%s", this, TrueOrFalse(mDidPreDestroy)); } } while (0) |
| 287 | TrueOrFalse(mDidPreDestroy)))do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: PreDestroy() mDidPreDestroy=%s", this, TrueOrFalse(mDidPreDestroy)); } } while (0); |
| 288 | |
| 289 | if (mDidPreDestroy) { |
| 290 | return nullptr; |
| 291 | } |
| 292 | |
| 293 | UniquePtr<PasswordMaskData> passwordMaskData = std::move(mPasswordMaskData); |
| 294 | if (passwordMaskData) { |
| 295 | // Disable auto-masking timer since nobody can catch the notification |
| 296 | // from the timer and canceling the unmasking. |
| 297 | passwordMaskData->CancelTimer(PasswordMaskData::ReleaseTimer::Yes); |
| 298 | // Similary, keeping preventing echoing password temporarily across |
| 299 | // TextEditor instances is hard. So, we should forget it. |
| 300 | passwordMaskData->mEchoingPasswordPrevented = false; |
| 301 | } |
| 302 | |
| 303 | PreDestroyInternal(); |
| 304 | |
| 305 | return passwordMaskData; |
| 306 | } |
| 307 | |
| 308 | Result<widget::IMEState, nsresult> TextEditor::GetPreferredIMEState() const { |
| 309 | using IMEState = widget::IMEState; |
| 310 | using IMEEnabled = widget::IMEEnabled; |
| 311 | |
| 312 | if (IsReadonly()) { |
| 313 | return IMEState{IMEEnabled::Disabled, IMEState::DONT_CHANGE_OPEN_STATE}; |
| 314 | } |
| 315 | |
| 316 | Element* const textControlElement = GetExposedRoot(); |
| 317 | if (NS_WARN_IF(!textControlElement)NS_warn_if_impl(!textControlElement, "!textControlElement", "./../../../editor/libeditor/TextEditor.cpp" , 317)) { |
| 318 | return Err(NS_ERROR_FAILURE); |
| 319 | } |
| 320 | MOZ_ASSERT(textControlElement->IsTextControlElement())do { static_assert( mozilla::detail::AssertionConditionType< decltype(textControlElement->IsTextControlElement())>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(textControlElement->IsTextControlElement()))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("textControlElement->IsTextControlElement()" , "./../../../editor/libeditor/TextEditor.cpp", 320); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "textControlElement->IsTextControlElement()" ")"); do { MOZ_CrashSequence(__null, 320); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
| 321 | |
| 322 | nsIFrame* const textControlFrame = textControlElement->GetPrimaryFrame(); |
| 323 | if (NS_WARN_IF(!textControlFrame)NS_warn_if_impl(!textControlFrame, "!textControlFrame", "./../../../editor/libeditor/TextEditor.cpp" , 323)) { |
| 324 | return Err(NS_ERROR_FAILURE); |
| 325 | } |
| 326 | |
| 327 | switch (textControlFrame->StyleUIReset()->mIMEMode) { |
| 328 | case StyleImeMode::Auto: |
| 329 | default: |
| 330 | return IMEState{ |
| 331 | IsPasswordEditor() ? IMEEnabled::Password : IMEEnabled::Enabled, |
| 332 | IMEState::DONT_CHANGE_OPEN_STATE}; |
| 333 | case StyleImeMode::Disabled: |
| 334 | // we should use password state for |ime-mode: disabled;|. |
| 335 | return IMEState{IMEEnabled::Password, IMEState::DONT_CHANGE_OPEN_STATE}; |
| 336 | case StyleImeMode::Active: |
| 337 | return IMEState{IMEEnabled::Enabled, IMEState::OPEN}; |
| 338 | case StyleImeMode::Inactive: |
| 339 | return IMEState{IMEEnabled::Enabled, IMEState::CLOSED}; |
| 340 | case StyleImeMode::Normal: |
| 341 | return IMEState{IMEEnabled::Enabled, IMEState::DONT_CHANGE_OPEN_STATE}; |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | nsresult TextEditor::HandleKeyPressEvent(WidgetKeyboardEvent* aKeyboardEvent) { |
| 346 | // NOTE: When you change this method, you should also change: |
| 347 | // * editor/libeditor/tests/test_texteditor_keyevent_handling.html |
| 348 | // * editor/libeditor/tests/test_htmleditor_keyevent_handling.html |
| 349 | // |
| 350 | // And also when you add new key handling, you need to change the subclass's |
| 351 | // HandleKeyPressEvent()'s switch statement. |
| 352 | |
| 353 | if (NS_WARN_IF(!aKeyboardEvent)NS_warn_if_impl(!aKeyboardEvent, "!aKeyboardEvent", "./../../../editor/libeditor/TextEditor.cpp" , 353)) { |
| 354 | return NS_ERROR_UNEXPECTED; |
| 355 | } |
| 356 | |
| 357 | if (IsReadonly()) { |
| 358 | HandleKeyPressEventInReadOnlyMode(*aKeyboardEvent); |
| 359 | return NS_OK; |
| 360 | } |
| 361 | |
| 362 | MOZ_ASSERT(aKeyboardEvent->mMessage == eKeyPress,do { static_assert( mozilla::detail::AssertionConditionType< decltype(aKeyboardEvent->mMessage == eKeyPress)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aKeyboardEvent->mMessage == eKeyPress))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aKeyboardEvent->mMessage == eKeyPress" " (" "HandleKeyPressEvent gets non-keypress event" ")", "./../../../editor/libeditor/TextEditor.cpp" , 363); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKeyboardEvent->mMessage == eKeyPress" ") (" "HandleKeyPressEvent gets non-keypress event" ")"); do { MOZ_CrashSequence(__null, 363); __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
| 363 | "HandleKeyPressEvent gets non-keypress event")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aKeyboardEvent->mMessage == eKeyPress)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aKeyboardEvent->mMessage == eKeyPress))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aKeyboardEvent->mMessage == eKeyPress" " (" "HandleKeyPressEvent gets non-keypress event" ")", "./../../../editor/libeditor/TextEditor.cpp" , 363); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKeyboardEvent->mMessage == eKeyPress" ") (" "HandleKeyPressEvent gets non-keypress event" ")"); do { MOZ_CrashSequence(__null, 363); __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
| 364 | |
| 365 | switch (aKeyboardEvent->mKeyCode) { |
| 366 | case NS_VK_META: |
| 367 | case NS_VK_WIN: |
| 368 | case NS_VK_SHIFT: |
| 369 | case NS_VK_CONTROL: |
| 370 | case NS_VK_ALT: |
| 371 | // FYI: This shouldn't occur since modifier key shouldn't cause eKeyPress |
| 372 | // event. |
| 373 | aKeyboardEvent->PreventDefault(); |
| 374 | return NS_OK; |
| 375 | |
| 376 | case NS_VK_BACK: |
| 377 | case NS_VK_DELETE: |
| 378 | case NS_VK_TAB: { |
| 379 | nsresult rv = EditorBase::HandleKeyPressEvent(aKeyboardEvent); |
| 380 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::HandleKeyPressEvent() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 381); } } while (false) |
| 381 | "EditorBase::HandleKeyPressEvent() failed")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::HandleKeyPressEvent() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 381); } } while (false); |
| 382 | return rv; |
| 383 | } |
| 384 | case NS_VK_RETURN: { |
| 385 | if (!aKeyboardEvent->IsInputtingLineBreak()) { |
| 386 | return NS_OK; |
| 387 | } |
| 388 | if (!IsSingleLineEditor()) { |
| 389 | aKeyboardEvent->PreventDefault(); |
| 390 | } |
| 391 | // We need to dispatch "beforeinput" event at least even if we're a |
| 392 | // single line text editor. |
| 393 | nsresult rv = InsertLineBreakAsAction(); |
| 394 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::InsertLineBreakAsAction() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 395); } } while (false) |
| 395 | "TextEditor::InsertLineBreakAsAction() failed")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::InsertLineBreakAsAction() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 395); } } while (false); |
| 396 | return rv; |
| 397 | } |
| 398 | } |
| 399 | |
| 400 | if (!aKeyboardEvent->IsInputtingText()) { |
| 401 | // we don't PreventDefault() here or keybindings like control-x won't work |
| 402 | return NS_OK; |
| 403 | } |
| 404 | aKeyboardEvent->PreventDefault(); |
| 405 | // If we dispatch 2 keypress events for a surrogate pair and we set only |
| 406 | // first `.key` value to the surrogate pair, the preceding one has it and the |
| 407 | // other has empty string. In this case, we should handle only the first one |
| 408 | // with the key value. |
| 409 | if (!StaticPrefs::dom_event_keypress_dispatch_once_per_surrogate_pair() && |
| 410 | !StaticPrefs::dom_event_keypress_key_allow_lone_surrogate() && |
| 411 | aKeyboardEvent->mKeyValue.IsEmpty() && |
| 412 | mozilla::IsSurrogate(aKeyboardEvent->mCharCode)) { |
| 413 | return NS_OK; |
| 414 | } |
| 415 | // Our widget shouldn't set `\r` to `mKeyValue`, but it may be synthesized |
| 416 | // keyboard event and its value may be `\r`. In such case, we should treat |
| 417 | // it as `\n` for the backward compatibility because we stopped converting |
| 418 | // `\r` and `\r\n` to `\n` at getting `HTMLInputElement.value` and |
| 419 | // `HTMLTextAreaElement.value` for the performance (i.e., we don't need to |
| 420 | // take care in `HTMLEditor`). |
| 421 | nsAutoString str(aKeyboardEvent->mKeyValue); |
| 422 | if (str.IsEmpty()) { |
| 423 | MOZ_ASSERT(aKeyboardEvent->mCharCode <= 0xFFFF,do { static_assert( mozilla::detail::AssertionConditionType< decltype(aKeyboardEvent->mCharCode <= 0xFFFF)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aKeyboardEvent->mCharCode <= 0xFFFF))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aKeyboardEvent->mCharCode <= 0xFFFF" " (" "Non-BMP character needs special handling" ")", "./../../../editor/libeditor/TextEditor.cpp" , 424); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKeyboardEvent->mCharCode <= 0xFFFF" ") (" "Non-BMP character needs special handling" ")"); do { MOZ_CrashSequence (__null, 424); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false) |
| 424 | "Non-BMP character needs special handling")do { static_assert( mozilla::detail::AssertionConditionType< decltype(aKeyboardEvent->mCharCode <= 0xFFFF)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aKeyboardEvent->mCharCode <= 0xFFFF))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aKeyboardEvent->mCharCode <= 0xFFFF" " (" "Non-BMP character needs special handling" ")", "./../../../editor/libeditor/TextEditor.cpp" , 424); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKeyboardEvent->mCharCode <= 0xFFFF" ") (" "Non-BMP character needs special handling" ")"); do { MOZ_CrashSequence (__null, 424); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
| 425 | str.Assign(aKeyboardEvent->mCharCode == nsCRT::CR |
| 426 | ? static_cast<char16_t>(nsCRT::LF) |
| 427 | : static_cast<char16_t>(aKeyboardEvent->mCharCode)); |
| 428 | } else { |
| 429 | MOZ_ASSERT(str.Find(u"\r\n"_ns) == kNotFound,do { static_assert( mozilla::detail::AssertionConditionType< decltype(str.Find(u"\r\n"_ns) == kNotFound)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(str.Find(u"\r\n"_ns) == kNotFound ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "str.Find(u\"\\r\\n\"_ns) == kNotFound" " (" "This assumes that typed text does not include CRLF" ")", "./../../../editor/libeditor/TextEditor.cpp", 430); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "str.Find(u\"\\r\\n\"_ns) == kNotFound" ") (" "This assumes that typed text does not include CRLF" ")"); do { MOZ_CrashSequence(__null, 430); __attribute__((nomerge)) :: abort(); } while (false); } } while (false) |
| 430 | "This assumes that typed text does not include CRLF")do { static_assert( mozilla::detail::AssertionConditionType< decltype(str.Find(u"\r\n"_ns) == kNotFound)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(str.Find(u"\r\n"_ns) == kNotFound ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "str.Find(u\"\\r\\n\"_ns) == kNotFound" " (" "This assumes that typed text does not include CRLF" ")", "./../../../editor/libeditor/TextEditor.cpp", 430); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "str.Find(u\"\\r\\n\"_ns) == kNotFound" ") (" "This assumes that typed text does not include CRLF" ")"); do { MOZ_CrashSequence(__null, 430); __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
| 431 | str.ReplaceChar('\r', '\n'); |
| 432 | } |
| 433 | nsresult rv = OnInputText(str); |
| 434 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "EditorBase::OnInputText() failed")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::OnInputText() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 434); } } while (false); |
| 435 | return rv; |
| 436 | } |
| 437 | |
| 438 | NS_IMETHODIMPnsresult TextEditor::InsertLineBreak() { |
| 439 | AutoEditActionDataSetter editActionData(*this, EditAction::eInsertLineBreak); |
| 440 | nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent(); |
| 441 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 442 | NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,do { if (!(rv == NS_ERROR_EDITOR_ACTION_CANCELED)) { NS_DebugBreak (NS_DEBUG_WARNING, "CanHandleAndMaybeDispatchBeforeInputEvent() failed" , "rv == NS_ERROR_EDITOR_ACTION_CANCELED", "./../../../editor/libeditor/TextEditor.cpp" , 443); } } while (false) |
| 443 | "CanHandleAndMaybeDispatchBeforeInputEvent() failed")do { if (!(rv == NS_ERROR_EDITOR_ACTION_CANCELED)) { NS_DebugBreak (NS_DEBUG_WARNING, "CanHandleAndMaybeDispatchBeforeInputEvent() failed" , "rv == NS_ERROR_EDITOR_ACTION_CANCELED", "./../../../editor/libeditor/TextEditor.cpp" , 443); } } while (false); |
| 444 | return EditorBase::ToGenericNSResult(rv); |
| 445 | } |
| 446 | |
| 447 | if (NS_WARN_IF(IsSingleLineEditor())NS_warn_if_impl(IsSingleLineEditor(), "IsSingleLineEditor()", "./../../../editor/libeditor/TextEditor.cpp", 447)) { |
| 448 | return NS_ERROR_FAILURE; |
| 449 | } |
| 450 | |
| 451 | AutoPlaceholderBatch treatAsOneTransaction( |
| 452 | *this, ScrollSelectionIntoView::Yes, __FUNCTION__); |
| 453 | rv = InsertLineBreakAsSubAction(); |
| 454 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::InsertLineBreakAsSubAction() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 455); } } while (false) |
| 455 | "TextEditor::InsertLineBreakAsSubAction() failed")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::InsertLineBreakAsSubAction() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 455); } } while (false); |
| 456 | return EditorBase::ToGenericNSResult(rv); |
| 457 | } |
| 458 | |
| 459 | nsresult TextEditor::ComputeTextValue(nsAString& aString) const { |
| 460 | // This is a public method so that anytime this may be called, e.g., before |
| 461 | // initialized or after destroyed. However, GetTextNode() is an internal API |
| 462 | // for friend classes and internal use. Therefore, it asserts the conditions |
| 463 | // whether the anonymous subtree is available. Therefore, this method needs |
| 464 | // to get the Text with the anonymous <div>. |
| 465 | const Element* const anonymousDivElement = GetRoot(); |
| 466 | if (MOZ_UNLIKELY(!anonymousDivElement)(__builtin_expect(!!(!anonymousDivElement), 0))) { |
| 467 | // If we're temporarily destroyed while we're handling something, we can get |
| 468 | // the value from the cached text node which was maybe modified by us. This |
| 469 | // helps TextControlState and TextInputListener to notify the text control |
| 470 | // element of value changes, etc, at UnbindFromFrame(). |
| 471 | const Text* const cachedTextNode = GetCachedTextNode(); |
| 472 | if (NS_WARN_IF(!cachedTextNode)NS_warn_if_impl(!cachedTextNode, "!cachedTextNode", "./../../../editor/libeditor/TextEditor.cpp" , 472)) { |
| 473 | return NS_ERROR_NOT_INITIALIZED; |
| 474 | } |
| 475 | cachedTextNode->GetData(aString); |
| 476 | return NS_OK; |
| 477 | } |
| 478 | |
| 479 | const auto* const text = |
| 480 | Text::FromNodeOrNull(anonymousDivElement->GetFirstChild()); |
| 481 | if (MOZ_UNLIKELY(!text)(__builtin_expect(!!(!text), 0))) { |
| 482 | MOZ_ASSERT_UNREACHABLE("how?")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: " "how?" ")", "./../../../editor/libeditor/TextEditor.cpp", 482 ); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "how?" ")"); do { MOZ_CrashSequence(__null, 482); __attribute__ ((nomerge)) ::abort(); } while (false); } } while (false); |
| 483 | return NS_ERROR_UNEXPECTED; |
| 484 | } |
| 485 | |
| 486 | text->GetData(aString); |
| 487 | return NS_OK; |
| 488 | } |
| 489 | |
| 490 | nsresult TextEditor::InsertLineBreakAsAction(nsIPrincipal* aPrincipal) { |
| 491 | AutoEditActionDataSetter editActionData(*this, EditAction::eInsertLineBreak, |
| 492 | aPrincipal); |
| 493 | nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent(); |
| 494 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 495 | NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,do { if (!(rv == NS_ERROR_EDITOR_ACTION_CANCELED)) { NS_DebugBreak (NS_DEBUG_WARNING, "CanHandleAndMaybeDispatchBeforeInputEvent() failed" , "rv == NS_ERROR_EDITOR_ACTION_CANCELED", "./../../../editor/libeditor/TextEditor.cpp" , 496); } } while (false) |
| 496 | "CanHandleAndMaybeDispatchBeforeInputEvent() failed")do { if (!(rv == NS_ERROR_EDITOR_ACTION_CANCELED)) { NS_DebugBreak (NS_DEBUG_WARNING, "CanHandleAndMaybeDispatchBeforeInputEvent() failed" , "rv == NS_ERROR_EDITOR_ACTION_CANCELED", "./../../../editor/libeditor/TextEditor.cpp" , 496); } } while (false); |
| 497 | return EditorBase::ToGenericNSResult(rv); |
| 498 | } |
| 499 | |
| 500 | if (IsSingleLineEditor()) { |
| 501 | return NS_OK; |
| 502 | } |
| 503 | |
| 504 | // XXX This may be called by execCommand() with "insertParagraph". |
| 505 | // In such case, naming the transaction "TypingTxnName" is odd. |
| 506 | AutoPlaceholderBatch treatAsOneTransaction(*this, *nsGkAtoms::TypingTxnName, |
| 507 | ScrollSelectionIntoView::Yes, |
| 508 | __FUNCTION__); |
| 509 | rv = InsertLineBreakAsSubAction(); |
| 510 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::InsertLineBreakAsSubAction() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 511); } } while (false) |
| 511 | "EditorBase::InsertLineBreakAsSubAction() failed")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::InsertLineBreakAsSubAction() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 511); } } while (false); |
| 512 | return EditorBase::ToGenericNSResult(rv); |
| 513 | } |
| 514 | |
| 515 | nsresult TextEditor::SetTextAsAction( |
| 516 | const nsAString& aString, |
| 517 | AllowBeforeInputEventCancelable aAllowBeforeInputEventCancelable, |
| 518 | nsIPrincipal* aPrincipal) { |
| 519 | MOZ_ASSERT(aString.FindChar(nsCRT::CR) == kNotFound)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aString.FindChar(nsCRT::CR) == kNotFound)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(aString.FindChar(nsCRT::CR) == kNotFound))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aString.FindChar(nsCRT::CR) == kNotFound" , "./../../../editor/libeditor/TextEditor.cpp", 519); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aString.FindChar(nsCRT::CR) == kNotFound" ")" ); do { MOZ_CrashSequence(__null, 519); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
| 520 | |
| 521 | AutoEditActionDataSetter editActionData(*this, EditAction::eSetText, |
| 522 | aPrincipal); |
| 523 | if (aAllowBeforeInputEventCancelable == AllowBeforeInputEventCancelable::No) { |
| 524 | editActionData.MakeBeforeInputEventNonCancelable(); |
| 525 | } |
| 526 | nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent(); |
| 527 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 528 | NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,do { if (!(rv == NS_ERROR_EDITOR_ACTION_CANCELED)) { NS_DebugBreak (NS_DEBUG_WARNING, "CanHandleAndMaybeDispatchBeforeInputEvent() failed" , "rv == NS_ERROR_EDITOR_ACTION_CANCELED", "./../../../editor/libeditor/TextEditor.cpp" , 529); } } while (false) |
| 529 | "CanHandleAndMaybeDispatchBeforeInputEvent() failed")do { if (!(rv == NS_ERROR_EDITOR_ACTION_CANCELED)) { NS_DebugBreak (NS_DEBUG_WARNING, "CanHandleAndMaybeDispatchBeforeInputEvent() failed" , "rv == NS_ERROR_EDITOR_ACTION_CANCELED", "./../../../editor/libeditor/TextEditor.cpp" , 529); } } while (false); |
| 530 | return EditorBase::ToGenericNSResult(rv); |
| 531 | } |
| 532 | |
| 533 | AutoPlaceholderBatch treatAsOneTransaction( |
| 534 | *this, ScrollSelectionIntoView::Yes, __FUNCTION__); |
| 535 | rv = SetTextAsSubAction(aString); |
| 536 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetTextAsSubAction() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 537); } } while (false) |
| 537 | "TextEditor::SetTextAsSubAction() failed")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetTextAsSubAction() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 537); } } while (false); |
| 538 | return EditorBase::ToGenericNSResult(rv); |
| 539 | } |
| 540 | |
| 541 | nsresult TextEditor::SetTextAsSubAction(const nsAString& aString) { |
| 542 | MOZ_ASSERT(IsEditActionDataAvailable())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsEditActionDataAvailable())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsEditActionDataAvailable()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsEditActionDataAvailable()" , "./../../../editor/libeditor/TextEditor.cpp", 542); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "IsEditActionDataAvailable()" ")"); do { MOZ_CrashSequence (__null, 542); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
| 543 | MOZ_ASSERT(mPlaceholderBatch)do { static_assert( mozilla::detail::AssertionConditionType< decltype(mPlaceholderBatch)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mPlaceholderBatch))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mPlaceholderBatch" , "./../../../editor/libeditor/TextEditor.cpp", 543); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "mPlaceholderBatch" ")"); do { MOZ_CrashSequence (__null, 543); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
| 544 | |
| 545 | if (NS_WARN_IF(!mInitSucceeded)NS_warn_if_impl(!mInitSucceeded, "!mInitSucceeded", "./../../../editor/libeditor/TextEditor.cpp" , 545)) { |
| 546 | return NS_ERROR_NOT_INITIALIZED; |
| 547 | } |
| 548 | |
| 549 | IgnoredErrorResult ignoredError; |
| 550 | AutoEditSubActionNotifier startToHandleEditSubAction( |
| 551 | *this, EditSubAction::eSetText, nsIEditor::eNext, ignoredError); |
| 552 | if (NS_WARN_IF(ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))NS_warn_if_impl(ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED ), "ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED)", "./../../../editor/libeditor/TextEditor.cpp" , 552)) { |
| 553 | return ignoredError.StealNSResult(); |
| 554 | } |
| 555 | NS_WARNING_ASSERTION(do { if (!(!ignoredError.Failed())) { NS_DebugBreak(NS_DEBUG_WARNING , "TextEditor::OnStartToHandleTopLevelEditSubAction() failed, but ignored" , "!ignoredError.Failed()", "./../../../editor/libeditor/TextEditor.cpp" , 557); } } while (false) |
| 556 | !ignoredError.Failed(),do { if (!(!ignoredError.Failed())) { NS_DebugBreak(NS_DEBUG_WARNING , "TextEditor::OnStartToHandleTopLevelEditSubAction() failed, but ignored" , "!ignoredError.Failed()", "./../../../editor/libeditor/TextEditor.cpp" , 557); } } while (false) |
| 557 | "TextEditor::OnStartToHandleTopLevelEditSubAction() failed, but ignored")do { if (!(!ignoredError.Failed())) { NS_DebugBreak(NS_DEBUG_WARNING , "TextEditor::OnStartToHandleTopLevelEditSubAction() failed, but ignored" , "!ignoredError.Failed()", "./../../../editor/libeditor/TextEditor.cpp" , 557); } } while (false); |
| 558 | |
| 559 | if (!IsIMEComposing() && !IsUndoRedoEnabled() && |
| 560 | GetEditAction() != EditAction::eReplaceText && mMaxTextLength < 0) { |
| 561 | Result<EditActionResult, nsresult> result = |
| 562 | SetTextWithoutTransaction(aString); |
| 563 | if (MOZ_UNLIKELY(result.isErr())(__builtin_expect(!!(result.isErr()), 0))) { |
| 564 | NS_WARNING("TextEditor::SetTextWithoutTransaction() failed")NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetTextWithoutTransaction() failed" , nullptr, "./../../../editor/libeditor/TextEditor.cpp", 564); |
| 565 | return result.unwrapErr(); |
| 566 | } |
| 567 | if (!result.inspect().Ignored()) { |
| 568 | return NS_OK; |
| 569 | } |
| 570 | } |
| 571 | |
| 572 | { |
| 573 | // Note that do not notify selectionchange caused by selecting all text |
| 574 | // because it's preparation of our delete implementation so web apps |
| 575 | // shouldn't receive such selectionchange before the first mutation. |
| 576 | AutoUpdateViewBatch preventSelectionChangeEvent(*this, __FUNCTION__); |
| 577 | |
| 578 | // XXX We should make ReplaceSelectionAsSubAction() take range. Then, |
| 579 | // we can saving the expensive cost of modifying `Selection` here. |
| 580 | if (NS_SUCCEEDED(SelectEntireDocument())((bool)(__builtin_expect(!!(!NS_FAILED_impl(SelectEntireDocument ())), 1)))) { |
| 581 | DebugOnly<nsresult> rvIgnored = ReplaceSelectionAsSubAction(aString); |
| 582 | NS_WARNING_ASSERTION(do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::ReplaceSelectionAsSubAction() failed, but ignored" , "NS_SUCCEEDED(rvIgnored)", "./../../../editor/libeditor/TextEditor.cpp" , 584); } } while (false) |
| 583 | NS_SUCCEEDED(rvIgnored),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::ReplaceSelectionAsSubAction() failed, but ignored" , "NS_SUCCEEDED(rvIgnored)", "./../../../editor/libeditor/TextEditor.cpp" , 584); } } while (false) |
| 584 | "EditorBase::ReplaceSelectionAsSubAction() failed, but ignored")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::ReplaceSelectionAsSubAction() failed, but ignored" , "NS_SUCCEEDED(rvIgnored)", "./../../../editor/libeditor/TextEditor.cpp" , 584); } } while (false); |
| 585 | } |
| 586 | } |
| 587 | |
| 588 | // Destroying AutoUpdateViewBatch may cause destroying us. |
| 589 | return NS_WARN_IF(Destroyed())NS_warn_if_impl(Destroyed(), "Destroyed()", "./../../../editor/libeditor/TextEditor.cpp" , 589) ? NS_ERROR_EDITOR_DESTROYED : NS_OK; |
| 590 | } |
| 591 | |
| 592 | already_AddRefed<Element> TextEditor::GetInputEventTargetElement() const { |
| 593 | RefPtr<Element> target = Element::FromEventTargetOrNull(mEventTarget); |
| 594 | return target.forget(); |
| 595 | } |
| 596 | |
| 597 | bool TextEditor::IsEmpty() const { |
| 598 | // This is a public method so that anytime this may be called, e.g., before |
| 599 | // initialized or after destroyed. However, GetTextNode() is an internal API |
| 600 | // for friend classes and internal use. Therefore, it asserts the conditions |
| 601 | // whether the anonymous subtree is available. Therefore, this method needs |
| 602 | // to get the Text with the anonymous <div>. |
| 603 | if (MOZ_UNLIKELY(!mInitSucceeded)(__builtin_expect(!!(!mInitSucceeded), 0))) { |
| 604 | // If we're temporarily destroyed while we're handling something, we can get |
| 605 | // the value from the cached text node which was maybe modified by us. This |
| 606 | // helps TextControlState and TextInputListener to notify the text control |
| 607 | // element of value changes, etc, at UnbindFromFrame(). |
| 608 | const Text* const cachedTextNode = GetCachedTextNode(); |
| 609 | return NS_WARN_IF(!cachedTextNode)NS_warn_if_impl(!cachedTextNode, "!cachedTextNode", "./../../../editor/libeditor/TextEditor.cpp" , 609) || !cachedTextNode->TextDataLength(); |
| 610 | } |
| 611 | const Text* const textNode = GetTextNode(); |
| 612 | return !textNode || !textNode->TextDataLength(); |
| 613 | } |
| 614 | |
| 615 | NS_IMETHODIMPnsresult TextEditor::GetTextLength(uint32_t* aCount) { |
| 616 | MOZ_ASSERT(aCount)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aCount)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(aCount))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aCount", "./../../../editor/libeditor/TextEditor.cpp" , 616); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aCount" ")") ; do { MOZ_CrashSequence(__null, 616); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
| 617 | // This is a public method so that anytime this may be called, e.g., before |
| 618 | // initialized or after destroyed. However, GetTextNode() is an internal API |
| 619 | // for friend classes and internal use. Therefore, it asserts the conditions |
| 620 | // whether the anonymous subtree is available. Therefore, this method needs |
| 621 | // to get the Text with the anonymous <div>. |
| 622 | if (MOZ_UNLIKELY(!mInitSucceeded)(__builtin_expect(!!(!mInitSucceeded), 0))) { |
| 623 | // If we're temporarily destroyed while we're handling something, we can get |
| 624 | // the value from the cached text node which was maybe modified by us. |
| 625 | const Text* const textNode = GetCachedTextNode(); |
| 626 | if (NS_WARN_IF(!textNode)NS_warn_if_impl(!textNode, "!textNode", "./../../../editor/libeditor/TextEditor.cpp" , 626)) { |
| 627 | return NS_ERROR_FAILURE; |
| 628 | } |
| 629 | *aCount = textNode->TextDataLength(); |
| 630 | return NS_OK; |
| 631 | } |
| 632 | |
| 633 | const Text* const textNode = GetTextNode(); |
| 634 | *aCount = textNode ? textNode->TextDataLength() : 0u; |
| 635 | return NS_OK; |
| 636 | } |
| 637 | |
| 638 | bool TextEditor::IsCopyToClipboardAllowedInternal() const { |
| 639 | MOZ_ASSERT(IsEditActionDataAvailable())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsEditActionDataAvailable())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsEditActionDataAvailable()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsEditActionDataAvailable()" , "./../../../editor/libeditor/TextEditor.cpp", 639); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "IsEditActionDataAvailable()" ")"); do { MOZ_CrashSequence (__null, 639); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
| 640 | if (!EditorBase::IsCopyToClipboardAllowedInternal()) { |
| 641 | return false; |
| 642 | } |
| 643 | |
| 644 | if (!IsSingleLineEditor() || !IsPasswordEditor() || |
| 645 | NS_WARN_IF(!mPasswordMaskData)NS_warn_if_impl(!mPasswordMaskData, "!mPasswordMaskData", "./../../../editor/libeditor/TextEditor.cpp" , 645)) { |
| 646 | return true; |
| 647 | } |
| 648 | |
| 649 | // The reveal button makes the value visible to the user, so copying it |
| 650 | // leaks nothing they cannot already read off the screen. |
| 651 | if (const Element* const textControlElement = GetExposedRoot()) { |
| 652 | if (textControlElement->State().HasState(ElementState::REVEALED)) { |
| 653 | return true; |
| 654 | } |
| 655 | } |
| 656 | |
| 657 | // If we're a password editor, we should allow selected text to be copied |
| 658 | // to the clipboard only when selection range is in unmasked range. |
| 659 | if (IsAllMasked() || IsMaskingPassword() || !UnmaskedLength()) { |
| 660 | return false; |
| 661 | } |
| 662 | |
| 663 | // If there are 2 or more ranges, we don't allow to copy/cut for now since |
| 664 | // we need to check whether all ranges are in unmasked range or not. |
| 665 | // Anyway, such operation in password field does not make sense. |
| 666 | if (SelectionRef().RangeCount() > 1) { |
| 667 | return false; |
| 668 | } |
| 669 | |
| 670 | uint32_t selectionStart = 0, selectionEnd = 0; |
| 671 | nsContentUtils::GetSelectionInTextControl(&SelectionRef(), mRootElement, |
| 672 | selectionStart, selectionEnd); |
| 673 | return UnmaskedStart() <= selectionStart && UnmaskedEnd() >= selectionEnd; |
| 674 | } |
| 675 | |
| 676 | nsresult TextEditor::HandlePasteAsQuotation( |
| 677 | AutoEditActionDataSetter& aEditActionData, |
| 678 | nsIClipboard::ClipboardType aClipboardType, DataTransfer* aDataTransfer) { |
| 679 | MOZ_ASSERT(aClipboardType == nsIClipboard::kGlobalClipboard ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aClipboardType == nsIClipboard::kGlobalClipboard || aClipboardType == nsIClipboard::kSelectionClipboard)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aClipboardType == nsIClipboard ::kGlobalClipboard || aClipboardType == nsIClipboard::kSelectionClipboard ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aClipboardType == nsIClipboard::kGlobalClipboard || aClipboardType == nsIClipboard::kSelectionClipboard" , "./../../../editor/libeditor/TextEditor.cpp", 680); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aClipboardType == nsIClipboard::kGlobalClipboard || aClipboardType == nsIClipboard::kSelectionClipboard" ")"); do { MOZ_CrashSequence(__null, 680); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
| 680 | aClipboardType == nsIClipboard::kSelectionClipboard)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aClipboardType == nsIClipboard::kGlobalClipboard || aClipboardType == nsIClipboard::kSelectionClipboard)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aClipboardType == nsIClipboard ::kGlobalClipboard || aClipboardType == nsIClipboard::kSelectionClipboard ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aClipboardType == nsIClipboard::kGlobalClipboard || aClipboardType == nsIClipboard::kSelectionClipboard" , "./../../../editor/libeditor/TextEditor.cpp", 680); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aClipboardType == nsIClipboard::kGlobalClipboard || aClipboardType == nsIClipboard::kSelectionClipboard" ")"); do { MOZ_CrashSequence(__null, 680); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
| 681 | if (NS_WARN_IF(!GetDocument())NS_warn_if_impl(!GetDocument(), "!GetDocument()", "./../../../editor/libeditor/TextEditor.cpp" , 681)) { |
| 682 | return NS_OK; |
| 683 | } |
| 684 | |
| 685 | // XXX Why don't we dispatch ePaste event here? |
| 686 | |
| 687 | // Get the nsITransferable interface for getting the data from the clipboard |
| 688 | Result<nsCOMPtr<nsITransferable>, nsresult> maybeTransferable = |
| 689 | EditorUtils::CreateTransferableForPlainText(*GetDocument()); |
| 690 | if (maybeTransferable.isErr()) { |
| 691 | NS_WARNING("EditorUtils::CreateTransferableForPlainText() failed")NS_DebugBreak(NS_DEBUG_WARNING, "EditorUtils::CreateTransferableForPlainText() failed" , nullptr, "./../../../editor/libeditor/TextEditor.cpp", 691); |
| 692 | return maybeTransferable.unwrapErr(); |
| 693 | } |
| 694 | nsCOMPtr<nsITransferable> trans(maybeTransferable.unwrap()); |
| 695 | if (!trans) { |
| 696 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "EditorUtils::CreateTransferableForPlainText() returned nullptr, but " "ignored", nullptr, "./../../../editor/libeditor/TextEditor.cpp" , 698) |
| 697 | "EditorUtils::CreateTransferableForPlainText() returned nullptr, but "NS_DebugBreak(NS_DEBUG_WARNING, "EditorUtils::CreateTransferableForPlainText() returned nullptr, but " "ignored", nullptr, "./../../../editor/libeditor/TextEditor.cpp" , 698) |
| 698 | "ignored")NS_DebugBreak(NS_DEBUG_WARNING, "EditorUtils::CreateTransferableForPlainText() returned nullptr, but " "ignored", nullptr, "./../../../editor/libeditor/TextEditor.cpp" , 698); |
| 699 | return NS_OK; |
| 700 | } |
| 701 | |
| 702 | // Get the Data from the clipboard |
| 703 | nsresult rv = |
Value stored to 'rv' during its initialization is never read | |
| 704 | GetDataFromDataTransferOrClipboard(aDataTransfer, trans, aClipboardType); |
| 705 | |
| 706 | // Now we ask the transferable for the data |
| 707 | // it still owns the data, we just have a pointer to it. |
| 708 | // If it can't support a "text" output of the data the call will fail |
| 709 | nsCOMPtr<nsISupports> genericDataObj; |
| 710 | nsAutoCString flavor; |
| 711 | rv = trans->GetAnyTransferData(flavor, getter_AddRefs(genericDataObj)); |
| 712 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 713 | NS_WARNING("nsITransferable::GetAnyTransferData() failed")NS_DebugBreak(NS_DEBUG_WARNING, "nsITransferable::GetAnyTransferData() failed" , nullptr, "./../../../editor/libeditor/TextEditor.cpp", 713); |
| 714 | return rv; |
| 715 | } |
| 716 | |
| 717 | if (!flavor.EqualsLiteral(kTextMime"text/plain") && |
| 718 | !flavor.EqualsLiteral(kMozTextInternal"text/x-moz-text-internal") && |
| 719 | !flavor.EqualsLiteral(kURLDataMime"text/x-moz-url-data")) { |
| 720 | return NS_OK; |
| 721 | } |
| 722 | |
| 723 | nsCOMPtr<nsISupportsString> text = do_QueryInterface(genericDataObj); |
| 724 | if (!text) { |
| 725 | return NS_OK; |
| 726 | } |
| 727 | |
| 728 | nsString stuffToPaste; |
| 729 | DebugOnly<nsresult> rvIgnored = text->GetData(stuffToPaste); |
| 730 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "nsISupportsString::GetData() failed, but ignored" , "NS_SUCCEEDED(rvIgnored)", "./../../../editor/libeditor/TextEditor.cpp" , 731); } } while (false) |
| 731 | "nsISupportsString::GetData() failed, but ignored")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "nsISupportsString::GetData() failed, but ignored" , "NS_SUCCEEDED(rvIgnored)", "./../../../editor/libeditor/TextEditor.cpp" , 731); } } while (false); |
| 732 | if (stuffToPaste.IsEmpty()) { |
| 733 | return NS_OK; |
| 734 | } |
| 735 | |
| 736 | aEditActionData.SetData(stuffToPaste); |
| 737 | if (!stuffToPaste.IsEmpty()) { |
| 738 | nsContentUtils::PlatformToDOMLineBreaks(stuffToPaste); |
| 739 | } |
| 740 | rv = aEditActionData.MaybeDispatchBeforeInputEvent(); |
| 741 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 742 | NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,do { if (!(rv == NS_ERROR_EDITOR_ACTION_CANCELED)) { NS_DebugBreak (NS_DEBUG_WARNING, "MaybeDispatchBeforeInputEvent() failed", "rv == NS_ERROR_EDITOR_ACTION_CANCELED" , "./../../../editor/libeditor/TextEditor.cpp", 743); } } while (false) |
| 743 | "MaybeDispatchBeforeInputEvent() failed")do { if (!(rv == NS_ERROR_EDITOR_ACTION_CANCELED)) { NS_DebugBreak (NS_DEBUG_WARNING, "MaybeDispatchBeforeInputEvent() failed", "rv == NS_ERROR_EDITOR_ACTION_CANCELED" , "./../../../editor/libeditor/TextEditor.cpp", 743); } } while (false); |
| 744 | return rv; |
| 745 | } |
| 746 | |
| 747 | AutoPlaceholderBatch treatAsOneTransaction( |
| 748 | *this, ScrollSelectionIntoView::Yes, __FUNCTION__); |
| 749 | rv = InsertWithQuotationsAsSubAction(stuffToPaste); |
| 750 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::InsertWithQuotationsAsSubAction() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 751); } } while (false) |
| 751 | "TextEditor::InsertWithQuotationsAsSubAction() failed")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::InsertWithQuotationsAsSubAction() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 751); } } while (false); |
| 752 | return rv; |
| 753 | } |
| 754 | |
| 755 | nsresult TextEditor::InsertWithQuotationsAsSubAction( |
| 756 | const nsAString& aQuotedText) { |
| 757 | MOZ_ASSERT(IsEditActionDataAvailable())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsEditActionDataAvailable())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsEditActionDataAvailable()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsEditActionDataAvailable()" , "./../../../editor/libeditor/TextEditor.cpp", 757); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "IsEditActionDataAvailable()" ")"); do { MOZ_CrashSequence (__null, 757); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
| 758 | |
| 759 | if (IsReadonly()) { |
| 760 | return NS_OK; |
| 761 | } |
| 762 | |
| 763 | // Let the citer quote it for us: |
| 764 | nsString quotedStuff; |
| 765 | InternetCiter::GetCiteString(aQuotedText, quotedStuff); |
| 766 | |
| 767 | // It's best to put a blank line after the quoted text so that mails |
| 768 | // written without thinking won't be so ugly. |
| 769 | if (!aQuotedText.IsEmpty() && (aQuotedText.Last() != char16_t('\n'))) { |
| 770 | quotedStuff.Append(char16_t('\n')); |
| 771 | } |
| 772 | |
| 773 | IgnoredErrorResult ignoredError; |
| 774 | AutoEditSubActionNotifier startToHandleEditSubAction( |
| 775 | *this, EditSubAction::eInsertText, nsIEditor::eNext, ignoredError); |
| 776 | if (NS_WARN_IF(ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))NS_warn_if_impl(ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED ), "ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED)", "./../../../editor/libeditor/TextEditor.cpp" , 776)) { |
| 777 | return ignoredError.StealNSResult(); |
| 778 | } |
| 779 | NS_WARNING_ASSERTION(do { if (!(!ignoredError.Failed())) { NS_DebugBreak(NS_DEBUG_WARNING , "TextEditor::OnStartToHandleTopLevelEditSubAction() failed, but ignored" , "!ignoredError.Failed()", "./../../../editor/libeditor/TextEditor.cpp" , 781); } } while (false) |
| 780 | !ignoredError.Failed(),do { if (!(!ignoredError.Failed())) { NS_DebugBreak(NS_DEBUG_WARNING , "TextEditor::OnStartToHandleTopLevelEditSubAction() failed, but ignored" , "!ignoredError.Failed()", "./../../../editor/libeditor/TextEditor.cpp" , 781); } } while (false) |
| 781 | "TextEditor::OnStartToHandleTopLevelEditSubAction() failed, but ignored")do { if (!(!ignoredError.Failed())) { NS_DebugBreak(NS_DEBUG_WARNING , "TextEditor::OnStartToHandleTopLevelEditSubAction() failed, but ignored" , "!ignoredError.Failed()", "./../../../editor/libeditor/TextEditor.cpp" , 781); } } while (false); |
| 782 | |
| 783 | // XXX Do we need to support paste-as-quotation in password editor (and |
| 784 | // also in single line editor)? |
| 785 | MaybeDoAutoPasswordMasking(); |
| 786 | |
| 787 | nsresult rv = InsertTextAsSubAction(quotedStuff, InsertTextFor::NormalText); |
| 788 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::InsertTextAsSubAction() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 789); } } while (false) |
| 789 | "EditorBase::InsertTextAsSubAction() failed")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::InsertTextAsSubAction() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 789); } } while (false); |
| 790 | return rv; |
| 791 | } |
| 792 | |
| 793 | nsresult TextEditor::SelectEntireDocument() { |
| 794 | MOZ_ASSERT(IsEditActionDataAvailable())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsEditActionDataAvailable())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsEditActionDataAvailable()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsEditActionDataAvailable()" , "./../../../editor/libeditor/TextEditor.cpp", 794); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "IsEditActionDataAvailable()" ")"); do { MOZ_CrashSequence (__null, 794); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
| 795 | |
| 796 | if (NS_WARN_IF(!mInitSucceeded)NS_warn_if_impl(!mInitSucceeded, "!mInitSucceeded", "./../../../editor/libeditor/TextEditor.cpp" , 796)) { |
| 797 | return NS_ERROR_NOT_INITIALIZED; |
| 798 | } |
| 799 | |
| 800 | RefPtr<Element> anonymousDivElement = GetRoot(); |
| 801 | if (NS_WARN_IF(!anonymousDivElement)NS_warn_if_impl(!anonymousDivElement, "!anonymousDivElement", "./../../../editor/libeditor/TextEditor.cpp", 801)) { |
| 802 | return NS_ERROR_NOT_INITIALIZED; |
| 803 | } |
| 804 | |
| 805 | RefPtr<Text> text = |
| 806 | Text::FromNodeOrNull(anonymousDivElement->GetFirstChild()); |
| 807 | MOZ_ASSERT(text)do { static_assert( mozilla::detail::AssertionConditionType< decltype(text)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(text))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("text", "./../../../editor/libeditor/TextEditor.cpp" , 807); AnnotateMozCrashReason("MOZ_ASSERT" "(" "text" ")"); do { MOZ_CrashSequence(__null, 807); __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
| 808 | |
| 809 | MOZ_TRY(SelectionRef().SetStartAndEndInLimiter(__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (SelectionRef().SetStartAndEndInLimiter( *text, 0, *text, text ->TextDataLength(), eDirNext, nsISelectionListener::SELECTALL_REASON )); if ((__builtin_expect(!!(mozTryVarTempResult.isErr()), 0) )) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult .unwrap(); }) |
| 810 | *text, 0, *text, text->TextDataLength(), eDirNext,__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (SelectionRef().SetStartAndEndInLimiter( *text, 0, *text, text ->TextDataLength(), eDirNext, nsISelectionListener::SELECTALL_REASON )); if ((__builtin_expect(!!(mozTryVarTempResult.isErr()), 0) )) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult .unwrap(); }) |
| 811 | nsISelectionListener::SELECTALL_REASON))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult (SelectionRef().SetStartAndEndInLimiter( *text, 0, *text, text ->TextDataLength(), eDirNext, nsISelectionListener::SELECTALL_REASON )); if ((__builtin_expect(!!(mozTryVarTempResult.isErr()), 0) )) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult .unwrap(); }); |
| 812 | |
| 813 | return NS_OK; |
| 814 | } |
| 815 | |
| 816 | EventTarget* TextEditor::GetDOMEventTarget() const { return mEventTarget; } |
| 817 | |
| 818 | void TextEditor::ReinitializeSelection(Element& aElement) { |
| 819 | MOZ_LOG(gTextEditorLog, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: ReinitializeSelection(aElement=%s)", this , ToString(RefPtr{&aElement}).c_str()); } } while (0) |
| 820 | ("%p: ReinitializeSelection(aElement=%s)", this,do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: ReinitializeSelection(aElement=%s)", this , ToString(RefPtr{&aElement}).c_str()); } } while (0) |
| 821 | ToString(RefPtr{&aElement}).c_str()))do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: ReinitializeSelection(aElement=%s)", this , ToString(RefPtr{&aElement}).c_str()); } } while (0); |
| 822 | |
| 823 | if (MOZ_UNLIKELY(Destroyed())(__builtin_expect(!!(Destroyed()), 0))) { |
| 824 | LogOrWarn(this, gTextEditorLog, LogLevel::Error, "Destroyed() failed"); |
| 825 | return; |
| 826 | } |
| 827 | |
| 828 | AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing); |
| 829 | if (MOZ_UNLIKELY(!editActionData.CanHandle())(__builtin_expect(!!(!editActionData.CanHandle()), 0))) { |
| 830 | LogOrWarn(this, gTextEditorLog, LogLevel::Error, |
| 831 | "AutoEditActionDataSetter::CanHandle() failed"); |
| 832 | return; |
| 833 | } |
| 834 | |
| 835 | // We don't need to flush pending notifications here and we don't need to |
| 836 | // handle spellcheck at first focus. Therefore, we don't need to call |
| 837 | // `TextEditor::OnFocus` here. |
| 838 | EditorBase::OnFocus(aElement); |
| 839 | |
| 840 | // If previous focused editor turn on spellcheck and this editor doesn't |
| 841 | // turn on it, spellcheck state is mismatched. So we need to re-sync it. |
| 842 | SyncRealTimeSpell(); |
| 843 | } |
| 844 | |
| 845 | nsresult TextEditor::OnFocus(const nsINode& aOriginalEventTargetNode) { |
| 846 | MOZ_LOG(gTextEditorLog, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: OnFocus(aOriginalEventTargetNode=%s)", this, ToString(RefPtr{&aOriginalEventTargetNode}).c_str( )); } } while (0) |
| 847 | ("%p: OnFocus(aOriginalEventTargetNode=%s)", this,do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: OnFocus(aOriginalEventTargetNode=%s)", this, ToString(RefPtr{&aOriginalEventTargetNode}).c_str( )); } } while (0) |
| 848 | ToString(RefPtr{&aOriginalEventTargetNode}).c_str()))do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: OnFocus(aOriginalEventTargetNode=%s)", this, ToString(RefPtr{&aOriginalEventTargetNode}).c_str( )); } } while (0); |
| 849 | |
| 850 | AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing); |
| 851 | if (MOZ_UNLIKELY(!editActionData.CanHandle())(__builtin_expect(!!(!editActionData.CanHandle()), 0))) { |
| 852 | LogOrWarn(this, gTextEditorLog, LogLevel::Error, |
| 853 | "AutoEditActionDataSetter::CanHandle() failed"); |
| 854 | return NS_ERROR_FAILURE; |
| 855 | } |
| 856 | return EditorBase::OnFocus(aOriginalEventTargetNode); |
| 857 | } |
| 858 | |
| 859 | void TextEditor::PostHandleFocusEvent(const nsINode& aFocusEventTargetNode) { |
| 860 | MOZ_LOG(gTextEditorLog, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: PostHandleFocusEvent(aFocusEvent={ " "GetOriginalEventTarget()=%s }), %s" , this, ToString(RefPtr{&aFocusEventTargetNode}).c_str(), GetFocusedElement() ? "but already lost focus" : "still has focus" ); } } while (0) |
| 861 | ("%p: PostHandleFocusEvent(aFocusEvent={ "do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: PostHandleFocusEvent(aFocusEvent={ " "GetOriginalEventTarget()=%s }), %s" , this, ToString(RefPtr{&aFocusEventTargetNode}).c_str(), GetFocusedElement() ? "but already lost focus" : "still has focus" ); } } while (0) |
| 862 | "GetOriginalEventTarget()=%s }), %s",do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: PostHandleFocusEvent(aFocusEvent={ " "GetOriginalEventTarget()=%s }), %s" , this, ToString(RefPtr{&aFocusEventTargetNode}).c_str(), GetFocusedElement() ? "but already lost focus" : "still has focus" ); } } while (0) |
| 863 | this, ToString(RefPtr{&aFocusEventTargetNode}).c_str(),do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: PostHandleFocusEvent(aFocusEvent={ " "GetOriginalEventTarget()=%s }), %s" , this, ToString(RefPtr{&aFocusEventTargetNode}).c_str(), GetFocusedElement() ? "but already lost focus" : "still has focus" ); } } while (0) |
| 864 | GetFocusedElement() ? "but already lost focus" : "still has focus"))do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: PostHandleFocusEvent(aFocusEvent={ " "GetOriginalEventTarget()=%s }), %s" , this, ToString(RefPtr{&aFocusEventTargetNode}).c_str(), GetFocusedElement() ? "but already lost focus" : "still has focus" ); } } while (0); |
| 865 | |
| 866 | AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing); |
| 867 | if (MOZ_UNLIKELY(!editActionData.CanHandle())(__builtin_expect(!!(!editActionData.CanHandle()), 0))) { |
| 868 | LogOrWarn(this, gTextEditorLog, LogLevel::Error, |
| 869 | "AutoEditActionDataSetter::CanHandle() failed"); |
| 870 | return; |
| 871 | } |
| 872 | |
| 873 | // Spell check a textarea the first time that it is focused. |
| 874 | nsresult rv = FlushPendingSpellCheck(); |
| 875 | if (rv == NS_ERROR_EDITOR_DESTROYED) [[unlikely]] { |
| 876 | LogOrWarn(this, gTextEditorLog, LogLevel::Error, |
| 877 | "EditorBase::FlushPendingSpellCheck() failed"); |
| 878 | return; |
| 879 | } |
| 880 | NS_WARNING_ASSERTION(do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::FlushPendingSpellCheck() failed, but ignored" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 882); } } while (false) |
| 881 | NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::FlushPendingSpellCheck() failed, but ignored" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 882); } } while (false) |
| 882 | "EditorBase::FlushPendingSpellCheck() failed, but ignored")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::FlushPendingSpellCheck() failed, but ignored" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 882); } } while (false); |
| 883 | if (!CanKeepHandlingFocusEvent(aFocusEventTargetNode)) [[unlikely]] { |
| 884 | MOZ_LOG(gTextEditorLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "%p: CanKeepHandlingFocusEvent() returned false after " "FlushPendingSpellCheck()", this); } } while (0) |
| 885 | ("%p: CanKeepHandlingFocusEvent() returned false after "do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "%p: CanKeepHandlingFocusEvent() returned false after " "FlushPendingSpellCheck()", this); } } while (0) |
| 886 | "FlushPendingSpellCheck()",do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "%p: CanKeepHandlingFocusEvent() returned false after " "FlushPendingSpellCheck()", this); } } while (0) |
| 887 | this))do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Debug, "%p: CanKeepHandlingFocusEvent() returned false after " "FlushPendingSpellCheck()", this); } } while (0); |
| 888 | return; |
| 889 | } |
| 890 | EditorBase::PostHandleFocusEvent(aFocusEventTargetNode); |
| 891 | } |
| 892 | |
| 893 | nsresult TextEditor::OnBlur(const EventTarget* aEventTarget) { |
| 894 | MOZ_LOG(gTextEditorLog, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: OnBlur(aEventTarget=%s)", this, ToString (RefPtr{aEventTarget}).c_str()); } } while (0) |
| 895 | ("%p: OnBlur(aEventTarget=%s)", this,do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: OnBlur(aEventTarget=%s)", this, ToString (RefPtr{aEventTarget}).c_str()); } } while (0) |
| 896 | ToString(RefPtr{aEventTarget}).c_str()))do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: OnBlur(aEventTarget=%s)", this, ToString (RefPtr{aEventTarget}).c_str()); } } while (0); |
| 897 | |
| 898 | // check if something else is focused. If another element is focused, then |
| 899 | // we should not change the selection. If another element already has focus, |
| 900 | // we should not maintain the selection because we may not have the rights |
| 901 | // doing it. |
| 902 | if ([[maybe_unused]] Element* const focusedElement = |
| 903 | nsFocusManager::GetFocusedElementStatic()) { |
| 904 | MOZ_LOG(gTextEditorLog, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: OnBlur() is ignored because another element already has " "focus (%s)", this, ToString(RefPtr{focusedElement}).c_str() ); } } while (0) |
| 905 | ("%p: OnBlur() is ignored because another element already has "do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: OnBlur() is ignored because another element already has " "focus (%s)", this, ToString(RefPtr{focusedElement}).c_str() ); } } while (0) |
| 906 | "focus (%s)",do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: OnBlur() is ignored because another element already has " "focus (%s)", this, ToString(RefPtr{focusedElement}).c_str() ); } } while (0) |
| 907 | this, ToString(RefPtr{focusedElement}).c_str()))do { const ::mozilla::LogModule* moz_real_module = gTextEditorLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module , LogLevel::Info, "%p: OnBlur() is ignored because another element already has " "focus (%s)", this, ToString(RefPtr{focusedElement}).c_str() ); } } while (0); |
| 908 | return NS_OK; |
| 909 | } |
| 910 | |
| 911 | nsresult rv = FinalizeSelection(); |
| 912 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 913 | LogOrWarn(this, gTextEditorLog, LogLevel::Error, |
| 914 | "EditorBase::FinalizeSelection() failed"); |
| 915 | return rv; |
| 916 | } |
| 917 | return NS_OK; |
| 918 | } |
| 919 | |
| 920 | nsresult TextEditor::SetAttributeOrEquivalent(Element* aElement, |
| 921 | nsAtom* aAttribute, |
| 922 | const nsAString& aValue, |
| 923 | bool aSuppressTransaction) { |
| 924 | if (NS_WARN_IF(!aElement)NS_warn_if_impl(!aElement, "!aElement", "./../../../editor/libeditor/TextEditor.cpp" , 924) || NS_WARN_IF(!aAttribute)NS_warn_if_impl(!aAttribute, "!aAttribute", "./../../../editor/libeditor/TextEditor.cpp" , 924)) { |
| 925 | return NS_ERROR_INVALID_ARG; |
| 926 | } |
| 927 | |
| 928 | AutoEditActionDataSetter editActionData(*this, EditAction::eSetAttribute); |
| 929 | nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent(); |
| 930 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 931 | NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,do { if (!(rv == NS_ERROR_EDITOR_ACTION_CANCELED)) { NS_DebugBreak (NS_DEBUG_WARNING, "CanHandleAndMaybeDispatchBeforeInputEvent() failed" , "rv == NS_ERROR_EDITOR_ACTION_CANCELED", "./../../../editor/libeditor/TextEditor.cpp" , 932); } } while (false) |
| 932 | "CanHandleAndMaybeDispatchBeforeInputEvent() failed")do { if (!(rv == NS_ERROR_EDITOR_ACTION_CANCELED)) { NS_DebugBreak (NS_DEBUG_WARNING, "CanHandleAndMaybeDispatchBeforeInputEvent() failed" , "rv == NS_ERROR_EDITOR_ACTION_CANCELED", "./../../../editor/libeditor/TextEditor.cpp" , 932); } } while (false); |
| 933 | return EditorBase::ToGenericNSResult(rv); |
| 934 | } |
| 935 | |
| 936 | rv = SetAttributeWithTransaction(*aElement, *aAttribute, aValue); |
| 937 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::SetAttributeWithTransaction() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 938); } } while (false) |
| 938 | "EditorBase::SetAttributeWithTransaction() failed")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::SetAttributeWithTransaction() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 938); } } while (false); |
| 939 | return EditorBase::ToGenericNSResult(rv); |
| 940 | } |
| 941 | |
| 942 | nsresult TextEditor::RemoveAttributeOrEquivalent(Element* aElement, |
| 943 | nsAtom* aAttribute, |
| 944 | bool aSuppressTransaction) { |
| 945 | if (NS_WARN_IF(!aElement)NS_warn_if_impl(!aElement, "!aElement", "./../../../editor/libeditor/TextEditor.cpp" , 945) || NS_WARN_IF(!aAttribute)NS_warn_if_impl(!aAttribute, "!aAttribute", "./../../../editor/libeditor/TextEditor.cpp" , 945)) { |
| 946 | return NS_ERROR_INVALID_ARG; |
| 947 | } |
| 948 | |
| 949 | AutoEditActionDataSetter editActionData(*this, EditAction::eRemoveAttribute); |
| 950 | nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent(); |
| 951 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 952 | NS_WARNING_ASSERTION(rv == NS_ERROR_EDITOR_ACTION_CANCELED,do { if (!(rv == NS_ERROR_EDITOR_ACTION_CANCELED)) { NS_DebugBreak (NS_DEBUG_WARNING, "CanHandleAndMaybeDispatchBeforeInputEvent() failed" , "rv == NS_ERROR_EDITOR_ACTION_CANCELED", "./../../../editor/libeditor/TextEditor.cpp" , 953); } } while (false) |
| 953 | "CanHandleAndMaybeDispatchBeforeInputEvent() failed")do { if (!(rv == NS_ERROR_EDITOR_ACTION_CANCELED)) { NS_DebugBreak (NS_DEBUG_WARNING, "CanHandleAndMaybeDispatchBeforeInputEvent() failed" , "rv == NS_ERROR_EDITOR_ACTION_CANCELED", "./../../../editor/libeditor/TextEditor.cpp" , 953); } } while (false); |
| 954 | return EditorBase::ToGenericNSResult(rv); |
| 955 | } |
| 956 | |
| 957 | rv = RemoveAttributeWithTransaction(*aElement, *aAttribute); |
| 958 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::RemoveAttributeWithTransaction() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 959); } } while (false) |
| 959 | "EditorBase::RemoveAttributeWithTransaction() failed")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::RemoveAttributeWithTransaction() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 959); } } while (false); |
| 960 | return EditorBase::ToGenericNSResult(rv); |
| 961 | } |
| 962 | |
| 963 | template <typename EditorDOMPointType> |
| 964 | EditorDOMPointType TextEditor::FindBetterInsertionPoint( |
| 965 | const EditorDOMPointType& aPoint) const { |
| 966 | if (MOZ_UNLIKELY(NS_WARN_IF(!aPoint.IsInContentNode()))(__builtin_expect(!!(NS_warn_if_impl(!aPoint.IsInContentNode( ), "!aPoint.IsInContentNode()", "./../../../editor/libeditor/TextEditor.cpp" , 966)), 0))) { |
| 967 | return aPoint; |
| 968 | } |
| 969 | |
| 970 | MOZ_ASSERT(aPoint.IsSetAndValid())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aPoint.IsSetAndValid())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aPoint.IsSetAndValid()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("aPoint.IsSetAndValid()" , "./../../../editor/libeditor/TextEditor.cpp", 970); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aPoint.IsSetAndValid()" ")"); do { MOZ_CrashSequence (__null, 970); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
| 971 | |
| 972 | Element* const anonymousDivElement = GetRoot(); |
| 973 | if (aPoint.GetContainer() == anonymousDivElement) { |
| 974 | // In some cases, aPoint points start of the anonymous <div>. To avoid |
| 975 | // injecting unneeded text nodes, we first look to see if we have one |
| 976 | // available. In that case, we'll just adjust node and offset accordingly. |
| 977 | if (aPoint.IsStartOfContainer()) { |
| 978 | if (aPoint.GetContainer()->HasChildren() && |
| 979 | aPoint.GetContainer()->GetFirstChild()->IsText()) { |
| 980 | return EditorDOMPointType(aPoint.GetContainer()->GetFirstChild(), 0u); |
| 981 | } |
| 982 | } |
| 983 | // In some other cases, aPoint points the terminating padding <br> element |
| 984 | // for empty last line in the anonymous <div>. In that case, we'll adjust |
| 985 | // aInOutNode and aInOutOffset to the preceding text node, if any. |
| 986 | else { |
| 987 | nsIContent* child = aPoint.GetContainer()->GetLastChild(); |
| 988 | while (child) { |
| 989 | if (child->IsText()) { |
| 990 | return EditorDOMPointType::AtEndOf(*child); |
| 991 | } |
| 992 | child = child->GetPreviousSibling(); |
| 993 | } |
| 994 | } |
| 995 | } |
| 996 | |
| 997 | // Sometimes, aPoint points the padding <br> element. In that case, we'll |
| 998 | // adjust the insertion point to the previous text node, if one exists, or to |
| 999 | // the parent anonymous DIV. |
| 1000 | if (EditorUtils::IsPaddingBRElementForEmptyLastLine( |
| 1001 | *aPoint.template ContainerAs<nsIContent>()) && |
| 1002 | aPoint.IsStartOfContainer()) { |
| 1003 | nsIContent* previousSibling = aPoint.GetContainer()->GetPreviousSibling(); |
| 1004 | if (previousSibling && previousSibling->IsText()) { |
| 1005 | return EditorDOMPointType::AtEndOf(*previousSibling); |
| 1006 | } |
| 1007 | |
| 1008 | nsINode* parentOfContainer = aPoint.GetContainerParent(); |
| 1009 | if (parentOfContainer && parentOfContainer == anonymousDivElement) { |
| 1010 | return EditorDOMPointType(parentOfContainer, |
| 1011 | aPoint.template ContainerAs<nsIContent>(), 0u); |
| 1012 | } |
| 1013 | } |
| 1014 | |
| 1015 | return aPoint; |
| 1016 | } |
| 1017 | |
| 1018 | // static |
| 1019 | void TextEditor::MaskString(nsString& aString, const Text& aTextNode, |
| 1020 | uint32_t aStartOffsetInString, |
| 1021 | uint32_t aStartOffsetInText) { |
| 1022 | MOZ_ASSERT(aTextNode.HasFlag(NS_MAYBE_MASKED))do { static_assert( mozilla::detail::AssertionConditionType< decltype(aTextNode.HasFlag(NS_MAYBE_MASKED))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(aTextNode.HasFlag(NS_MAYBE_MASKED )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aTextNode.HasFlag(NS_MAYBE_MASKED)", "./../../../editor/libeditor/TextEditor.cpp" , 1022); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTextNode.HasFlag(NS_MAYBE_MASKED)" ")"); do { MOZ_CrashSequence(__null, 1022); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
| 1023 | MOZ_ASSERT(aStartOffsetInString == 0 || aStartOffsetInText == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(aStartOffsetInString == 0 || aStartOffsetInText == 0 )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aStartOffsetInString == 0 || aStartOffsetInText == 0 ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "aStartOffsetInString == 0 || aStartOffsetInText == 0", "./../../../editor/libeditor/TextEditor.cpp" , 1023); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStartOffsetInString == 0 || aStartOffsetInText == 0" ")"); do { MOZ_CrashSequence(__null, 1023); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
| 1024 | |
| 1025 | const TextEditor* const textEditor = |
| 1026 | nsContentUtils::GetExtantTextEditorFromAnonymousNode(&aTextNode); |
| 1027 | if (textEditor) { |
| 1028 | // The reveal button shows the whole value, so nothing should be masked. |
| 1029 | const Element* const textControlElement = textEditor->GetExposedRoot(); |
| 1030 | if (textControlElement && |
| 1031 | textControlElement->State().HasState(ElementState::REVEALED)) { |
| 1032 | return; |
| 1033 | } |
| 1034 | } |
| 1035 | uint32_t unmaskStart = UINT32_MAX(4294967295U), unmaskLength = 0; |
| 1036 | if (textEditor && textEditor->UnmaskedLength() > 0) { |
| 1037 | unmaskStart = textEditor->UnmaskedStart(); |
| 1038 | unmaskLength = textEditor->UnmaskedLength(); |
| 1039 | // If text is copied from after unmasked range, we can treat this case |
| 1040 | // as mask all. |
| 1041 | if (aStartOffsetInText >= unmaskStart + unmaskLength) { |
| 1042 | unmaskLength = 0; |
| 1043 | unmaskStart = UINT32_MAX(4294967295U); |
| 1044 | } else { |
| 1045 | // If text is copied from middle of unmasked range, reduce the length |
| 1046 | // and adjust start offset. |
| 1047 | if (aStartOffsetInText > unmaskStart) { |
| 1048 | unmaskLength = unmaskStart + unmaskLength - aStartOffsetInText; |
| 1049 | unmaskStart = 0; |
| 1050 | } |
| 1051 | // If text is copied from before start of unmasked range, just adjust |
| 1052 | // the start offset. |
| 1053 | else { |
| 1054 | unmaskStart -= aStartOffsetInText; |
| 1055 | } |
| 1056 | // Make the range is in the string. |
| 1057 | unmaskStart += aStartOffsetInString; |
| 1058 | } |
| 1059 | } |
| 1060 | |
| 1061 | const char16_t kPasswordMask = TextEditor::PasswordMask(); |
| 1062 | for (uint32_t i = aStartOffsetInString; i < aString.Length(); ++i) { |
| 1063 | bool isSurrogatePair = mozilla::IsHighSurrogate(aString.CharAt(i)) && |
| 1064 | i < aString.Length() - 1 && |
| 1065 | mozilla::IsLowSurrogate(aString.CharAt(i + 1)); |
| 1066 | if (i < unmaskStart || i >= unmaskStart + unmaskLength) { |
| 1067 | if (isSurrogatePair) { |
| 1068 | aString.SetCharAt(kPasswordMask, i); |
| 1069 | aString.SetCharAt(kPasswordMask, i + 1); |
| 1070 | } else { |
| 1071 | aString.SetCharAt(kPasswordMask, i); |
| 1072 | } |
| 1073 | } |
| 1074 | |
| 1075 | // Skip the following low surrogate. |
| 1076 | if (isSurrogatePair) { |
| 1077 | ++i; |
| 1078 | } |
| 1079 | } |
| 1080 | } |
| 1081 | |
| 1082 | nsresult TextEditor::SetUnmaskRangeInternal(uint32_t aStart, uint32_t aLength, |
| 1083 | uint32_t aTimeout, bool aNotify, |
| 1084 | bool aForceStartMasking) { |
| 1085 | if (mPasswordMaskData) { |
| 1086 | mPasswordMaskData->mIsMaskingPassword = aForceStartMasking || aTimeout != 0; |
| 1087 | |
| 1088 | // We cannot manage multiple unmasked ranges so that shrink the previous |
| 1089 | // range first. |
| 1090 | if (!IsAllMasked()) { |
| 1091 | mPasswordMaskData->mUnmaskedLength = 0; |
| 1092 | mPasswordMaskData->CancelTimer(PasswordMaskData::ReleaseTimer::No); |
| 1093 | } |
| 1094 | } |
| 1095 | |
| 1096 | // If we're not a password editor, return error since this call does not |
| 1097 | // make sense. |
| 1098 | if (!IsPasswordEditor() || NS_WARN_IF(!mPasswordMaskData)NS_warn_if_impl(!mPasswordMaskData, "!mPasswordMaskData", "./../../../editor/libeditor/TextEditor.cpp" , 1098)) { |
| 1099 | mPasswordMaskData->CancelTimer(PasswordMaskData::ReleaseTimer::Yes); |
| 1100 | return NS_ERROR_NOT_AVAILABLE; |
| 1101 | } |
| 1102 | |
| 1103 | if (NS_WARN_IF(!GetRoot())NS_warn_if_impl(!GetRoot(), "!GetRoot()", "./../../../editor/libeditor/TextEditor.cpp" , 1103)) { |
| 1104 | return NS_ERROR_NOT_INITIALIZED; |
| 1105 | } |
| 1106 | Text* const text = GetTextNode(); |
| 1107 | if (!text || !text->Length()) { |
| 1108 | // There is no anonymous text node in the editor. |
| 1109 | return aStart > 0 && aStart != UINT32_MAX(4294967295U) ? NS_ERROR_INVALID_ARG : NS_OK; |
| 1110 | } |
| 1111 | |
| 1112 | if (aStart < UINT32_MAX(4294967295U)) { |
| 1113 | uint32_t valueLength = text->Length(); |
| 1114 | if (aStart >= valueLength) { |
| 1115 | return NS_ERROR_INVALID_ARG; // There is no character can be masked. |
| 1116 | } |
| 1117 | // If aStart is middle of a surrogate pair, expand it to include the |
| 1118 | // preceding high surrogate because the caller may want to show a |
| 1119 | // character before the character at `aStart + 1`. |
| 1120 | const CharacterDataBuffer& characterDataBuffer = text->DataBuffer(); |
| 1121 | if (characterDataBuffer.IsLowSurrogateFollowingHighSurrogateAt(aStart)) { |
| 1122 | mPasswordMaskData->mUnmaskedStart = aStart - 1; |
| 1123 | // If caller collapses the range, keep it. Otherwise, expand the length. |
| 1124 | if (aLength > 0) { |
| 1125 | ++aLength; |
| 1126 | } |
| 1127 | } else { |
| 1128 | mPasswordMaskData->mUnmaskedStart = aStart; |
| 1129 | } |
| 1130 | mPasswordMaskData->mUnmaskedLength = |
| 1131 | std::min(valueLength - UnmaskedStart(), aLength); |
| 1132 | // If unmasked end is middle of a surrogate pair, expand it to include |
| 1133 | // the following low surrogate because the caller may want to show a |
| 1134 | // character after the character at `aStart + aLength`. |
| 1135 | if (UnmaskedEnd() < valueLength && |
| 1136 | characterDataBuffer.IsLowSurrogateFollowingHighSurrogateAt( |
| 1137 | UnmaskedEnd())) { |
| 1138 | mPasswordMaskData->mUnmaskedLength++; |
| 1139 | } |
| 1140 | // If it's first time to mask the unmasking characters with timer, create |
| 1141 | // the timer now. Then, we'll keep using it for saving the creation cost. |
| 1142 | if (!HasAutoMaskingTimer() && aLength && aTimeout && UnmaskedLength()) { |
| 1143 | mPasswordMaskData->mTimer = NS_NewTimer(); |
| 1144 | } |
| 1145 | } else { |
| 1146 | if (NS_WARN_IF(aLength != 0)NS_warn_if_impl(aLength != 0, "aLength != 0", "./../../../editor/libeditor/TextEditor.cpp" , 1146)) { |
| 1147 | return NS_ERROR_INVALID_ARG; |
| 1148 | } |
| 1149 | mPasswordMaskData->MaskAll(); |
| 1150 | } |
| 1151 | |
| 1152 | // Notify nsTextFrame of this update if the caller wants this to do it. |
| 1153 | // Only in this case, script may run. |
| 1154 | if (aNotify) { |
| 1155 | MOZ_ASSERT(IsEditActionDataAvailable())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsEditActionDataAvailable())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsEditActionDataAvailable()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsEditActionDataAvailable()" , "./../../../editor/libeditor/TextEditor.cpp", 1155); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "IsEditActionDataAvailable()" ")"); do { MOZ_CrashSequence (__null, 1155); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
| 1156 | |
| 1157 | RefPtr<Document> document = GetDocument(); |
| 1158 | if (NS_WARN_IF(!document)NS_warn_if_impl(!document, "!document", "./../../../editor/libeditor/TextEditor.cpp" , 1158)) { |
| 1159 | return NS_ERROR_NOT_INITIALIZED; |
| 1160 | } |
| 1161 | // Notify nsTextFrame of masking range change. |
| 1162 | if (RefPtr<PresShell> presShell = document->GetObservingPresShell()) { |
| 1163 | nsAutoScriptBlocker blockRunningScript; |
| 1164 | uint32_t valueLength = text->Length(); |
| 1165 | CharacterDataChangeInfo changeInfo = {false, 0, valueLength, valueLength}; |
| 1166 | presShell->CharacterDataChanged(text, changeInfo); |
| 1167 | } |
| 1168 | |
| 1169 | // Scroll caret into the view since masking or unmasking character may |
| 1170 | // move caret to outside of the view. |
| 1171 | nsresult rv = ScrollSelectionFocusIntoView(); |
| 1172 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 1173 | NS_WARNING("EditorBase::ScrollSelectionFocusIntoView() failed")NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::ScrollSelectionFocusIntoView() failed" , nullptr, "./../../../editor/libeditor/TextEditor.cpp", 1173 ); |
| 1174 | return rv; |
| 1175 | } |
| 1176 | } |
| 1177 | |
| 1178 | if (!IsAllMasked() && aTimeout != 0) { |
| 1179 | // Initialize the timer to mask the range automatically. |
| 1180 | MOZ_ASSERT(HasAutoMaskingTimer())do { static_assert( mozilla::detail::AssertionConditionType< decltype(HasAutoMaskingTimer())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(HasAutoMaskingTimer()))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("HasAutoMaskingTimer()" , "./../../../editor/libeditor/TextEditor.cpp", 1180); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "HasAutoMaskingTimer()" ")"); do { MOZ_CrashSequence (__null, 1180); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
| 1181 | DebugOnly<nsresult> rvIgnored = mPasswordMaskData->mTimer->InitWithCallback( |
| 1182 | this, aTimeout, nsITimer::TYPE_ONE_SHOT); |
| 1183 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "nsITimer::InitWithCallback() failed, but ignored" , "NS_SUCCEEDED(rvIgnored)", "./../../../editor/libeditor/TextEditor.cpp" , 1184); } } while (false) |
| 1184 | "nsITimer::InitWithCallback() failed, but ignored")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "nsITimer::InitWithCallback() failed, but ignored" , "NS_SUCCEEDED(rvIgnored)", "./../../../editor/libeditor/TextEditor.cpp" , 1184); } } while (false); |
| 1185 | } |
| 1186 | |
| 1187 | return NS_OK; |
| 1188 | } |
| 1189 | |
| 1190 | // static |
| 1191 | char16_t TextEditor::PasswordMask() { |
| 1192 | char16_t ret = LookAndFeel::GetPasswordCharacter(); |
| 1193 | if (!ret) { |
| 1194 | ret = '*'; |
| 1195 | } |
| 1196 | return ret; |
| 1197 | } |
| 1198 | |
| 1199 | MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMPnsresult TextEditor::Notify(nsITimer* aTimer) { |
| 1200 | // Check whether our text editor's password flag was changed before this |
| 1201 | // "hide password character" timer actually fires. |
| 1202 | if (!IsPasswordEditor() || NS_WARN_IF(!mPasswordMaskData)NS_warn_if_impl(!mPasswordMaskData, "!mPasswordMaskData", "./../../../editor/libeditor/TextEditor.cpp" , 1202)) { |
| 1203 | return NS_OK; |
| 1204 | } |
| 1205 | |
| 1206 | if (IsAllMasked()) { |
| 1207 | return NS_OK; |
| 1208 | } |
| 1209 | |
| 1210 | AutoEditActionDataSetter editActionData(*this, EditAction::eHidePassword); |
| 1211 | if (NS_WARN_IF(!editActionData.CanHandle())NS_warn_if_impl(!editActionData.CanHandle(), "!editActionData.CanHandle()" , "./../../../editor/libeditor/TextEditor.cpp", 1211)) { |
| 1212 | return NS_ERROR_NOT_INITIALIZED; |
| 1213 | } |
| 1214 | |
| 1215 | // Mask all characters. |
| 1216 | nsresult rv = MaskAllCharactersAndNotify(); |
| 1217 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::MaskAllCharactersAndNotify() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 1218); } } while (false) |
| 1218 | "TextEditor::MaskAllCharactersAndNotify() failed")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::MaskAllCharactersAndNotify() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 1218); } } while (false); |
| 1219 | |
| 1220 | if (StaticPrefs::editor_password_testing_mask_delay()) { |
| 1221 | if (RefPtr<Element> target = GetInputEventTargetElement()) { |
| 1222 | DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchTrustedEvent( |
| 1223 | target, u"MozLastInputMasked"_ns, CanBubble::eYes, Cancelable::eNo); |
| 1224 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::DispatchTrustedEvent(" "MozLastInputMasked) failed, but ignored", "NS_SUCCEEDED(rvIgnored)" , "./../../../editor/libeditor/TextEditor.cpp", 1226); } } while (false) |
| 1225 | "nsContentUtils::DispatchTrustedEvent("do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::DispatchTrustedEvent(" "MozLastInputMasked) failed, but ignored", "NS_SUCCEEDED(rvIgnored)" , "./../../../editor/libeditor/TextEditor.cpp", 1226); } } while (false) |
| 1226 | "MozLastInputMasked) failed, but ignored")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::DispatchTrustedEvent(" "MozLastInputMasked) failed, but ignored", "NS_SUCCEEDED(rvIgnored)" , "./../../../editor/libeditor/TextEditor.cpp", 1226); } } while (false); |
| 1227 | } |
| 1228 | } |
| 1229 | |
| 1230 | return EditorBase::ToGenericNSResult(rv); |
| 1231 | } |
| 1232 | |
| 1233 | NS_IMETHODIMPnsresult TextEditor::GetName(nsACString& aName) { |
| 1234 | aName.AssignLiteral("TextEditor"); |
| 1235 | return NS_OK; |
| 1236 | } |
| 1237 | |
| 1238 | void TextEditor::WillDeleteText(uint32_t aCurrentLength, |
| 1239 | uint32_t aRemoveStartOffset, |
| 1240 | uint32_t aRemoveLength) { |
| 1241 | MOZ_ASSERT(IsEditActionDataAvailable())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsEditActionDataAvailable())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsEditActionDataAvailable()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsEditActionDataAvailable()" , "./../../../editor/libeditor/TextEditor.cpp", 1241); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "IsEditActionDataAvailable()" ")"); do { MOZ_CrashSequence (__null, 1241); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
| 1242 | |
| 1243 | if (!IsPasswordEditor() || NS_WARN_IF(!mPasswordMaskData)NS_warn_if_impl(!mPasswordMaskData, "!mPasswordMaskData", "./../../../editor/libeditor/TextEditor.cpp" , 1243) || IsAllMasked()) { |
| 1244 | return; |
| 1245 | } |
| 1246 | |
| 1247 | // Adjust unmasked range before deletion since DOM mutation may cause |
| 1248 | // layout referring the range in old text. |
| 1249 | |
| 1250 | // If we need to mask automatically, mask all now. |
| 1251 | if (IsMaskingPassword()) { |
| 1252 | DebugOnly<nsresult> rvIgnored = MaskAllCharacters(); |
| 1253 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::MaskAllCharacters() failed, but ignored" , "NS_SUCCEEDED(rvIgnored)", "./../../../editor/libeditor/TextEditor.cpp" , 1254); } } while (false) |
| 1254 | "TextEditor::MaskAllCharacters() failed, but ignored")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::MaskAllCharacters() failed, but ignored" , "NS_SUCCEEDED(rvIgnored)", "./../../../editor/libeditor/TextEditor.cpp" , 1254); } } while (false); |
| 1255 | return; |
| 1256 | } |
| 1257 | |
| 1258 | if (aRemoveStartOffset < UnmaskedStart()) { |
| 1259 | // If removing range is before the unmasked range, move it. |
| 1260 | if (aRemoveStartOffset + aRemoveLength <= UnmaskedStart()) { |
| 1261 | DebugOnly<nsresult> rvIgnored = |
| 1262 | SetUnmaskRange(UnmaskedStart() - aRemoveLength, UnmaskedLength()); |
| 1263 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetUnmaskRange() failed, but ignored" , "NS_SUCCEEDED(rvIgnored)", "./../../../editor/libeditor/TextEditor.cpp" , 1264); } } while (false) |
| 1264 | "TextEditor::SetUnmaskRange() failed, but ignored")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetUnmaskRange() failed, but ignored" , "NS_SUCCEEDED(rvIgnored)", "./../../../editor/libeditor/TextEditor.cpp" , 1264); } } while (false); |
| 1265 | return; |
| 1266 | } |
| 1267 | |
| 1268 | // If removing range starts before unmasked range, and ends in unmasked |
| 1269 | // range, move and shrink the range. |
| 1270 | if (aRemoveStartOffset + aRemoveLength < UnmaskedEnd()) { |
| 1271 | uint32_t unmaskedLengthInRemovingRange = |
| 1272 | aRemoveStartOffset + aRemoveLength - UnmaskedStart(); |
| 1273 | DebugOnly<nsresult> rvIgnored = SetUnmaskRange( |
| 1274 | aRemoveStartOffset, UnmaskedLength() - unmaskedLengthInRemovingRange); |
| 1275 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetUnmaskRange() failed, but ignored" , "NS_SUCCEEDED(rvIgnored)", "./../../../editor/libeditor/TextEditor.cpp" , 1276); } } while (false) |
| 1276 | "TextEditor::SetUnmaskRange() failed, but ignored")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetUnmaskRange() failed, but ignored" , "NS_SUCCEEDED(rvIgnored)", "./../../../editor/libeditor/TextEditor.cpp" , 1276); } } while (false); |
| 1277 | return; |
| 1278 | } |
| 1279 | |
| 1280 | // If removing range includes all unmasked range, collapse it to the |
| 1281 | // remove offset. |
| 1282 | DebugOnly<nsresult> rvIgnored = SetUnmaskRange(aRemoveStartOffset, 0); |
| 1283 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetUnmaskRange() failed, but ignored" , "NS_SUCCEEDED(rvIgnored)", "./../../../editor/libeditor/TextEditor.cpp" , 1284); } } while (false) |
| 1284 | "TextEditor::SetUnmaskRange() failed, but ignored")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetUnmaskRange() failed, but ignored" , "NS_SUCCEEDED(rvIgnored)", "./../../../editor/libeditor/TextEditor.cpp" , 1284); } } while (false); |
| 1285 | return; |
| 1286 | } |
| 1287 | |
| 1288 | if (aRemoveStartOffset < UnmaskedEnd()) { |
| 1289 | // If removing range is in unmasked range, shrink the range. |
| 1290 | if (aRemoveStartOffset + aRemoveLength <= UnmaskedEnd()) { |
| 1291 | DebugOnly<nsresult> rvIgnored = |
| 1292 | SetUnmaskRange(UnmaskedStart(), UnmaskedLength() - aRemoveLength); |
| 1293 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetUnmaskRange() failed, but ignored" , "NS_SUCCEEDED(rvIgnored)", "./../../../editor/libeditor/TextEditor.cpp" , 1294); } } while (false) |
| 1294 | "TextEditor::SetUnmaskRange() failed, but ignored")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetUnmaskRange() failed, but ignored" , "NS_SUCCEEDED(rvIgnored)", "./../../../editor/libeditor/TextEditor.cpp" , 1294); } } while (false); |
| 1295 | return; |
| 1296 | } |
| 1297 | |
| 1298 | // If removing range starts from unmasked range, and ends after it, |
| 1299 | // shrink it. |
| 1300 | DebugOnly<nsresult> rvIgnored = |
| 1301 | SetUnmaskRange(UnmaskedStart(), aRemoveStartOffset - UnmaskedStart()); |
| 1302 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetUnmaskRange() failed, but ignored" , "NS_SUCCEEDED(rvIgnored)", "./../../../editor/libeditor/TextEditor.cpp" , 1303); } } while (false) |
| 1303 | "TextEditor::SetUnmaskRange() failed, but ignored")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rvIgnored )), 1))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetUnmaskRange() failed, but ignored" , "NS_SUCCEEDED(rvIgnored)", "./../../../editor/libeditor/TextEditor.cpp" , 1303); } } while (false); |
| 1304 | return; |
| 1305 | } |
| 1306 | |
| 1307 | // If removing range is after the unmasked range, keep it. |
| 1308 | } |
| 1309 | |
| 1310 | nsresult TextEditor::DidInsertText(uint32_t aNewLength, |
| 1311 | uint32_t aInsertedOffset, |
| 1312 | uint32_t aInsertedLength) { |
| 1313 | MOZ_ASSERT(IsEditActionDataAvailable())do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsEditActionDataAvailable())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(IsEditActionDataAvailable()) )), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsEditActionDataAvailable()" , "./../../../editor/libeditor/TextEditor.cpp", 1313); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "IsEditActionDataAvailable()" ")"); do { MOZ_CrashSequence (__null, 1313); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
| 1314 | |
| 1315 | if (!IsPasswordEditor() || NS_WARN_IF(!mPasswordMaskData)NS_warn_if_impl(!mPasswordMaskData, "!mPasswordMaskData", "./../../../editor/libeditor/TextEditor.cpp" , 1315) || IsAllMasked()) { |
| 1316 | return NS_OK; |
| 1317 | } |
| 1318 | |
| 1319 | if (IsMaskingPassword()) { |
| 1320 | // If we need to mask password, mask all right now. |
| 1321 | nsresult rv = MaskAllCharactersAndNotify(); |
| 1322 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::MaskAllCharacters() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 1323); } } while (false) |
| 1323 | "TextEditor::MaskAllCharacters() failed")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::MaskAllCharacters() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 1323); } } while (false); |
| 1324 | return rv; |
| 1325 | } |
| 1326 | |
| 1327 | if (aInsertedOffset < UnmaskedStart()) { |
| 1328 | // If insertion point is before unmasked range, expand the unmasked range |
| 1329 | // to include the new text. |
| 1330 | nsresult rv = SetUnmaskRangeAndNotify( |
| 1331 | aInsertedOffset, UnmaskedEnd() + aInsertedLength - aInsertedOffset); |
| 1332 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetUnmaskRangeAndNotify() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 1333); } } while (false) |
| 1333 | "TextEditor::SetUnmaskRangeAndNotify() failed")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetUnmaskRangeAndNotify() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 1333); } } while (false); |
| 1334 | return rv; |
| 1335 | } |
| 1336 | |
| 1337 | if (aInsertedOffset <= UnmaskedEnd()) { |
| 1338 | // If insertion point is in unmasked range, unmask new text. |
| 1339 | nsresult rv = SetUnmaskRangeAndNotify(UnmaskedStart(), |
| 1340 | UnmaskedLength() + aInsertedLength); |
| 1341 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetUnmaskRangeAndNotify() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 1342); } } while (false) |
| 1342 | "TextEditor::SetUnmaskRangeAndNotify() failed")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetUnmaskRangeAndNotify() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 1342); } } while (false); |
| 1343 | return rv; |
| 1344 | } |
| 1345 | |
| 1346 | // If insertion point is after unmasked range, extend the unmask range to |
| 1347 | // include the new text. |
| 1348 | nsresult rv = SetUnmaskRangeAndNotify( |
| 1349 | UnmaskedStart(), aInsertedOffset + aInsertedLength - UnmaskedStart()); |
| 1350 | NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetUnmaskRangeAndNotify() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 1351); } } while (false) |
| 1351 | "TextEditor::SetUnmaskRangeAndNotify() failed")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1 ))))) { NS_DebugBreak(NS_DEBUG_WARNING, "TextEditor::SetUnmaskRangeAndNotify() failed" , "NS_SUCCEEDED(rv)", "./../../../editor/libeditor/TextEditor.cpp" , 1351); } } while (false); |
| 1352 | return rv; |
| 1353 | } |
| 1354 | |
| 1355 | } // namespace mozilla |