Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/editor/libeditor/./../../../editor/libeditor/TextEditor.cpp
Warning:line 703, column 12
Value stored to 'rv' during its initialization is never read

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