| File: | root/firefox-clang/obj-x86_64-pc-linux-gnu/editor/libeditor/./../../../editor/libeditor/TextEditor.cpp |
| Warning: | line 695, 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 | // If we're a password editor, we should allow selected text to be copied |
| 650 | // to the clipboard only when selection range is in unmasked range. |
| 651 | if (IsAllMasked() || IsMaskingPassword() || !UnmaskedLength()) { |
| 652 | return false; |
| 653 | } |
| 654 | |
| 655 | // If there are 2 or more ranges, we don't allow to copy/cut for now since |
| 656 | // we need to check whether all ranges are in unmasked range or not. |
| 657 | // Anyway, such operation in password field does not make sense. |
| 658 | if (SelectionRef().RangeCount() > 1) { |
| 659 | return false; |
| 660 | } |
| 661 | |
| 662 | uint32_t selectionStart = 0, selectionEnd = 0; |
| 663 | nsContentUtils::GetSelectionInTextControl(&SelectionRef(), mRootElement, |
| 664 | selectionStart, selectionEnd); |
| 665 | return UnmaskedStart() <= selectionStart && UnmaskedEnd() >= selectionEnd; |
| 666 | } |
| 667 | |
| 668 | nsresult TextEditor::HandlePasteAsQuotation( |
| 669 | AutoEditActionDataSetter& aEditActionData, |
| 670 | nsIClipboard::ClipboardType aClipboardType, DataTransfer* aDataTransfer) { |
| 671 | 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", 672); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aClipboardType == nsIClipboard::kGlobalClipboard || aClipboardType == nsIClipboard::kSelectionClipboard" ")"); do { MOZ_CrashSequence(__null, 672); __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
| 672 | 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", 672); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aClipboardType == nsIClipboard::kGlobalClipboard || aClipboardType == nsIClipboard::kSelectionClipboard" ")"); do { MOZ_CrashSequence(__null, 672); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
| 673 | if (NS_WARN_IF(!GetDocument())NS_warn_if_impl(!GetDocument(), "!GetDocument()", "./../../../editor/libeditor/TextEditor.cpp" , 673)) { |
| 674 | return NS_OK; |
| 675 | } |
| 676 | |
| 677 | // XXX Why don't we dispatch ePaste event here? |
| 678 | |
| 679 | // Get the nsITransferable interface for getting the data from the clipboard |
| 680 | Result<nsCOMPtr<nsITransferable>, nsresult> maybeTransferable = |
| 681 | EditorUtils::CreateTransferableForPlainText(*GetDocument()); |
| 682 | if (maybeTransferable.isErr()) { |
| 683 | NS_WARNING("EditorUtils::CreateTransferableForPlainText() failed")NS_DebugBreak(NS_DEBUG_WARNING, "EditorUtils::CreateTransferableForPlainText() failed" , nullptr, "./../../../editor/libeditor/TextEditor.cpp", 683); |
| 684 | return maybeTransferable.unwrapErr(); |
| 685 | } |
| 686 | nsCOMPtr<nsITransferable> trans(maybeTransferable.unwrap()); |
| 687 | if (!trans) { |
| 688 | NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "EditorUtils::CreateTransferableForPlainText() returned nullptr, but " "ignored", nullptr, "./../../../editor/libeditor/TextEditor.cpp" , 690) |
| 689 | "EditorUtils::CreateTransferableForPlainText() returned nullptr, but "NS_DebugBreak(NS_DEBUG_WARNING, "EditorUtils::CreateTransferableForPlainText() returned nullptr, but " "ignored", nullptr, "./../../../editor/libeditor/TextEditor.cpp" , 690) |
| 690 | "ignored")NS_DebugBreak(NS_DEBUG_WARNING, "EditorUtils::CreateTransferableForPlainText() returned nullptr, but " "ignored", nullptr, "./../../../editor/libeditor/TextEditor.cpp" , 690); |
| 691 | return NS_OK; |
| 692 | } |
| 693 | |
| 694 | // Get the Data from the clipboard |
| 695 | nsresult rv = |
Value stored to 'rv' during its initialization is never read | |
| 696 | GetDataFromDataTransferOrClipboard(aDataTransfer, trans, aClipboardType); |
| 697 | |
| 698 | // Now we ask the transferable for the data |
| 699 | // it still owns the data, we just have a pointer to it. |
| 700 | // If it can't support a "text" output of the data the call will fail |
| 701 | nsCOMPtr<nsISupports> genericDataObj; |
| 702 | nsAutoCString flavor; |
| 703 | rv = trans->GetAnyTransferData(flavor, getter_AddRefs(genericDataObj)); |
| 704 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 705 | NS_WARNING("nsITransferable::GetAnyTransferData() failed")NS_DebugBreak(NS_DEBUG_WARNING, "nsITransferable::GetAnyTransferData() failed" , nullptr, "./../../../editor/libeditor/TextEditor.cpp", 705); |
| 706 | return rv; |
| 707 | } |
| 708 | |
| 709 | if (!flavor.EqualsLiteral(kTextMime"text/plain") && |
| 710 | !flavor.EqualsLiteral(kMozTextInternal"text/x-moz-text-internal") && |
| 711 | !flavor.EqualsLiteral(kURLDataMime"text/x-moz-url-data")) { |
| 712 | return NS_OK; |
| 713 | } |
| 714 | |
| 715 | nsCOMPtr<nsISupportsString> text = do_QueryInterface(genericDataObj); |
| 716 | if (!text) { |
| 717 | return NS_OK; |
| 718 | } |
| 719 | |
| 720 | nsString stuffToPaste; |
| 721 | DebugOnly<nsresult> rvIgnored = text->GetData(stuffToPaste); |
| 722 | 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" , 723); } } while (false) |
| 723 | "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" , 723); } } while (false); |
| 724 | if (stuffToPaste.IsEmpty()) { |
| 725 | return NS_OK; |
| 726 | } |
| 727 | |
| 728 | aEditActionData.SetData(stuffToPaste); |
| 729 | if (!stuffToPaste.IsEmpty()) { |
| 730 | nsContentUtils::PlatformToDOMLineBreaks(stuffToPaste); |
| 731 | } |
| 732 | rv = aEditActionData.MaybeDispatchBeforeInputEvent(); |
| 733 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 734 | 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", 735); } } while (false) |
| 735 | "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", 735); } } while (false); |
| 736 | return rv; |
| 737 | } |
| 738 | |
| 739 | AutoPlaceholderBatch treatAsOneTransaction( |
| 740 | *this, ScrollSelectionIntoView::Yes, __FUNCTION__); |
| 741 | rv = InsertWithQuotationsAsSubAction(stuffToPaste); |
| 742 | 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" , 743); } } while (false) |
| 743 | "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" , 743); } } while (false); |
| 744 | return rv; |
| 745 | } |
| 746 | |
| 747 | nsresult TextEditor::InsertWithQuotationsAsSubAction( |
| 748 | const nsAString& aQuotedText) { |
| 749 | 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", 749); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "IsEditActionDataAvailable()" ")"); do { MOZ_CrashSequence (__null, 749); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
| 750 | |
| 751 | if (IsReadonly()) { |
| 752 | return NS_OK; |
| 753 | } |
| 754 | |
| 755 | // Let the citer quote it for us: |
| 756 | nsString quotedStuff; |
| 757 | InternetCiter::GetCiteString(aQuotedText, quotedStuff); |
| 758 | |
| 759 | // It's best to put a blank line after the quoted text so that mails |
| 760 | // written without thinking won't be so ugly. |
| 761 | if (!aQuotedText.IsEmpty() && (aQuotedText.Last() != char16_t('\n'))) { |
| 762 | quotedStuff.Append(char16_t('\n')); |
| 763 | } |
| 764 | |
| 765 | IgnoredErrorResult ignoredError; |
| 766 | AutoEditSubActionNotifier startToHandleEditSubAction( |
| 767 | *this, EditSubAction::eInsertText, nsIEditor::eNext, ignoredError); |
| 768 | 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" , 768)) { |
| 769 | return ignoredError.StealNSResult(); |
| 770 | } |
| 771 | NS_WARNING_ASSERTION(do { if (!(!ignoredError.Failed())) { NS_DebugBreak(NS_DEBUG_WARNING , "TextEditor::OnStartToHandleTopLevelEditSubAction() failed, but ignored" , "!ignoredError.Failed()", "./../../../editor/libeditor/TextEditor.cpp" , 773); } } while (false) |
| 772 | !ignoredError.Failed(),do { if (!(!ignoredError.Failed())) { NS_DebugBreak(NS_DEBUG_WARNING , "TextEditor::OnStartToHandleTopLevelEditSubAction() failed, but ignored" , "!ignoredError.Failed()", "./../../../editor/libeditor/TextEditor.cpp" , 773); } } while (false) |
| 773 | "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" , 773); } } while (false); |
| 774 | |
| 775 | // XXX Do we need to support paste-as-quotation in password editor (and |
| 776 | // also in single line editor)? |
| 777 | MaybeDoAutoPasswordMasking(); |
| 778 | |
| 779 | nsresult rv = InsertTextAsSubAction(quotedStuff, InsertTextFor::NormalText); |
| 780 | 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" , 781); } } while (false) |
| 781 | "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" , 781); } } while (false); |
| 782 | return rv; |
| 783 | } |
| 784 | |
| 785 | nsresult TextEditor::SelectEntireDocument() { |
| 786 | 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", 786); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "IsEditActionDataAvailable()" ")"); do { MOZ_CrashSequence (__null, 786); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
| 787 | |
| 788 | if (NS_WARN_IF(!mInitSucceeded)NS_warn_if_impl(!mInitSucceeded, "!mInitSucceeded", "./../../../editor/libeditor/TextEditor.cpp" , 788)) { |
| 789 | return NS_ERROR_NOT_INITIALIZED; |
| 790 | } |
| 791 | |
| 792 | RefPtr<Element> anonymousDivElement = GetRoot(); |
| 793 | if (NS_WARN_IF(!anonymousDivElement)NS_warn_if_impl(!anonymousDivElement, "!anonymousDivElement", "./../../../editor/libeditor/TextEditor.cpp", 793)) { |
| 794 | return NS_ERROR_NOT_INITIALIZED; |
| 795 | } |
| 796 | |
| 797 | RefPtr<Text> text = |
| 798 | Text::FromNodeOrNull(anonymousDivElement->GetFirstChild()); |
| 799 | 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" , 799); AnnotateMozCrashReason("MOZ_ASSERT" "(" "text" ")"); do { MOZ_CrashSequence(__null, 799); __attribute__((nomerge)) :: abort(); } while (false); } } while (false); |
| 800 | |
| 801 | 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(); }) |
| 802 | *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(); }) |
| 803 | 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(); }); |
| 804 | |
| 805 | return NS_OK; |
| 806 | } |
| 807 | |
| 808 | EventTarget* TextEditor::GetDOMEventTarget() const { return mEventTarget; } |
| 809 | |
| 810 | void TextEditor::ReinitializeSelection(Element& aElement) { |
| 811 | 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) |
| 812 | ("%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) |
| 813 | 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); |
| 814 | |
| 815 | if (MOZ_UNLIKELY(Destroyed())(__builtin_expect(!!(Destroyed()), 0))) { |
| 816 | LogOrWarn(this, gTextEditorLog, LogLevel::Error, "Destroyed() failed"); |
| 817 | return; |
| 818 | } |
| 819 | |
| 820 | AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing); |
| 821 | if (MOZ_UNLIKELY(!editActionData.CanHandle())(__builtin_expect(!!(!editActionData.CanHandle()), 0))) { |
| 822 | LogOrWarn(this, gTextEditorLog, LogLevel::Error, |
| 823 | "AutoEditActionDataSetter::CanHandle() failed"); |
| 824 | return; |
| 825 | } |
| 826 | |
| 827 | // We don't need to flush pending notifications here and we don't need to |
| 828 | // handle spellcheck at first focus. Therefore, we don't need to call |
| 829 | // `TextEditor::OnFocus` here. |
| 830 | EditorBase::OnFocus(aElement); |
| 831 | |
| 832 | // If previous focused editor turn on spellcheck and this editor doesn't |
| 833 | // turn on it, spellcheck state is mismatched. So we need to re-sync it. |
| 834 | SyncRealTimeSpell(); |
| 835 | } |
| 836 | |
| 837 | nsresult TextEditor::OnFocus(const nsINode& aOriginalEventTargetNode) { |
| 838 | 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) |
| 839 | ("%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) |
| 840 | 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); |
| 841 | |
| 842 | AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing); |
| 843 | if (MOZ_UNLIKELY(!editActionData.CanHandle())(__builtin_expect(!!(!editActionData.CanHandle()), 0))) { |
| 844 | LogOrWarn(this, gTextEditorLog, LogLevel::Error, |
| 845 | "AutoEditActionDataSetter::CanHandle() failed"); |
| 846 | return NS_ERROR_FAILURE; |
| 847 | } |
| 848 | return EditorBase::OnFocus(aOriginalEventTargetNode); |
| 849 | } |
| 850 | |
| 851 | void TextEditor::PostHandleFocusEvent(const nsINode& aFocusEventTargetNode) { |
| 852 | 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) |
| 853 | ("%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) |
| 854 | "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) |
| 855 | 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) |
| 856 | 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); |
| 857 | |
| 858 | AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing); |
| 859 | if (MOZ_UNLIKELY(!editActionData.CanHandle())(__builtin_expect(!!(!editActionData.CanHandle()), 0))) { |
| 860 | LogOrWarn(this, gTextEditorLog, LogLevel::Error, |
| 861 | "AutoEditActionDataSetter::CanHandle() failed"); |
| 862 | return; |
| 863 | } |
| 864 | |
| 865 | // Spell check a textarea the first time that it is focused. |
| 866 | nsresult rv = FlushPendingSpellCheck(); |
| 867 | if (rv == NS_ERROR_EDITOR_DESTROYED) [[unlikely]] { |
| 868 | LogOrWarn(this, gTextEditorLog, LogLevel::Error, |
| 869 | "EditorBase::FlushPendingSpellCheck() failed"); |
| 870 | return; |
| 871 | } |
| 872 | 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" , 874); } } while (false) |
| 873 | 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" , 874); } } while (false) |
| 874 | "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" , 874); } } while (false); |
| 875 | if (!CanKeepHandlingFocusEvent(aFocusEventTargetNode)) [[unlikely]] { |
| 876 | 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) |
| 877 | ("%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) |
| 878 | "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) |
| 879 | 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); |
| 880 | return; |
| 881 | } |
| 882 | EditorBase::PostHandleFocusEvent(aFocusEventTargetNode); |
| 883 | } |
| 884 | |
| 885 | nsresult TextEditor::OnBlur(const EventTarget* aEventTarget) { |
| 886 | 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) |
| 887 | ("%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) |
| 888 | 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); |
| 889 | |
| 890 | // check if something else is focused. If another element is focused, then |
| 891 | // we should not change the selection. If another element already has focus, |
| 892 | // we should not maintain the selection because we may not have the rights |
| 893 | // doing it. |
| 894 | if ([[maybe_unused]] Element* const focusedElement = |
| 895 | nsFocusManager::GetFocusedElementStatic()) { |
| 896 | 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) |
| 897 | ("%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) |
| 898 | "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) |
| 899 | 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); |
| 900 | return NS_OK; |
| 901 | } |
| 902 | |
| 903 | nsresult rv = FinalizeSelection(); |
| 904 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 905 | LogOrWarn(this, gTextEditorLog, LogLevel::Error, |
| 906 | "EditorBase::FinalizeSelection() failed"); |
| 907 | return rv; |
| 908 | } |
| 909 | return NS_OK; |
| 910 | } |
| 911 | |
| 912 | nsresult TextEditor::SetAttributeOrEquivalent(Element* aElement, |
| 913 | nsAtom* aAttribute, |
| 914 | const nsAString& aValue, |
| 915 | bool aSuppressTransaction) { |
| 916 | if (NS_WARN_IF(!aElement)NS_warn_if_impl(!aElement, "!aElement", "./../../../editor/libeditor/TextEditor.cpp" , 916) || NS_WARN_IF(!aAttribute)NS_warn_if_impl(!aAttribute, "!aAttribute", "./../../../editor/libeditor/TextEditor.cpp" , 916)) { |
| 917 | return NS_ERROR_INVALID_ARG; |
| 918 | } |
| 919 | |
| 920 | AutoEditActionDataSetter editActionData(*this, EditAction::eSetAttribute); |
| 921 | nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent(); |
| 922 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 923 | 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" , 924); } } while (false) |
| 924 | "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" , 924); } } while (false); |
| 925 | return EditorBase::ToGenericNSResult(rv); |
| 926 | } |
| 927 | |
| 928 | rv = SetAttributeWithTransaction(*aElement, *aAttribute, aValue); |
| 929 | 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" , 930); } } while (false) |
| 930 | "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" , 930); } } while (false); |
| 931 | return EditorBase::ToGenericNSResult(rv); |
| 932 | } |
| 933 | |
| 934 | nsresult TextEditor::RemoveAttributeOrEquivalent(Element* aElement, |
| 935 | nsAtom* aAttribute, |
| 936 | bool aSuppressTransaction) { |
| 937 | if (NS_WARN_IF(!aElement)NS_warn_if_impl(!aElement, "!aElement", "./../../../editor/libeditor/TextEditor.cpp" , 937) || NS_WARN_IF(!aAttribute)NS_warn_if_impl(!aAttribute, "!aAttribute", "./../../../editor/libeditor/TextEditor.cpp" , 937)) { |
| 938 | return NS_ERROR_INVALID_ARG; |
| 939 | } |
| 940 | |
| 941 | AutoEditActionDataSetter editActionData(*this, EditAction::eRemoveAttribute); |
| 942 | nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent(); |
| 943 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 944 | 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" , 945); } } while (false) |
| 945 | "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" , 945); } } while (false); |
| 946 | return EditorBase::ToGenericNSResult(rv); |
| 947 | } |
| 948 | |
| 949 | rv = RemoveAttributeWithTransaction(*aElement, *aAttribute); |
| 950 | 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" , 951); } } while (false) |
| 951 | "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" , 951); } } while (false); |
| 952 | return EditorBase::ToGenericNSResult(rv); |
| 953 | } |
| 954 | |
| 955 | template <typename EditorDOMPointType> |
| 956 | EditorDOMPointType TextEditor::FindBetterInsertionPoint( |
| 957 | const EditorDOMPointType& aPoint) const { |
| 958 | if (MOZ_UNLIKELY(NS_WARN_IF(!aPoint.IsInContentNode()))(__builtin_expect(!!(NS_warn_if_impl(!aPoint.IsInContentNode( ), "!aPoint.IsInContentNode()", "./../../../editor/libeditor/TextEditor.cpp" , 958)), 0))) { |
| 959 | return aPoint; |
| 960 | } |
| 961 | |
| 962 | 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", 962); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "aPoint.IsSetAndValid()" ")"); do { MOZ_CrashSequence (__null, 962); __attribute__((nomerge)) ::abort(); } while (false ); } } while (false); |
| 963 | |
| 964 | Element* const anonymousDivElement = GetRoot(); |
| 965 | if (aPoint.GetContainer() == anonymousDivElement) { |
| 966 | // In some cases, aPoint points start of the anonymous <div>. To avoid |
| 967 | // injecting unneeded text nodes, we first look to see if we have one |
| 968 | // available. In that case, we'll just adjust node and offset accordingly. |
| 969 | if (aPoint.IsStartOfContainer()) { |
| 970 | if (aPoint.GetContainer()->HasChildren() && |
| 971 | aPoint.GetContainer()->GetFirstChild()->IsText()) { |
| 972 | return EditorDOMPointType(aPoint.GetContainer()->GetFirstChild(), 0u); |
| 973 | } |
| 974 | } |
| 975 | // In some other cases, aPoint points the terminating padding <br> element |
| 976 | // for empty last line in the anonymous <div>. In that case, we'll adjust |
| 977 | // aInOutNode and aInOutOffset to the preceding text node, if any. |
| 978 | else { |
| 979 | nsIContent* child = aPoint.GetContainer()->GetLastChild(); |
| 980 | while (child) { |
| 981 | if (child->IsText()) { |
| 982 | return EditorDOMPointType::AtEndOf(*child); |
| 983 | } |
| 984 | child = child->GetPreviousSibling(); |
| 985 | } |
| 986 | } |
| 987 | } |
| 988 | |
| 989 | // Sometimes, aPoint points the padding <br> element. In that case, we'll |
| 990 | // adjust the insertion point to the previous text node, if one exists, or to |
| 991 | // the parent anonymous DIV. |
| 992 | if (EditorUtils::IsPaddingBRElementForEmptyLastLine( |
| 993 | *aPoint.template ContainerAs<nsIContent>()) && |
| 994 | aPoint.IsStartOfContainer()) { |
| 995 | nsIContent* previousSibling = aPoint.GetContainer()->GetPreviousSibling(); |
| 996 | if (previousSibling && previousSibling->IsText()) { |
| 997 | return EditorDOMPointType::AtEndOf(*previousSibling); |
| 998 | } |
| 999 | |
| 1000 | nsINode* parentOfContainer = aPoint.GetContainerParent(); |
| 1001 | if (parentOfContainer && parentOfContainer == anonymousDivElement) { |
| 1002 | return EditorDOMPointType(parentOfContainer, |
| 1003 | aPoint.template ContainerAs<nsIContent>(), 0u); |
| 1004 | } |
| 1005 | } |
| 1006 | |
| 1007 | return aPoint; |
| 1008 | } |
| 1009 | |
| 1010 | // static |
| 1011 | void TextEditor::MaskString(nsString& aString, const Text& aTextNode, |
| 1012 | uint32_t aStartOffsetInString, |
| 1013 | uint32_t aStartOffsetInText) { |
| 1014 | 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" , 1014); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTextNode.HasFlag(NS_MAYBE_MASKED)" ")"); do { MOZ_CrashSequence(__null, 1014); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
| 1015 | 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" , 1015); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStartOffsetInString == 0 || aStartOffsetInText == 0" ")"); do { MOZ_CrashSequence(__null, 1015); __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
| 1016 | |
| 1017 | uint32_t unmaskStart = UINT32_MAX(4294967295U), unmaskLength = 0; |
| 1018 | const TextEditor* const textEditor = |
| 1019 | nsContentUtils::GetExtantTextEditorFromAnonymousNode(&aTextNode); |
| 1020 | if (textEditor && textEditor->UnmaskedLength() > 0) { |
| 1021 | unmaskStart = textEditor->UnmaskedStart(); |
| 1022 | unmaskLength = textEditor->UnmaskedLength(); |
| 1023 | // If text is copied from after unmasked range, we can treat this case |
| 1024 | // as mask all. |
| 1025 | if (aStartOffsetInText >= unmaskStart + unmaskLength) { |
| 1026 | unmaskLength = 0; |
| 1027 | unmaskStart = UINT32_MAX(4294967295U); |
| 1028 | } else { |
| 1029 | // If text is copied from middle of unmasked range, reduce the length |
| 1030 | // and adjust start offset. |
| 1031 | if (aStartOffsetInText > unmaskStart) { |
| 1032 | unmaskLength = unmaskStart + unmaskLength - aStartOffsetInText; |
| 1033 | unmaskStart = 0; |
| 1034 | } |
| 1035 | // If text is copied from before start of unmasked range, just adjust |
| 1036 | // the start offset. |
| 1037 | else { |
| 1038 | unmaskStart -= aStartOffsetInText; |
| 1039 | } |
| 1040 | // Make the range is in the string. |
| 1041 | unmaskStart += aStartOffsetInString; |
| 1042 | } |
| 1043 | } |
| 1044 | |
| 1045 | const char16_t kPasswordMask = TextEditor::PasswordMask(); |
| 1046 | for (uint32_t i = aStartOffsetInString; i < aString.Length(); ++i) { |
| 1047 | bool isSurrogatePair = mozilla::IsHighSurrogate(aString.CharAt(i)) && |
| 1048 | i < aString.Length() - 1 && |
| 1049 | mozilla::IsLowSurrogate(aString.CharAt(i + 1)); |
| 1050 | if (i < unmaskStart || i >= unmaskStart + unmaskLength) { |
| 1051 | if (isSurrogatePair) { |
| 1052 | aString.SetCharAt(kPasswordMask, i); |
| 1053 | aString.SetCharAt(kPasswordMask, i + 1); |
| 1054 | } else { |
| 1055 | aString.SetCharAt(kPasswordMask, i); |
| 1056 | } |
| 1057 | } |
| 1058 | |
| 1059 | // Skip the following low surrogate. |
| 1060 | if (isSurrogatePair) { |
| 1061 | ++i; |
| 1062 | } |
| 1063 | } |
| 1064 | } |
| 1065 | |
| 1066 | nsresult TextEditor::SetUnmaskRangeInternal(uint32_t aStart, uint32_t aLength, |
| 1067 | uint32_t aTimeout, bool aNotify, |
| 1068 | bool aForceStartMasking) { |
| 1069 | if (mPasswordMaskData) { |
| 1070 | mPasswordMaskData->mIsMaskingPassword = aForceStartMasking || aTimeout != 0; |
| 1071 | |
| 1072 | // We cannot manage multiple unmasked ranges so that shrink the previous |
| 1073 | // range first. |
| 1074 | if (!IsAllMasked()) { |
| 1075 | mPasswordMaskData->mUnmaskedLength = 0; |
| 1076 | mPasswordMaskData->CancelTimer(PasswordMaskData::ReleaseTimer::No); |
| 1077 | } |
| 1078 | } |
| 1079 | |
| 1080 | // If we're not a password editor, return error since this call does not |
| 1081 | // make sense. |
| 1082 | if (!IsPasswordEditor() || NS_WARN_IF(!mPasswordMaskData)NS_warn_if_impl(!mPasswordMaskData, "!mPasswordMaskData", "./../../../editor/libeditor/TextEditor.cpp" , 1082)) { |
| 1083 | mPasswordMaskData->CancelTimer(PasswordMaskData::ReleaseTimer::Yes); |
| 1084 | return NS_ERROR_NOT_AVAILABLE; |
| 1085 | } |
| 1086 | |
| 1087 | if (NS_WARN_IF(!GetRoot())NS_warn_if_impl(!GetRoot(), "!GetRoot()", "./../../../editor/libeditor/TextEditor.cpp" , 1087)) { |
| 1088 | return NS_ERROR_NOT_INITIALIZED; |
| 1089 | } |
| 1090 | Text* const text = GetTextNode(); |
| 1091 | if (!text || !text->Length()) { |
| 1092 | // There is no anonymous text node in the editor. |
| 1093 | return aStart > 0 && aStart != UINT32_MAX(4294967295U) ? NS_ERROR_INVALID_ARG : NS_OK; |
| 1094 | } |
| 1095 | |
| 1096 | if (aStart < UINT32_MAX(4294967295U)) { |
| 1097 | uint32_t valueLength = text->Length(); |
| 1098 | if (aStart >= valueLength) { |
| 1099 | return NS_ERROR_INVALID_ARG; // There is no character can be masked. |
| 1100 | } |
| 1101 | // If aStart is middle of a surrogate pair, expand it to include the |
| 1102 | // preceding high surrogate because the caller may want to show a |
| 1103 | // character before the character at `aStart + 1`. |
| 1104 | const CharacterDataBuffer& characterDataBuffer = text->DataBuffer(); |
| 1105 | if (characterDataBuffer.IsLowSurrogateFollowingHighSurrogateAt(aStart)) { |
| 1106 | mPasswordMaskData->mUnmaskedStart = aStart - 1; |
| 1107 | // If caller collapses the range, keep it. Otherwise, expand the length. |
| 1108 | if (aLength > 0) { |
| 1109 | ++aLength; |
| 1110 | } |
| 1111 | } else { |
| 1112 | mPasswordMaskData->mUnmaskedStart = aStart; |
| 1113 | } |
| 1114 | mPasswordMaskData->mUnmaskedLength = |
| 1115 | std::min(valueLength - UnmaskedStart(), aLength); |
| 1116 | // If unmasked end is middle of a surrogate pair, expand it to include |
| 1117 | // the following low surrogate because the caller may want to show a |
| 1118 | // character after the character at `aStart + aLength`. |
| 1119 | if (UnmaskedEnd() < valueLength && |
| 1120 | characterDataBuffer.IsLowSurrogateFollowingHighSurrogateAt( |
| 1121 | UnmaskedEnd())) { |
| 1122 | mPasswordMaskData->mUnmaskedLength++; |
| 1123 | } |
| 1124 | // If it's first time to mask the unmasking characters with timer, create |
| 1125 | // the timer now. Then, we'll keep using it for saving the creation cost. |
| 1126 | if (!HasAutoMaskingTimer() && aLength && aTimeout && UnmaskedLength()) { |
| 1127 | mPasswordMaskData->mTimer = NS_NewTimer(); |
| 1128 | } |
| 1129 | } else { |
| 1130 | if (NS_WARN_IF(aLength != 0)NS_warn_if_impl(aLength != 0, "aLength != 0", "./../../../editor/libeditor/TextEditor.cpp" , 1130)) { |
| 1131 | return NS_ERROR_INVALID_ARG; |
| 1132 | } |
| 1133 | mPasswordMaskData->MaskAll(); |
| 1134 | } |
| 1135 | |
| 1136 | // Notify nsTextFrame of this update if the caller wants this to do it. |
| 1137 | // Only in this case, script may run. |
| 1138 | if (aNotify) { |
| 1139 | 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", 1139); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "IsEditActionDataAvailable()" ")"); do { MOZ_CrashSequence (__null, 1139); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
| 1140 | |
| 1141 | RefPtr<Document> document = GetDocument(); |
| 1142 | if (NS_WARN_IF(!document)NS_warn_if_impl(!document, "!document", "./../../../editor/libeditor/TextEditor.cpp" , 1142)) { |
| 1143 | return NS_ERROR_NOT_INITIALIZED; |
| 1144 | } |
| 1145 | // Notify nsTextFrame of masking range change. |
| 1146 | if (RefPtr<PresShell> presShell = document->GetObservingPresShell()) { |
| 1147 | nsAutoScriptBlocker blockRunningScript; |
| 1148 | uint32_t valueLength = text->Length(); |
| 1149 | CharacterDataChangeInfo changeInfo = {false, 0, valueLength, valueLength}; |
| 1150 | presShell->CharacterDataChanged(text, changeInfo); |
| 1151 | } |
| 1152 | |
| 1153 | // Scroll caret into the view since masking or unmasking character may |
| 1154 | // move caret to outside of the view. |
| 1155 | nsresult rv = ScrollSelectionFocusIntoView(); |
| 1156 | if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { |
| 1157 | NS_WARNING("EditorBase::ScrollSelectionFocusIntoView() failed")NS_DebugBreak(NS_DEBUG_WARNING, "EditorBase::ScrollSelectionFocusIntoView() failed" , nullptr, "./../../../editor/libeditor/TextEditor.cpp", 1157 ); |
| 1158 | return rv; |
| 1159 | } |
| 1160 | } |
| 1161 | |
| 1162 | if (!IsAllMasked() && aTimeout != 0) { |
| 1163 | // Initialize the timer to mask the range automatically. |
| 1164 | 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", 1164); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "HasAutoMaskingTimer()" ")"); do { MOZ_CrashSequence (__null, 1164); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
| 1165 | DebugOnly<nsresult> rvIgnored = mPasswordMaskData->mTimer->InitWithCallback( |
| 1166 | this, aTimeout, nsITimer::TYPE_ONE_SHOT); |
| 1167 | 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" , 1168); } } while (false) |
| 1168 | "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" , 1168); } } while (false); |
| 1169 | } |
| 1170 | |
| 1171 | return NS_OK; |
| 1172 | } |
| 1173 | |
| 1174 | // static |
| 1175 | char16_t TextEditor::PasswordMask() { |
| 1176 | char16_t ret = LookAndFeel::GetPasswordCharacter(); |
| 1177 | if (!ret) { |
| 1178 | ret = '*'; |
| 1179 | } |
| 1180 | return ret; |
| 1181 | } |
| 1182 | |
| 1183 | MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMPnsresult TextEditor::Notify(nsITimer* aTimer) { |
| 1184 | // Check whether our text editor's password flag was changed before this |
| 1185 | // "hide password character" timer actually fires. |
| 1186 | if (!IsPasswordEditor() || NS_WARN_IF(!mPasswordMaskData)NS_warn_if_impl(!mPasswordMaskData, "!mPasswordMaskData", "./../../../editor/libeditor/TextEditor.cpp" , 1186)) { |
| 1187 | return NS_OK; |
| 1188 | } |
| 1189 | |
| 1190 | if (IsAllMasked()) { |
| 1191 | return NS_OK; |
| 1192 | } |
| 1193 | |
| 1194 | AutoEditActionDataSetter editActionData(*this, EditAction::eHidePassword); |
| 1195 | if (NS_WARN_IF(!editActionData.CanHandle())NS_warn_if_impl(!editActionData.CanHandle(), "!editActionData.CanHandle()" , "./../../../editor/libeditor/TextEditor.cpp", 1195)) { |
| 1196 | return NS_ERROR_NOT_INITIALIZED; |
| 1197 | } |
| 1198 | |
| 1199 | // Mask all characters. |
| 1200 | nsresult rv = MaskAllCharactersAndNotify(); |
| 1201 | 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" , 1202); } } while (false) |
| 1202 | "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" , 1202); } } while (false); |
| 1203 | |
| 1204 | if (StaticPrefs::editor_password_testing_mask_delay()) { |
| 1205 | if (RefPtr<Element> target = GetInputEventTargetElement()) { |
| 1206 | DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchTrustedEvent( |
| 1207 | target, u"MozLastInputMasked"_ns, CanBubble::eYes, Cancelable::eNo); |
| 1208 | 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", 1210); } } while (false) |
| 1209 | "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", 1210); } } while (false) |
| 1210 | "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", 1210); } } while (false); |
| 1211 | } |
| 1212 | } |
| 1213 | |
| 1214 | return EditorBase::ToGenericNSResult(rv); |
| 1215 | } |
| 1216 | |
| 1217 | NS_IMETHODIMPnsresult TextEditor::GetName(nsACString& aName) { |
| 1218 | aName.AssignLiteral("TextEditor"); |
| 1219 | return NS_OK; |
| 1220 | } |
| 1221 | |
| 1222 | void TextEditor::WillDeleteText(uint32_t aCurrentLength, |
| 1223 | uint32_t aRemoveStartOffset, |
| 1224 | uint32_t aRemoveLength) { |
| 1225 | 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", 1225); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "IsEditActionDataAvailable()" ")"); do { MOZ_CrashSequence (__null, 1225); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
| 1226 | |
| 1227 | if (!IsPasswordEditor() || NS_WARN_IF(!mPasswordMaskData)NS_warn_if_impl(!mPasswordMaskData, "!mPasswordMaskData", "./../../../editor/libeditor/TextEditor.cpp" , 1227) || IsAllMasked()) { |
| 1228 | return; |
| 1229 | } |
| 1230 | |
| 1231 | // Adjust unmasked range before deletion since DOM mutation may cause |
| 1232 | // layout referring the range in old text. |
| 1233 | |
| 1234 | // If we need to mask automatically, mask all now. |
| 1235 | if (IsMaskingPassword()) { |
| 1236 | DebugOnly<nsresult> rvIgnored = MaskAllCharacters(); |
| 1237 | 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" , 1238); } } while (false) |
| 1238 | "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" , 1238); } } while (false); |
| 1239 | return; |
| 1240 | } |
| 1241 | |
| 1242 | if (aRemoveStartOffset < UnmaskedStart()) { |
| 1243 | // If removing range is before the unmasked range, move it. |
| 1244 | if (aRemoveStartOffset + aRemoveLength <= UnmaskedStart()) { |
| 1245 | DebugOnly<nsresult> rvIgnored = |
| 1246 | SetUnmaskRange(UnmaskedStart() - aRemoveLength, UnmaskedLength()); |
| 1247 | 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" , 1248); } } while (false) |
| 1248 | "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" , 1248); } } while (false); |
| 1249 | return; |
| 1250 | } |
| 1251 | |
| 1252 | // If removing range starts before unmasked range, and ends in unmasked |
| 1253 | // range, move and shrink the range. |
| 1254 | if (aRemoveStartOffset + aRemoveLength < UnmaskedEnd()) { |
| 1255 | uint32_t unmaskedLengthInRemovingRange = |
| 1256 | aRemoveStartOffset + aRemoveLength - UnmaskedStart(); |
| 1257 | DebugOnly<nsresult> rvIgnored = SetUnmaskRange( |
| 1258 | aRemoveStartOffset, UnmaskedLength() - unmaskedLengthInRemovingRange); |
| 1259 | 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" , 1260); } } while (false) |
| 1260 | "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" , 1260); } } while (false); |
| 1261 | return; |
| 1262 | } |
| 1263 | |
| 1264 | // If removing range includes all unmasked range, collapse it to the |
| 1265 | // remove offset. |
| 1266 | DebugOnly<nsresult> rvIgnored = SetUnmaskRange(aRemoveStartOffset, 0); |
| 1267 | 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" , 1268); } } while (false) |
| 1268 | "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" , 1268); } } while (false); |
| 1269 | return; |
| 1270 | } |
| 1271 | |
| 1272 | if (aRemoveStartOffset < UnmaskedEnd()) { |
| 1273 | // If removing range is in unmasked range, shrink the range. |
| 1274 | if (aRemoveStartOffset + aRemoveLength <= UnmaskedEnd()) { |
| 1275 | DebugOnly<nsresult> rvIgnored = |
| 1276 | SetUnmaskRange(UnmaskedStart(), UnmaskedLength() - aRemoveLength); |
| 1277 | 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" , 1278); } } while (false) |
| 1278 | "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" , 1278); } } while (false); |
| 1279 | return; |
| 1280 | } |
| 1281 | |
| 1282 | // If removing range starts from unmasked range, and ends after it, |
| 1283 | // shrink it. |
| 1284 | DebugOnly<nsresult> rvIgnored = |
| 1285 | SetUnmaskRange(UnmaskedStart(), aRemoveStartOffset - UnmaskedStart()); |
| 1286 | 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" , 1287); } } while (false) |
| 1287 | "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" , 1287); } } while (false); |
| 1288 | return; |
| 1289 | } |
| 1290 | |
| 1291 | // If removing range is after the unmasked range, keep it. |
| 1292 | } |
| 1293 | |
| 1294 | nsresult TextEditor::DidInsertText(uint32_t aNewLength, |
| 1295 | uint32_t aInsertedOffset, |
| 1296 | uint32_t aInsertedLength) { |
| 1297 | 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", 1297); AnnotateMozCrashReason ("MOZ_ASSERT" "(" "IsEditActionDataAvailable()" ")"); do { MOZ_CrashSequence (__null, 1297); __attribute__((nomerge)) ::abort(); } while ( false); } } while (false); |
| 1298 | |
| 1299 | if (!IsPasswordEditor() || NS_WARN_IF(!mPasswordMaskData)NS_warn_if_impl(!mPasswordMaskData, "!mPasswordMaskData", "./../../../editor/libeditor/TextEditor.cpp" , 1299) || IsAllMasked()) { |
| 1300 | return NS_OK; |
| 1301 | } |
| 1302 | |
| 1303 | if (IsMaskingPassword()) { |
| 1304 | // If we need to mask password, mask all right now. |
| 1305 | nsresult rv = MaskAllCharactersAndNotify(); |
| 1306 | 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" , 1307); } } while (false) |
| 1307 | "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" , 1307); } } while (false); |
| 1308 | return rv; |
| 1309 | } |
| 1310 | |
| 1311 | if (aInsertedOffset < UnmaskedStart()) { |
| 1312 | // If insertion point is before unmasked range, expand the unmasked range |
| 1313 | // to include the new text. |
| 1314 | nsresult rv = SetUnmaskRangeAndNotify( |
| 1315 | aInsertedOffset, UnmaskedEnd() + aInsertedLength - aInsertedOffset); |
| 1316 | 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" , 1317); } } while (false) |
| 1317 | "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" , 1317); } } while (false); |
| 1318 | return rv; |
| 1319 | } |
| 1320 | |
| 1321 | if (aInsertedOffset <= UnmaskedEnd()) { |
| 1322 | // If insertion point is in unmasked range, unmask new text. |
| 1323 | nsresult rv = SetUnmaskRangeAndNotify(UnmaskedStart(), |
| 1324 | UnmaskedLength() + aInsertedLength); |
| 1325 | 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" , 1326); } } while (false) |
| 1326 | "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" , 1326); } } while (false); |
| 1327 | return rv; |
| 1328 | } |
| 1329 | |
| 1330 | // If insertion point is after unmasked range, extend the unmask range to |
| 1331 | // include the new text. |
| 1332 | nsresult rv = SetUnmaskRangeAndNotify( |
| 1333 | UnmaskedStart(), aInsertedOffset + aInsertedLength - UnmaskedStart()); |
| 1334 | 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" , 1335); } } while (false) |
| 1335 | "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" , 1335); } } while (false); |
| 1336 | return rv; |
| 1337 | } |
| 1338 | |
| 1339 | } // namespace mozilla |