Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_editor_libeditor3.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/editor/libeditor -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/editor/libeditor -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/editor/libeditor -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/editor/libeditor -I /root/firefox-clang/dom/base -I /root/firefox-clang/dom/html -I /root/firefox-clang/extensions/spellcheck/src -I /root/firefox-clang/layout/generic -I /root/firefox-clang/layout/style -I /root/firefox-clang/layout/tables -I /root/firefox-clang/layout/xul -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/toolkit/components/telemetry -I /root/firefox-clang/xpcom/base -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c++ Unified_cpp_editor_libeditor3.cpp
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
69class nsIOutputStream;
70class nsISupports;
71
72namespace mozilla {
73
74// This logs the important things for the lifecycle of the TextEditor.
75LazyLogModule gTextEditorLog("TextEditor");
76
77static 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
90using namespace dom;
91
92template EditorDOMPoint TextEditor::FindBetterInsertionPoint(
93 const EditorDOMPoint& aPoint) const;
94template EditorRawDOMPoint TextEditor::FindBetterInsertionPoint(
95 const EditorRawDOMPoint& aPoint) const;
96
97TextEditor::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
106TextEditor::~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
114NS_IMPL_CYCLE_COLLECTION_CLASS(TextEditor)TextEditor::cycleCollection TextEditor::_cycleCollectorGlobal
;
115
116NS_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 }
121NS_IMPL_CYCLE_COLLECTION_UNLINK_END(void)tmp; }
122
123NS_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 }
127NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END(void)tmp; return NS_OK; }
128
129NS_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; }
130NS_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
132NS_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
135NS_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
137NS_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
150nsresult 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
167nsresult 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
224nsresult 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
252nsresult 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
284UniquePtr<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
308Result<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
345nsresult 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
438NS_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
459nsresult 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
490nsresult 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
515nsresult 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
541nsresult 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
592already_AddRefed<Element> TextEditor::GetInputEventTargetElement() const {
593 RefPtr<Element> target = Element::FromEventTargetOrNull(mEventTarget);
594 return target.forget();
595}
596
597bool 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
615NS_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
638bool 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
668nsresult 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
747nsresult 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
785nsresult 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
808EventTarget* TextEditor::GetDOMEventTarget() const { return mEventTarget; }
809
810void 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
837nsresult 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
851void 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
885nsresult 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
912nsresult 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
934nsresult 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
955template <typename EditorDOMPointType>
956EditorDOMPointType 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
1011void 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
1066nsresult 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
1175char16_t TextEditor::PasswordMask() {
1176 char16_t ret = LookAndFeel::GetPasswordCharacter();
1177 if (!ret) {
1178 ret = '*';
1179 }
1180 return ret;
1181}
1182
1183MOZ_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
1217NS_IMETHODIMPnsresult TextEditor::GetName(nsACString& aName) {
1218 aName.AssignLiteral("TextEditor");
1219 return NS_OK;
1220}
1221
1222void 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
1294nsresult 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