Bug Summary

File:root/firefox-clang/dom/base/nsContentUtils.cpp
Warning:line 12419, column 9
Called C++ object pointer is null

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 nsContentUtils.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/dom/base -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/base -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/dom/base -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/base -I /root/firefox-clang/dom/battery -I /root/firefox-clang/dom/events -I /root/firefox-clang/dom/media -I /root/firefox-clang/dom/network -I /root/firefox-clang/caps -I /root/firefox-clang/docshell/base -I /root/firefox-clang/dom/base -I /root/firefox-clang/dom/file -I /root/firefox-clang/dom/geolocation -I /root/firefox-clang/dom/html -I /root/firefox-clang/dom/ipc -I /root/firefox-clang/dom/storage -I /root/firefox-clang/dom/svg -I /root/firefox-clang/dom/xml -I /root/firefox-clang/dom/xslt/xpath -I /root/firefox-clang/dom/xul -I /root/firefox-clang/extensions/spellcheck/src -I /root/firefox-clang/gfx/2d -I /root/firefox-clang/image -I /root/firefox-clang/js/xpconnect/loader -I /root/firefox-clang/js/xpconnect/src -I /root/firefox-clang/js/xpconnect/wrappers -I /root/firefox-clang/layout/base -I /root/firefox-clang/layout/forms -I /root/firefox-clang/layout/generic -I /root/firefox-clang/layout/style -I /root/firefox-clang/layout/xul -I /root/firefox-clang/netwerk/base -I /root/firefox-clang/netwerk/protocol/http -I /root/firefox-clang/netwerk/url-classifier -I /root/firefox-clang/parser/htmlparser -I /root/firefox-clang/security/manager/ssl -I /root/firefox-clang/third_party/xsimd/include -I /root/firefox-clang/widget -I /root/firefox-clang/xpcom/build -I /root/firefox-clang/xpcom/ds -I /root/firefox-clang/netwerk/sctp/datachannel -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 -I /usr/include/gtk-3.0/unix-print -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cloudproviders -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/fribidi -I /usr/include/harfbuzz -I /usr/include/atk-1.0 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/glycin-2 -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/gio-unix-2.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -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-11-12-001017-1011516-1 -x c++ /root/firefox-clang/dom/base/nsContentUtils.cpp

/root/firefox-clang/dom/base/nsContentUtils.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/* A namespace class for static layout utilities. */
6
7#include "nsContentUtils.h"
8
9#include <fmt/format.h>
10
11#include <algorithm>
12#include <cstddef>
13#include <cstdint>
14#include <cstdlib>
15#include <cstring>
16#include <functional>
17#include <new>
18#include <utility>
19
20#include "BrowserChild.h"
21#include "CharacterDataBuffer.h"
22#include "DecoderTraits.h"
23#include "ErrorList.h"
24#include "HTMLSplitOnSpacesTokenizer.h"
25#include "ImageOps.h"
26#include "InProcessBrowserChildMessageManager.h"
27#include "MainThreadUtils.h"
28#include "PLDHashTable.h"
29#include "ReferrerInfo.h"
30#include "ScopedNSSTypes.h"
31#include "ThirdPartyUtil.h"
32#include "Units.h"
33#include "chrome/common/ipc_message.h"
34#include "gfxDrawable.h"
35#include "harfbuzz/hb.h"
36#include "imgICache.h"
37#include "imgIContainer.h"
38#include "imgILoader.h"
39#include "imgIRequest.h"
40#include "imgLoader.h"
41#include "js/Array.h"
42#include "js/ArrayBuffer.h"
43#include "js/BuildId.h"
44#include "js/GCAPI.h"
45#include "js/Id.h"
46#include "js/JSON.h"
47#include "js/PropertyAndElement.h" // JS_DefineElement, JS_GetProperty
48#include "js/PropertyDescriptor.h"
49#include "js/Realm.h"
50#include "js/RegExp.h"
51#include "js/RegExpFlags.h"
52#include "js/RootingAPI.h"
53#include "js/TypeDecls.h"
54#include "js/Value.h"
55#include "js/Wrapper.h"
56#include "jsapi.h"
57#include "jsfriendapi.h"
58#include "mozAutoDocUpdate.h"
59#include "mozIDOMWindow.h"
60#include "mozilla/AlreadyAddRefed.h"
61#include "mozilla/AntiTrackingUtils.h"
62#include "mozilla/ArrayIterator.h"
63#include "mozilla/AsyncEventDispatcher.h"
64#include "mozilla/AtomArray.h"
65#include "mozilla/Atomics.h"
66#include "mozilla/Attributes.h"
67#include "mozilla/AutoRestore.h"
68#include "mozilla/BackgroundHangMonitor.h"
69#include "mozilla/Base64.h"
70#include "mozilla/BasePrincipal.h"
71#include "mozilla/BasicEvents.h"
72#include "mozilla/BloomFilter.h"
73#include "mozilla/CORSMode.h"
74#include "mozilla/CallState.h"
75#include "mozilla/CheckedInt.h"
76#include "mozilla/ClearOnShutdown.h"
77#include "mozilla/Components.h"
78#include "mozilla/ContentBlockingAllowList.h"
79#include "mozilla/CycleCollectedJSContext.h"
80#include "mozilla/DOMEventTargetHelper.h"
81#include "mozilla/DebugOnly.h"
82#include "mozilla/ErrorResult.h"
83#include "mozilla/EventDispatcher.h"
84#include "mozilla/EventListenerManager.h"
85#include "mozilla/EventQueue.h"
86#include "mozilla/EventStateManager.h"
87#include "mozilla/FOGIPC.h"
88#include "mozilla/FlowMarkers.h"
89#include "mozilla/FlushType.h"
90#include "mozilla/HTMLEditor.h"
91#include "mozilla/HangAnnotations.h"
92#include "mozilla/IMEStateManager.h"
93#include "mozilla/InputEventOptions.h"
94#include "mozilla/Latin1.h"
95#include "mozilla/Likely.h"
96#include "mozilla/LoadInfo.h"
97#include "mozilla/Logging.h"
98#include "mozilla/ManualNAC.h"
99#include "mozilla/Maybe.h"
100#include "mozilla/MediaFeatureChange.h"
101#include "mozilla/MouseEvents.h"
102#include "mozilla/NullPrincipal.h"
103#include "mozilla/OriginAttributes.h"
104#include "mozilla/Preferences.h"
105#include "mozilla/PresShell.h"
106#include "mozilla/ProfilerRunnable.h"
107#include "mozilla/RangeBoundary.h"
108#include "mozilla/RefPtr.h"
109#include "mozilla/Result.h"
110#include "mozilla/ScopeExit.h"
111#include "mozilla/ScrollContainerFrame.h"
112#include "mozilla/ShutdownPhase.h"
113#include "mozilla/Span.h"
114#include "mozilla/StaticAnalysisFunctions.h"
115#include "mozilla/StaticPrefs_browser.h"
116#include "mozilla/StaticPrefs_clipboard.h"
117#include "mozilla/StaticPrefs_dom.h"
118#include "mozilla/StaticPrefs_network.h"
119#include "mozilla/StaticPrefs_pdfjs.h"
120#include "mozilla/dom/ReportDeliver.h"
121#include "mozilla/extensions/WebExtensionPolicy.h"
122#include "nsIOService.h"
123#include "nsMenuPopupFrame.h"
124#include "nsObjectLoadingContent.h"
125#ifdef FUZZING
126# include "mozilla/StaticPrefs_fuzzing.h"
127#endif
128#include "mozilla/StaticPrefs_mathml.h"
129#include "mozilla/StaticPrefs_nglayout.h"
130#include "mozilla/StaticPrefs_privacy.h"
131#include "mozilla/StaticPrefs_test.h"
132#include "mozilla/StaticPrefs_ui.h"
133#include "mozilla/StaticPtr.h"
134#include "mozilla/TextControlState.h"
135#include "mozilla/TextEditor.h"
136#include "mozilla/TextEvents.h"
137#include "mozilla/TextUtils.h"
138#include "mozilla/Tokenizer.h"
139#include "mozilla/UniquePtr.h"
140#include "mozilla/ViewportUtils.h"
141#include "mozilla/dom/AncestorIterator.h"
142#include "mozilla/dom/AutoEntryScript.h"
143#include "mozilla/dom/AutoSuppressEventHandlingAndSuspend.h"
144#include "mozilla/dom/AutocompleteInfoBinding.h"
145#include "mozilla/dom/BindingDeclarations.h"
146#include "mozilla/dom/BindingUtils.h"
147#include "mozilla/dom/BlobImpl.h"
148#include "mozilla/dom/BlobURLProtocolHandler.h"
149#include "mozilla/dom/BorrowedAttrInfo.h"
150#include "mozilla/dom/BrowserBridgeParent.h"
151#include "mozilla/dom/BrowserParent.h"
152#include "mozilla/dom/BrowsingContext.h"
153#include "mozilla/dom/BrowsingContextGroup.h"
154#include "mozilla/dom/CacheExpirationTime.h"
155#include "mozilla/dom/CallbackFunction.h"
156#include "mozilla/dom/CallbackObject.h"
157#include "mozilla/dom/ChildIterator.h"
158#include "mozilla/dom/ChromeMessageBroadcaster.h"
159#include "mozilla/dom/ContentChild.h"
160#include "mozilla/dom/ContentFrameMessageManager.h"
161#include "mozilla/dom/ContentParent.h"
162#include "mozilla/dom/CustomElementRegistry.h"
163#include "mozilla/dom/CustomElementRegistryBinding.h"
164#include "mozilla/dom/CustomElementTypes.h"
165#include "mozilla/dom/DOMArena.h"
166#include "mozilla/dom/DOMException.h"
167#include "mozilla/dom/DOMExceptionBinding.h"
168#include "mozilla/dom/DOMSecurityMonitor.h"
169#include "mozilla/dom/DOMTypes.h"
170#include "mozilla/dom/DataTransfer.h"
171#include "mozilla/dom/DeprecationReportBody.h"
172#include "mozilla/dom/DocGroup.h"
173#include "mozilla/dom/Document.h"
174#include "mozilla/dom/DocumentFragment.h"
175#include "mozilla/dom/DocumentInlines.h"
176#include "mozilla/dom/DocumentOrShadowRoot.h"
177#include "mozilla/dom/Element.h"
178#include "mozilla/dom/ElementBinding.h"
179#include "mozilla/dom/ElementInlines.h"
180#include "mozilla/dom/Event.h"
181#include "mozilla/dom/EventTarget.h"
182#include "mozilla/dom/FileBlobImpl.h"
183#include "mozilla/dom/FileSystemSecurity.h"
184#include "mozilla/dom/FilteredNodeIterator.h"
185#include "mozilla/dom/FormData.h"
186#include "mozilla/dom/FragmentOrElement.h"
187#include "mozilla/dom/FromParser.h"
188#include "mozilla/dom/FunctionBinding.h"
189#include "mozilla/dom/HTMLElement.h"
190#include "mozilla/dom/HTMLFormElement.h"
191#include "mozilla/dom/HTMLImageElement.h"
192#include "mozilla/dom/HTMLInputElement.h"
193#include "mozilla/dom/HTMLTemplateElement.h"
194#include "mozilla/dom/HTMLTextAreaElement.h"
195#include "mozilla/dom/IPCBlob.h"
196#include "mozilla/dom/IPCBlobUtils.h"
197#include "mozilla/dom/MessageBroadcaster.h"
198#include "mozilla/dom/MessageListenerManager.h"
199#include "mozilla/dom/MessagePort.h"
200#include "mozilla/dom/MimeType.h"
201#include "mozilla/dom/MouseEventBinding.h"
202#include "mozilla/dom/MutationObservers.h"
203#include "mozilla/dom/NameSpaceConstants.h"
204#include "mozilla/dom/NodeBinding.h"
205#include "mozilla/dom/NodeInfo.h"
206#include "mozilla/dom/NodeOwnedObjectList.h"
207#include "mozilla/dom/PBrowser.h"
208#include "mozilla/dom/PContentChild.h"
209#include "mozilla/dom/PrototypeList.h"
210#include "mozilla/dom/Range.h"
211#include "mozilla/dom/ReferrerPolicyBinding.h"
212#include "mozilla/dom/ReportingUtils.h"
213#include "mozilla/dom/Sanitizer.h"
214#include "mozilla/dom/ScriptLoader.h"
215#include "mozilla/dom/ScriptSettings.h"
216#include "mozilla/dom/Selection.h"
217#include "mozilla/dom/ShadowRoot.h"
218#include "mozilla/dom/Text.h"
219#include "mozilla/dom/TrustedHTML.h"
220#include "mozilla/dom/TrustedTypeUtils.h"
221#include "mozilla/dom/TrustedTypesConstants.h"
222#include "mozilla/dom/UserActivation.h"
223#include "mozilla/dom/ViewTransition.h"
224#include "mozilla/dom/WindowBinding.h"
225#include "mozilla/dom/WindowContext.h"
226#include "mozilla/dom/WindowGlobalChild.h"
227#include "mozilla/dom/WindowGlobalParent.h"
228#include "mozilla/dom/WorkerCommon.h"
229#include "mozilla/dom/WorkerPrivate.h"
230#include "mozilla/dom/WorkerRunnable.h"
231#include "mozilla/dom/XULCommandEvent.h"
232#include "mozilla/fallible.h"
233#include "mozilla/gfx/2D.h"
234#include "mozilla/gfx/BaseMargin.h"
235#include "mozilla/gfx/BasePoint.h"
236#include "mozilla/gfx/BaseSize.h"
237#include "mozilla/gfx/DataSurfaceHelpers.h"
238#include "mozilla/gfx/Point.h"
239#include "mozilla/gfx/Rect.h"
240#include "mozilla/gfx/Types.h"
241#include "mozilla/glean/GleanPings.h"
242#include "mozilla/htmlaccel/htmlaccelEnabled.h"
243#ifdef MOZ_MAY_HAVE_HTMLACCEL1
244# include "mozilla/htmlaccel/htmlaccelNotInline.h"
245#endif
246#include "mozilla/dom/ContentList.h"
247#include "mozilla/intl/LocaleService.h"
248#include "mozilla/ipc/ProtocolUtils.h"
249#include "mozilla/widget/IMEData.h"
250#include "nsAboutProtocolUtils.h"
251#include "nsArrayUtils.h"
252#include "nsAtomHashKeys.h"
253#include "nsAttrName.h"
254#include "nsAttrValue.h"
255#include "nsAttrValueInlines.h"
256#include "nsBaseHashtable.h"
257#include "nsCCUncollectableMarker.h"
258#include "nsCOMPtr.h"
259#include "nsCRT.h"
260#include "nsCRTGlue.h"
261#include "nsCanvasFrame.h"
262#include "nsCaseTreatment.h"
263#include "nsCharSeparatedTokenizer.h"
264#include "nsCharTraits.h"
265#include "nsCompatibility.h"
266#include "nsComponentManagerUtils.h"
267#include "nsContainerFrame.h"
268#include "nsContentCreatorFunctions.h"
269#include "nsContentDLF.h"
270#include "nsContentListDeclarations.h"
271#include "nsContentPolicyUtils.h"
272#include "nsCoord.h"
273#include "nsCycleCollectionNoteChild.h"
274#include "nsDOMMutationObserver.h"
275#include "nsDOMString.h"
276#include "nsDebug.h"
277#include "nsDocShell.h"
278#include "nsDocShellCID.h"
279#include "nsError.h"
280#include "nsFocusManager.h"
281#include "nsFrameList.h"
282#include "nsFrameLoader.h"
283#include "nsFrameLoaderOwner.h"
284#include "nsGenericHTMLElement.h"
285#include "nsGkAtoms.h"
286#include "nsGlobalWindowInner.h"
287#include "nsGlobalWindowOuter.h"
288#include "nsHTMLDocument.h"
289#include "nsHTMLTags.h"
290#include "nsHashKeys.h"
291#include "nsHtml5StringParser.h"
292#include "nsIAboutModule.h"
293#include "nsIAnonymousContentCreator.h"
294#include "nsIAppShell.h"
295#include "nsIArray.h"
296#include "nsIAsyncVerifyRedirectCallback.h"
297#include "nsIBidiKeyboard.h"
298#include "nsIBrowser.h"
299#include "nsICacheInfoChannel.h"
300#include "nsICachingChannel.h"
301#include "nsICategoryManager.h"
302#include "nsIChannel.h"
303#include "nsIChannelEventSink.h"
304#include "nsIConsoleService.h"
305#include "nsIContent.h"
306#include "nsIContentInlines.h"
307#include "nsIContentPolicy.h"
308#include "nsIContentSecurityPolicy.h"
309#include "nsIContentSink.h"
310#include "nsIDOMWindowUtils.h"
311#include "nsIDocShell.h"
312#include "nsIDocShellTreeItem.h"
313#include "nsIDocumentEncoder.h"
314#include "nsIDocumentLoaderFactory.h"
315#include "nsIDocumentViewer.h"
316#include "nsIDragService.h"
317#include "nsIDragSession.h"
318#include "nsIFile.h"
319#include "nsIFocusManager.h"
320#include "nsIFormControl.h"
321#include "nsIFragmentContentSink.h"
322#include "nsIFrame.h"
323#include "nsIGlobalObject.h"
324#include "nsIHttpChannel.h"
325#include "nsIHttpChannelInternal.h"
326#include "nsIIOService.h"
327#include "nsIImageLoadingContent.h"
328#include "nsIInputStream.h"
329#include "nsIInterfaceRequestor.h"
330#include "nsIInterfaceRequestorUtils.h"
331#include "nsILoadContext.h"
332#include "nsILoadGroup.h"
333#include "nsILoadInfo.h"
334#include "nsIMIMEService.h"
335#include "nsINetUtil.h"
336#include "nsINode.h"
337#include "nsIObjectLoadingContent.h"
338#include "nsIObserver.h"
339#include "nsIObserverService.h"
340#include "nsIParserUtils.h"
341#include "nsIPermissionManager.h"
342#include "nsIPrincipal.h"
343#include "nsIProperties.h"
344#include "nsIProtocolHandler.h"
345#include "nsIRequest.h"
346#include "nsIRunnable.h"
347#include "nsIScreen.h"
348#include "nsIScriptError.h"
349#include "nsIScriptGlobalObject.h"
350#include "nsIScriptObjectPrincipal.h"
351#include "nsIScriptSecurityManager.h"
352#include "nsISerialEventTarget.h"
353#include "nsIStreamConverter.h"
354#include "nsIStreamConverterService.h"
355#include "nsIStringBundle.h"
356#include "nsISupports.h"
357#include "nsISupportsPrimitives.h"
358#include "nsISupportsUtils.h"
359#include "nsITransferable.h"
360#include "nsIURI.h"
361#include "nsIURIMutator.h"
362#include "nsTHashMap.h"
363#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
364# include "nsIURIWithSpecialOrigin.h"
365#endif
366#include "nsIUserIdleServiceInternal.h"
367#include "nsIWeakReferenceUtils.h"
368#include "nsIWebNavigation.h"
369#include "nsIWebNavigationInfo.h"
370#include "nsIWidget.h"
371#include "nsIWindowMediator.h"
372#include "nsIXPConnect.h"
373#include "nsJSPrincipals.h"
374#include "nsJSUtils.h"
375#include "nsLayoutUtils.h"
376#include "nsLiteralString.h"
377#include "nsMargin.h"
378#include "nsMimeTypes.h"
379#include "nsNameSpaceManager.h"
380#include "nsNetCID.h"
381#include "nsNetUtil.h"
382#include "nsNodeInfoManager.h"
383#include "nsPIDOMWindow.h"
384#include "nsPIDOMWindowInlines.h"
385#include "nsParser.h"
386#include "nsParserConstants.h"
387#include "nsPoint.h"
388#include "nsPointerHashKeys.h"
389#include "nsPresContext.h"
390#include "nsQueryFrame.h"
391#include "nsQueryObject.h"
392#include "nsReadableUtils.h"
393#include "nsRefPtrHashtable.h"
394#include "nsSandboxFlags.h"
395#include "nsScriptSecurityManager.h"
396#include "nsServiceManagerUtils.h"
397#include "nsStreamUtils.h"
398#include "nsString.h"
399#include "nsStringBundle.h"
400#include "nsStringFlags.h"
401#include "nsStringFwd.h"
402#include "nsStringIterator.h"
403#include "nsStringStream.h"
404#include "nsTArray.h"
405#include "nsTLiteralString.h"
406#include "nsTPromiseFlatString.h"
407#include "nsTStringRepr.h"
408#include "nsTextNode.h"
409#include "nsThreadManager.h"
410#include "nsThreadUtils.h"
411#include "nsTreeSanitizer.h"
412#include "nsUGenCategory.h"
413#include "nsURLHelper.h"
414#include "nsUnicodeProperties.h"
415#include "nsVariant.h"
416#include "nsWhitespaceTokenizer.h"
417#include "nsWidgetsCID.h"
418#include "nsXMLContentSerializer.h"
419#include "nsXPCOM.h"
420#include "nsXPCOMCID.h"
421#include "nsXULAppAPI.h"
422#include "nsXULElement.h"
423#include "nsXULPopupManager.h"
424#include "nscore.h"
425#include "prinrval.h"
426#include "xpcprivate.h"
427#include "xpcpublic.h"
428
429#if defined(XP_WIN)
430// Undefine LoadImage to prevent naming conflict with Windows.
431# undef LoadImage
432#endif
433
434extern "C" int MOZ_XMLTranslateEntity(const char* ptr, const char* end,
435 const char** next, char16_t* result);
436extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end, int ns_aware,
437 const char** colon);
438
439using namespace mozilla::dom;
440using namespace mozilla::ipc;
441using namespace mozilla::gfx;
442using namespace mozilla::layers;
443using namespace mozilla::widget;
444using namespace mozilla;
445
446const char kLoadAsData[] = "loadAsData";
447
448nsIXPConnect* nsContentUtils::sXPConnect;
449nsIScriptSecurityManager* nsContentUtils::sSecurityManager;
450nsIPrincipal* nsContentUtils::sSystemPrincipal;
451nsIPrincipal* nsContentUtils::sNullSubjectPrincipal;
452nsIPrincipal* nsContentUtils::sFingerprintingProtectionPrincipal;
453nsIConsoleService* nsContentUtils::sConsoleService;
454
455static nsTHashMap<RefPtr<nsAtom>, EventNameMapping>* sAtomEventTable;
456static nsTHashMap<nsStringHashKey, EventNameMapping>* sStringEventTable;
457static nsTArray<RefPtr<nsAtom>>* sUserDefinedEvents;
458nsIStringBundleService* nsContentUtils::sStringBundleService;
459
460static constexpr size_t kPropertiesFileCount =
461 static_cast<size_t>(PropertiesFile::COUNT);
462
463static StaticRefPtr<nsIStringBundle> sStringBundles[kPropertiesFileCount];
464
465nsIContentPolicy* nsContentUtils::sContentPolicyService;
466bool nsContentUtils::sTriedToGetContentPolicy = false;
467StaticRefPtr<nsIBidiKeyboard> nsContentUtils::sBidiKeyboard;
468uint32_t nsContentUtils::sScriptBlockerCount = 0;
469uint32_t nsContentUtils::sDOMNodeRemovedSuppressCount = 0;
470AutoTArray<nsCOMPtr<nsIRunnable>, 8>* nsContentUtils::sBlockedScriptRunners =
471 nullptr;
472uint32_t nsContentUtils::sRunnersCountAtFirstBlocker = 0;
473nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nullptr;
474
475bool nsContentUtils::sIsHandlingKeyBoardEvent = false;
476
477nsString* nsContentUtils::sShiftText = nullptr;
478nsString* nsContentUtils::sControlText = nullptr;
479nsString* nsContentUtils::sCommandOrWinText = nullptr;
480nsString* nsContentUtils::sAltText = nullptr;
481nsString* nsContentUtils::sModifierSeparator = nullptr;
482
483bool nsContentUtils::sInitialized = false;
484#ifndef RELEASE_OR_BETA
485bool nsContentUtils::sBypassCSSOMOriginCheck = false;
486#endif
487
488nsCString* nsContentUtils::sJSScriptBytecodeMimeType = nullptr;
489nsCString* nsContentUtils::sJSModuleBytecodeMimeType = nullptr;
490
491nsContentUtils::UserInteractionObserver*
492 nsContentUtils::sUserInteractionObserver = nullptr;
493
494nsHtml5StringParser* nsContentUtils::sHTMLFragmentParser = nullptr;
495nsParser* nsContentUtils::sXMLFragmentParser = nullptr;
496nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nullptr;
497bool nsContentUtils::sFragmentParsingActive = false;
498
499mozilla::LazyLogModule nsContentUtils::gResistFingerprintingLog(
500 "nsResistFingerprinting");
501mozilla::LazyLogModule nsContentUtils::sDOMDumpLog("Dump");
502// Log when "input" and "beforeinput" events are dispatched or enqueued with
503// InputEvent:3,sync.
504mozilla::LazyLogModule gInputEventLog("InputEvent");
505
506int32_t nsContentUtils::sInnerOrOuterWindowCount = 0;
507uint32_t nsContentUtils::sInnerOrOuterWindowSerialCounter = 0;
508
509#define INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
510 aResultType, aMethodName, aTreeKind, ...) \
511 template aResultType aMethodName<aTreeKind>(__VA_ARGS__);
512
513#define INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS( \
514 aResultType, aMethodName, aTreeKind, ...) \
515 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
516 aResultType, aMethodName, aTreeKind, const RangeBoundary&, \
517 const RangeBoundary&, __VA_ARGS__) \
518 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
519 aResultType, aMethodName, aTreeKind, const RangeBoundary&, \
520 const RawRangeBoundary&, __VA_ARGS__) \
521 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
522 aResultType, aMethodName, aTreeKind, const RawRangeBoundary&, \
523 const RangeBoundary&, __VA_ARGS__) \
524 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
525 aResultType, aMethodName, aTreeKind, const RawRangeBoundary&, \
526 const RawRangeBoundary&, __VA_ARGS__) \
527 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
528 aResultType, aMethodName, aTreeKind, const ConstRawRangeBoundary&, \
529 const ConstRawRangeBoundary&, __VA_ARGS__) \
530 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
531 aResultType, aMethodName, aTreeKind, const ConstRawRangeBoundary&, \
532 const RangeBoundary&, __VA_ARGS__) \
533 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
534 aResultType, aMethodName, aTreeKind, const ConstRawRangeBoundary&, \
535 const RawRangeBoundary&, __VA_ARGS__) \
536 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
537 aResultType, aMethodName, aTreeKind, const RangeBoundary&, \
538 const ConstRawRangeBoundary&, __VA_ARGS__) \
539 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
540 aResultType, aMethodName, aTreeKind, const RawRangeBoundary&, \
541 const ConstRawRangeBoundary&, __VA_ARGS__)
542
543INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS(Maybe<int32_t>,
544 nsContentUtils::ComparePoints,
545 TreeKind::DOM, NodeIndexCache*,
546 const nsINode*);
547INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS(Maybe<int32_t>,
548 nsContentUtils::ComparePoints,
549 TreeKind::ShadowIncludingDOM,
550 NodeIndexCache*,
551 const nsINode*);
552INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS(Maybe<int32_t>,
553 nsContentUtils::ComparePoints,
554 TreeKind::Flat,
555 NodeIndexCache*,
556 const nsINode*);
557INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS(Maybe<int32_t>,
558 nsContentUtils::ComparePoints,
559 TreeKind::FlatForSelection,
560 NodeIndexCache*,
561 const nsINode*);
562
563#undef INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS
564#undef INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM
565
566// Subset of
567// http://www.whatwg.org/specs/web-apps/current-work/#autofill-field-name
568enum AutocompleteUnsupportedFieldName : uint8_t {
569#define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
570 eAutocompleteUnsupportedFieldName_##name_,
571#include "AutocompleteFieldList.h"
572#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
573};
574
575enum AutocompleteNoPersistFieldName : uint8_t {
576#define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \
577 eAutocompleteNoPersistFieldName_##name_,
578#include "AutocompleteFieldList.h"
579#undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME
580};
581
582enum AutocompleteUnsupportFieldContactHint : uint8_t {
583#define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
584 eAutocompleteUnsupportedFieldContactHint_##name_,
585#include "AutocompleteFieldList.h"
586#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
587};
588
589enum AutocompleteFieldName : uint8_t {
590#define AUTOCOMPLETE_FIELD_NAME(name_, value_) eAutocompleteFieldName_##name_,
591#define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
592 AUTOCOMPLETE_FIELD_NAME(name_, value_)
593#include "AutocompleteFieldList.h"
594#undef AUTOCOMPLETE_FIELD_NAME
595#undef AUTOCOMPLETE_CONTACT_FIELD_NAME
596};
597
598enum AutocompleteFieldHint : uint8_t {
599#define AUTOCOMPLETE_FIELD_HINT(name_, value_) eAutocompleteFieldHint_##name_,
600#include "AutocompleteFieldList.h"
601#undef AUTOCOMPLETE_FIELD_HINT
602};
603
604enum AutocompleteFieldContactHint : uint8_t {
605#define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
606 eAutocompleteFieldContactHint_##name_,
607#include "AutocompleteFieldList.h"
608#undef AUTOCOMPLETE_FIELD_CONTACT_HINT
609};
610
611enum AutocompleteCredentialType : uint8_t {
612#define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \
613 eAutocompleteCredentialType_##name_,
614#include "AutocompleteFieldList.h"
615#undef AUTOCOMPLETE_CREDENTIAL_TYPE
616};
617
618enum AutocompleteCategory {
619#define AUTOCOMPLETE_CATEGORY(name_, value_) eAutocompleteCategory_##name_,
620#include "AutocompleteFieldList.h"
621#undef AUTOCOMPLETE_CATEGORY
622};
623
624static constexpr nsAttrValue::EnumTableEntry
625 kAutocompleteUnsupportedFieldNameTable[]{
626#define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
627 {value_, eAutocompleteUnsupportedFieldName_##name_},
628#include "AutocompleteFieldList.h"
629#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
630 };
631
632static constexpr nsAttrValue::EnumTableEntry
633 kAutocompleteNoPersistFieldNameTable[] = {
634#define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \
635 {value_, eAutocompleteNoPersistFieldName_##name_},
636#include "AutocompleteFieldList.h"
637#undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME
638};
639static constexpr nsAttrValue::EnumTableEntry
640 kAutocompleteUnsupportedContactFieldHintTable[] = {
641#define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
642 {value_, eAutocompleteUnsupportedFieldContactHint_##name_},
643#include "AutocompleteFieldList.h"
644#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
645};
646
647static constexpr nsAttrValue::EnumTableEntry kAutocompleteFieldNameTable[] = {
648#define AUTOCOMPLETE_FIELD_NAME(name_, value_) \
649 {value_, eAutocompleteFieldName_##name_},
650#include "AutocompleteFieldList.h"
651#undef AUTOCOMPLETE_FIELD_NAME
652};
653
654static constexpr nsAttrValue::EnumTableEntry
655 kAutocompleteContactFieldNameTable[] = {
656#define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
657 {value_, eAutocompleteFieldName_##name_},
658#include "AutocompleteFieldList.h"
659#undef AUTOCOMPLETE_CONTACT_FIELD_NAME
660};
661
662static constexpr nsAttrValue::EnumTableEntry kAutocompleteFieldHintTable[] = {
663#define AUTOCOMPLETE_FIELD_HINT(name_, value_) \
664 {value_, eAutocompleteFieldHint_##name_},
665#include "AutocompleteFieldList.h"
666#undef AUTOCOMPLETE_FIELD_HINT
667};
668
669static constexpr nsAttrValue::EnumTableEntry
670 kAutocompleteContactFieldHintTable[] = {
671#define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
672 {value_, eAutocompleteFieldContactHint_##name_},
673#include "AutocompleteFieldList.h"
674#undef AUTOCOMPLETE_FIELD_CONTACT_HINT
675};
676
677static constexpr nsAttrValue::EnumTableEntry
678 kAutocompleteCredentialTypeTable[] = {
679#define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \
680 {value_, eAutocompleteCredentialType_##name_},
681#include "AutocompleteFieldList.h"
682#undef AUTOCOMPLETE_CREDENTIAL_TYPE
683};
684
685namespace {
686
687// A global hashtable to for keeping the arena alive for cross docGroup node
688// adoption.
689static nsRefPtrHashtable<nsPtrHashKey<const nsINode>, mozilla::dom::DOMArena>*
690 sDOMArenaHashtable;
691
692class SameOriginCheckerImpl final : public nsIChannelEventSink,
693 public nsIInterfaceRequestor {
694 ~SameOriginCheckerImpl() = default;
695
696 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
697 NS_DECL_NSICHANNELEVENTSINKvirtual nsresult AsyncOnChannelRedirect(nsIChannel *oldChannel
, nsIChannel *newChannel, uint32_t flags, nsIAsyncVerifyRedirectCallback
*callback) override;
698 NS_DECL_NSIINTERFACEREQUESTORvirtual nsresult GetInterface(const nsIID & uuid, void * *
result) override;
699};
700
701} // namespace
702
703void AutoSuppressEventHandling::SuppressDocument(Document* aDoc) {
704 // Note: Document::SuppressEventHandling will also automatically suppress
705 // event handling for any in-process sub-documents. However, since we need
706 // to deal with cases where remote BrowsingContexts may be interleaved
707 // with in-process ones, we still need to walk the entire tree ourselves.
708 // This may be slightly redundant in some cases, but since event handling
709 // suppressions maintain a count of current blockers, it does not cause
710 // any problems.
711 aDoc->SuppressEventHandling();
712}
713
714void AutoSuppressEventHandling::UnsuppressDocument(Document* aDoc) {
715 aDoc->UnsuppressEventHandlingAndFireEvents(true);
716}
717
718AutoSuppressEventHandling::~AutoSuppressEventHandling() {
719 UnsuppressDocuments();
720}
721
722void AutoSuppressEventHandlingAndSuspend::SuppressDocument(Document* aDoc) {
723 AutoSuppressEventHandling::SuppressDocument(aDoc);
724 if (nsCOMPtr<nsPIDOMWindowInner> win = aDoc->GetInnerWindow()) {
725 win->Suspend();
726 mWindows.AppendElement(win);
727 }
728}
729
730AutoSuppressEventHandlingAndSuspend::~AutoSuppressEventHandlingAndSuspend() {
731 for (const auto& win : mWindows) {
732 win->Resume();
733 }
734}
735
736// The following structs are used by CommonAncestors. They must have:
737// NodeType, Get(), ComputeChildIndex(), GetChildCount() and CanComputeIndex().
738// If CanComputeIndex() returns false, ComputeChildIndex() nor GetChildCount()
739// is not used by CommonAncestors to assert the odd result.
740
741/**
742 * GetParentNodeForComparison is used for implementing
743 * nsContentUtils::ComparePoints and its relatives and helpers.
744 */
745template <TreeKind aKind>
746struct GetParentNodeForComparison {
747 using NodeType = nsINode;
748 static NodeType* Get(const NodeType* aNode) {
749 if constexpr (aKind == TreeKind::DOM) {
750 return aNode->GetParentNode();
751 }
752 // We want to list up ShadowRoot as the parent of a child of ShadowRoot and
753 // its host as the parent of the ShadowRoot. GetFlattenedTreeParentNode()
754 // won't return ShadowRoot so that we cannot use
755 // nsINode::GetParentNode<aKind>() here.
756 if constexpr (ShouldHandleAssignedNodesOnSlot<aKind>()) {
757 if (aNode->IsContent()) {
758 if (HTMLSlotElement* const slot =
759 aNode->AsContent()->GetAssignedSlot<aKind>()) {
760 return slot;
761 }
762 // FIXME: If aNode->GetParentNode()->GetShadowRoot<aKind>() returns
763 // non-nullptr, we should always return nullptr here. However, if aKind
764 // is TreeKind::FlatForSelection, we cannot do that because
765 // GetFlattenedTreeParentNode<nsINode::eForSelection>() returns the
766 // shadow host element as-is. Therefore, we do the strict behavior only
767 // here causes assertion failures with the extant tests. This should
768 // be fixed in bug 2014622.
769 if constexpr (aKind != TreeKind::FlatForSelection) {
770 // If we're handling a flattened tree, we should return nullptr if the
771 // node is not part of a flattened tree.
772 if (nsINode* const parentNode = aNode->GetParentNode()) {
773 if (parentNode->GetShadowRoot<aKind>()) {
774 return nullptr;
775 }
776 }
777 }
778 }
779 }
780 return aNode->GetParentOrShadowHostNode();
781 }
782 static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent,
783 const nsIContent* aPossibleChild) {
784 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
785 return aParent->ComputeIndexOf(aPossibleChild);
786 } else {
787 return aParent->ComputeIndexOf<aKind>(aPossibleChild);
788 }
789 }
790 static uint32_t GetChildCount(const NodeType* aParent) {
791 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
792 return aParent->GetChildCount();
793 } else {
794 return aParent->GetChildCount<aKind>();
795 }
796 }
797 constexpr static bool CanComputeIndex() {
798 // The helpers of nsContentUtils::ComparePoints() and relatives require
799 // ComputeChildIndex() and GetChildCount(). Therefore, we implement them and
800 // return true.
801 return true;
802 }
803};
804
805/**
806 * GetParentNode is used for implementing
807 * nsContentUtils::GetClosestCommonInclusiveAncestor().
808 */
809using GetParentNode = GetParentNodeForComparison<TreeKind::DOM>;
810
811/**
812 * GetParentOrShadowHostNode is used for implementing
813 * nsContentUtils::GetClosestCommonShadowIncludingInclusiveAncestor().
814 */
815struct GetParentOrShadowHostNode {
816 using NodeType = nsINode;
817 static NodeType* Get(const NodeType* aNode) {
818 return aNode->GetParentOrShadowHostNode();
819 }
820 static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent,
821 const nsIContent* aPossibleChild) {
822 return aParent->ComputeIndexOf(aPossibleChild);
823 }
824 static uint32_t GetChildCount(const NodeType* aParent) {
825 return aParent->GetChildCount();
826 }
827 constexpr static bool CanComputeIndex() {
828 // Neither ComputeChildIndex() nor GetChildCount() is required by
829 // nsContentUtils::GetClosestCommonShadowIncludingInclusiveAncestor(), but
830 // let's implement them to make CommonAncestors asserts the odd situations
831 // so that return true.
832 return true;
833 }
834};
835
836/**
837 * GetFlattenedTreeParent is used for implementing
838 * nsContentUtils::GetCommonFlattenedTreeAncestor().
839 */
840struct GetFlattenedTreeParent {
841 using NodeType = nsIContent;
842 static NodeType* Get(const NodeType* aContent) {
843 return aContent->GetFlattenedTreeParent();
844 }
845 static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent,
846 const nsIContent* aPossibleChild) {
847 return aParent->ComputeFlatTreeIndexOf(aPossibleChild);
848 }
849 static uint32_t GetChildCount(const NodeType* aParent) {
850 return aParent->GetFlatTreeChildCount();
851 }
852 constexpr static bool CanComputeIndex() {
853 // Neither ComputeChildIndex() nor GetChildCount() is required by
854 // nsContentUtils::GetCommonFlattenedTreeAncestor(), but let's implement
855 // them to make CommonAncestors asserts the odd situations so that return
856 // true.
857 return true;
858 }
859};
860
861/**
862 * GetFlattenedTreeParentNodeForSelection is used for implementing
863 * nsContentUtils::GetCommonFlattenedTreeAncestorForSelection().
864 */
865struct GetFlattenedTreeParentNodeForSelection {
866 using NodeType = nsINode;
867 static NodeType* Get(const NodeType* aNode) {
868 return aNode->GetFlattenedTreeParentNodeForSelection();
869 }
870 static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent,
871 const nsIContent* aPossibleChild) {
872 return aParent->ComputeFlatTreeForSelectionIndexOf(aPossibleChild);
873 }
874 static uint32_t GetChildCount(const NodeType* aParent) {
875 return aParent->GetFlatTreeForSelectionChildCount();
876 }
877 constexpr static bool CanComputeIndex() {
878 // Neither ComputeChildIndex() nor GetChildCount() is required by
879 // nsContentUtils::GetCommonFlattenedTreeAncestorForSelection(), but let's
880 // implement them to make CommonAncestors asserts the odd situations so that
881 // return true.
882 return true;
883 }
884};
885
886/**
887 * GetFlattenedTreeParentElementForStyle is used for implementing
888 * nsContentUtils::GetCommonFlattenedTreeAncestorForStyle().
889 */
890struct GetFlattenedTreeParentElementForStyle {
891 using NodeType = Element;
892 static NodeType* Get(const NodeType* aElement) {
893 return aElement->GetFlattenedTreeParentElementForStyle();
894 }
895 static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent,
896 const nsIContent* aPossibleChild) {
897 return Nothing();
898 }
899 static uint32_t GetChildCount(const NodeType* aParent) {
900 return 0; // This should be called only when CanComputeIndex() returns true
901 }
902 constexpr static bool CanComputeIndex() {
903 // Neither ComputeChildIndex() nor GetChildCount() is required by
904 // nsContentUtils::GetCommonFlattenedTreeAncestorForStyle() and there is no
905 // API to get child count nor compute index of a child in the flattened tree
906 // for style. Therefore, we don't implement them so that return false.
907 return false;
908 }
909};
910
911/**
912 * GetParentBrowserParent is used for implementing
913 * nsContentUtils::GetCommonBrowserParentAncestor().
914 */
915struct GetParentBrowserParent {
916 using NodeType = BrowserParent;
917 static NodeType* Get(const NodeType* aBrowserParent) {
918 return aBrowserParent->GetBrowserBridgeParent()
919 ? aBrowserParent->GetBrowserBridgeParent()->Manager()
920 : nullptr;
921 }
922 static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent,
923 const nsIContent* aPossibleChild) {
924 return Nothing();
925 }
926 static uint32_t GetChildCount(const NodeType* aParent) {
927 return 0; // This should be called only when CanComputeIndex() returns true
928 }
929 constexpr static bool CanComputeIndex() {
930 // Neither ComputeChildIndex() nor GetChildCount() is required by
931 // nsContentUtils::GetCommonBrowserParentAncestor() and there is no API to
932 // get child count of a BrowserParent nor compute index of a child of
933 // BrowserParent. Therefore, we don't implement them so that return false.
934 return false;
935 }
936};
937
938template <TreeKind aKind>
939static bool ChildNodeIsInShadowDOMHostedByParent(const nsINode* aParent,
940 const nsINode* aChild) {
941 ShadowRoot* const shadowRoot = aParent->GetShadowRoot<aKind>();
942 if (!shadowRoot) {
943 return false;
944 }
945 // We already checked whether aChild is in a shadow in the tree kind.
946 // Therefore, we don't need to use GetContainingShadowForSelection() here.
947 return shadowRoot == aChild->GetContainingShadow();
948}
949
950// If we're comparing 2 DOM points in TreeKind::ShadowIncludingDOM mode, we want
951// to compare the direct children of the parent node even if the parent is a
952// shadow host. So, we want to compare them as TreeKind::DOM.
953template <TreeKind aKind>
954constexpr TreeKind TreeKindToCompareChildren() {
955 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
956 return TreeKind::DOM;
957 } else {
958 return aKind;
959 }
960}
961
962template <TreeKind aKind>
963static inline bool IsInclusiveDescendantForComparison(
964 const nsINode& aNode, const nsINode& aAncestor) {
965 for (const nsINode* node = &aNode; node;
966 node = GetParentNodeForComparison<aKind>::Get(node)) {
967 if (node == &aAncestor) {
968 return true;
969 }
970 }
971 return false;
972}
973
974template <class GetParentStruct>
975class MOZ_STACK_CLASS CommonAncestors final {
976 public:
977 using NodeType = GetParentStruct::NodeType;
978
979 /**
980 * @param aNode1 A DOM node or something which may have ancestors.
981 * @param aNode2 Another DOM node or something.
982 * @param aGetParentStruct A struct containing static GetParent(),
983 * ComputeChildIndex(), GetChildCount() and CanComputeIndex(). If
984 * CanComputeIndex() returns false, ComputeChildIndex() nor GetChildCount() is
985 * never used.
986 */
987 CommonAncestors(const NodeType& aNode1, const NodeType& aNode2,
988 const NodeType* aAncestorLimiter = nullptr) {
989#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1
990 mAssertNoGC.emplace();
991#endif // #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
992
993 AppendInclusiveAncestors(const_cast<NodeType*>(&aNode1),
994 mInclusiveAncestors1, aAncestorLimiter);
995 if (aAncestorLimiter &&
996 mInclusiveAncestors1.LastElement() != aAncestorLimiter) {
997 return;
998 }
999 AppendInclusiveAncestors(const_cast<NodeType*>(&aNode2),
1000 mInclusiveAncestors2, aAncestorLimiter);
1001 if (aAncestorLimiter &&
1002 mInclusiveAncestors2.LastElement() != aAncestorLimiter) {
1003 return;
1004 }
1005
1006 // Find where the parent chain differs
1007 size_t depth1 = mInclusiveAncestors1.Length();
1008 size_t depth2 = mInclusiveAncestors2.Length();
1009 const size_t shorterLength = std::min(depth1, depth2);
1010 NodeType** const inclusiveAncestors1 = mInclusiveAncestors1.Elements();
1011 NodeType** const inclusiveAncestors2 = mInclusiveAncestors2.Elements();
1012 for ([[maybe_unused]] const size_t unused : IntegerRange(shorterLength)) {
1013 NodeType* const inclusiveAncestor1 = inclusiveAncestors1[--depth1];
1014 NodeType* const inclusiveAncestor2 = inclusiveAncestors2[--depth2];
1015 if (inclusiveAncestor1 != inclusiveAncestor2) {
1016 MOZ_ASSERT_IF(mClosestCommonAncestor,do { if (mClosestCommonAncestor) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(inclusiveAncestor1
== GetClosestCommonAncestorChild1())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(inclusiveAncestor1 == GetClosestCommonAncestorChild1
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("inclusiveAncestor1 == GetClosestCommonAncestorChild1()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1017); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inclusiveAncestor1 == GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 1017); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1017 inclusiveAncestor1 == GetClosestCommonAncestorChild1())do { if (mClosestCommonAncestor) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(inclusiveAncestor1
== GetClosestCommonAncestorChild1())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(inclusiveAncestor1 == GetClosestCommonAncestorChild1
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("inclusiveAncestor1 == GetClosestCommonAncestorChild1()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1017); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inclusiveAncestor1 == GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 1017); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1018 MOZ_ASSERT_IF(mClosestCommonAncestor,do { if (mClosestCommonAncestor) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(inclusiveAncestor2
== GetClosestCommonAncestorChild2())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(inclusiveAncestor2 == GetClosestCommonAncestorChild2
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("inclusiveAncestor2 == GetClosestCommonAncestorChild2()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1019); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inclusiveAncestor2 == GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 1019); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1019 inclusiveAncestor2 == GetClosestCommonAncestorChild2())do { if (mClosestCommonAncestor) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(inclusiveAncestor2
== GetClosestCommonAncestorChild2())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(inclusiveAncestor2 == GetClosestCommonAncestorChild2
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("inclusiveAncestor2 == GetClosestCommonAncestorChild2()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1019); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inclusiveAncestor2 == GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 1019); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1020 return;
1021 }
1022 mNumberOfCommonAncestors++;
1023 mClosestCommonAncestor = inclusiveAncestor1;
1024 }
1025 MOZ_ASSERT(mClosestCommonAncestor)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mClosestCommonAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mClosestCommonAncestor))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("mClosestCommonAncestor"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1025); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mClosestCommonAncestor" ")"); do { MOZ_CrashSequence
(__null, 1025); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1026 MOZ_ASSERT(mNumberOfCommonAncestors)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mNumberOfCommonAncestors)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mNumberOfCommonAncestors))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("mNumberOfCommonAncestors"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1026); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mNumberOfCommonAncestors" ")"); do { MOZ_CrashSequence
(__null, 1026); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1027 MOZ_ASSERT(!depth1 || !depth2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!depth1 || !depth2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!depth1 || !depth2))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!depth1 || !depth2"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1027); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!depth1 || !depth2" ")"); do { MOZ_CrashSequence
(__null, 1027); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1028 MOZ_ASSERT_IF(!depth1, !GetClosestCommonAncestorChild1())do { if (!depth1) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(!GetClosestCommonAncestorChild1())>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(!GetClosestCommonAncestorChild1()))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("!GetClosestCommonAncestorChild1()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1028); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!GetClosestCommonAncestorChild1()" ")"); do
{ MOZ_CrashSequence(__null, 1028); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); } } while (false
)
;
1029 MOZ_ASSERT_IF(depth1, GetClosestCommonAncestorChild1())do { if (depth1) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(GetClosestCommonAncestorChild1())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetClosestCommonAncestorChild1
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetClosestCommonAncestorChild1()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1029); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 1029); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1030 MOZ_ASSERT_IF(!depth2, !GetClosestCommonAncestorChild2())do { if (!depth2) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(!GetClosestCommonAncestorChild2())>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(!GetClosestCommonAncestorChild2()))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("!GetClosestCommonAncestorChild2()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1030); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!GetClosestCommonAncestorChild2()" ")"); do
{ MOZ_CrashSequence(__null, 1030); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); } } while (false
)
;
1031 MOZ_ASSERT_IF(depth2, GetClosestCommonAncestorChild2())do { if (depth2) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(GetClosestCommonAncestorChild2())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetClosestCommonAncestorChild2
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetClosestCommonAncestorChild2()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1031); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 1031); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1032 }
1033
1034#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1
1035 ~CommonAncestors() { MOZ_DIAGNOSTIC_ASSERT(!mMutationGuard.Mutated(0))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mMutationGuard.Mutated(0))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mMutationGuard.Mutated(0)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mMutationGuard.Mutated(0)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1035); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "!mMutationGuard.Mutated(0)" ")"
); do { MOZ_CrashSequence(__null, 1035); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; }
1036#endif // #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1037
1038 [[nodiscard]] NodeType* GetClosestCommonAncestor() const {
1039 return mClosestCommonAncestor;
1040 }
1041 [[nodiscard]] NodeType* GetClosestCommonAncestorChild1() const {
1042 return GetClosestCommonAncestorChild(mInclusiveAncestors1);
1043 }
1044 [[nodiscard]] NodeType* GetClosestCommonAncestorChild2() const {
1045 return GetClosestCommonAncestorChild(mInclusiveAncestors2);
1046 }
1047
1048 template <TreeKind aKind>
1049 void WarnIfClosestCommonAncestorChildrenAreNotInChildList() const {
1050 WarnIfClosestCommonAncestorChildIsNotInChildList<aKind>(
1051 mInclusiveAncestors1);
1052 WarnIfClosestCommonAncestorChildIsNotInChildList<aKind>(
1053 mInclusiveAncestors2);
1054 }
1055
1056 private:
1057 static void AppendInclusiveAncestors(NodeType* aNode,
1058 nsTArray<NodeType*>& aArrayOfParents,
1059 const NodeType* aAncestorLimiter) {
1060 NodeType* node = aNode;
1061 while (node) {
1062 aArrayOfParents.AppendElement(node);
1063 if (node == aAncestorLimiter) {
1064 break;
1065 }
1066 node = GetParentStruct::Get(node);
1067 }
1068 }
1069
1070 Maybe<size_t> GetClosestCommonAncestorChildIndex(
1071 const nsTArray<NodeType*>& aInclusiveAncestors) const {
1072 if (!mClosestCommonAncestor ||
1073 aInclusiveAncestors.Length() <= mNumberOfCommonAncestors) {
1074 return Nothing();
1075 }
1076 return Some((aInclusiveAncestors.Length() - 1) // last index
1077 - mNumberOfCommonAncestors); // before closest common ancestor
1078 }
1079
1080 [[nodiscard]] NodeType* GetClosestCommonAncestorChild(
1081 const nsTArray<NodeType*>& aInclusiveAncestors) const {
1082 const Maybe<size_t> index =
1083 GetClosestCommonAncestorChildIndex(aInclusiveAncestors);
1084 if (index.isNothing()) {
1085 MOZ_ASSERT_IF(mClosestCommonAncestor,do { if (mClosestCommonAncestor) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(aInclusiveAncestors
.Length() == mNumberOfCommonAncestors)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aInclusiveAncestors.Length()
== mNumberOfCommonAncestors))), 0))) { do { } while (false);
MOZ_ReportAssertionFailure("aInclusiveAncestors.Length() == mNumberOfCommonAncestors"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1086); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aInclusiveAncestors.Length() == mNumberOfCommonAncestors"
")"); do { MOZ_CrashSequence(__null, 1086); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1086 aInclusiveAncestors.Length() == mNumberOfCommonAncestors)do { if (mClosestCommonAncestor) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(aInclusiveAncestors
.Length() == mNumberOfCommonAncestors)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aInclusiveAncestors.Length()
== mNumberOfCommonAncestors))), 0))) { do { } while (false);
MOZ_ReportAssertionFailure("aInclusiveAncestors.Length() == mNumberOfCommonAncestors"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1086); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aInclusiveAncestors.Length() == mNumberOfCommonAncestors"
")"); do { MOZ_CrashSequence(__null, 1086); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1087 return nullptr;
1088 }
1089 NodeType* const child = aInclusiveAncestors[*index];
1090 MOZ_ASSERT(child)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(child)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(child))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("child", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1090); AnnotateMozCrashReason("MOZ_ASSERT" "(" "child" ")")
; do { MOZ_CrashSequence(__null, 1090); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1091 MOZ_ASSERT(GetParentStruct::Get(child) == mClosestCommonAncestor)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetParentStruct::Get(child) == mClosestCommonAncestor
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentStruct::Get(child) == mClosestCommonAncestor
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"GetParentStruct::Get(child) == mClosestCommonAncestor", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1091); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetParentStruct::Get(child) == mClosestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 1091); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1092 return child;
1093 }
1094
1095 template <TreeKind aKind>
1096 void WarnIfClosestCommonAncestorChildIsNotInChildList(
1097 const nsTArray<NodeType*>& aInclusiveAncestors) const {
1098#ifdef DEBUG1
1099 if constexpr (std::is_base_of_v<nsINode, NodeType>) {
1100 if (!GetParentStruct::CanComputeIndex()) {
1101 return;
1102 }
1103 const nsIContent* const child = nsIContent::FromNodeOrNull(
1104 GetClosestCommonAncestorChild(aInclusiveAncestors));
1105 if (!child) {
1106 return;
1107 }
1108
1109 if (child->IsShadowRoot() ||
1110 (ShouldHandleAssignedNodesOnSlot<aKind>() &&
1111 child->GetAssignedSlot<aKind>() &&
1112 mClosestCommonAncestor != child->GetAssignedSlot<aKind>())) {
1113 return;
1114 }
1115
1116 if (MOZ_LIKELY((__builtin_expect(!!(GetParentStruct::ComputeChildIndex(mClosestCommonAncestor
, child) .isSome()), 1))
1117 GetParentStruct::ComputeChildIndex(mClosestCommonAncestor, child)(__builtin_expect(!!(GetParentStruct::ComputeChildIndex(mClosestCommonAncestor
, child) .isSome()), 1))
1118 .isSome())(__builtin_expect(!!(GetParentStruct::ComputeChildIndex(mClosestCommonAncestor
, child) .isSome()), 1))
) {
1119 return;
1120 }
1121 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
1122 NS_WARNING(ToString(ConstRawRangeBoundary::FromChild(*child)).c_str())NS_DebugBreak(NS_DEBUG_WARNING, ToString(ConstRawRangeBoundary
::FromChild(*child)).c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1122)
;
1123 const nsINode* const parentOrShadowHostNode =
1124 child->GetParentOrShadowHostNode();
1125 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}"
, ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode
->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode
? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr
}) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1135)
1126 fmt::format(NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}"
, ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode
->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode
? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr
}) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1135)
1127 "\nparent={}\nlength={}\nshadow={}",NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}"
, ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode
->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode
? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr
}) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1135)
1128 ToString(RefPtr{parentOrShadowHostNode}).c_str(),NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}"
, ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode
->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode
? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr
}) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1135)
1129 parentOrShadowHostNode->GetChildCount(),NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}"
, ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode
->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode
? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr
}) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1135)
1130 ToString(NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}"
, ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode
->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode
? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr
}) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1135)
1131 RefPtr{parentOrShadowHostNodeNS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}"
, ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode
->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode
? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr
}) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1135)
1132 ? parentOrShadowHostNode->GetShadowRoot<aKind>()NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}"
, ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode
->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode
? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr
}) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1135)
1133 : nullptr})NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}"
, ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode
->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode
? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr
}) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1135)
1134 .c_str())NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}"
, ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode
->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode
? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr
}) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1135)
1135 .c_str())NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "\nparent={}\nlength={}\nshadow={}"
, ToString(RefPtr{parentOrShadowHostNode}).c_str(), parentOrShadowHostNode
->GetChildCount(), ToString( RefPtr{parentOrShadowHostNode
? parentOrShadowHostNode->GetShadowRoot<aKind>() : nullptr
}) .c_str()) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1135)
;
1136 } else if constexpr (aKind == TreeKind::FlatForSelection) {
1137 if (child->GetParentNode() == mClosestCommonAncestor) {
1138 // It's okay to compare the non-assigned children of a shadow host
1139 // with the shadow root or another non-assigned child if we're
1140 // handling the flattened tree for selection.
1141 if (mClosestCommonAncestor->GetShadowRootForSelection()) {
1142 return;
1143 }
1144 // It's okay to compare the fallback content of a <slot> which has
1145 // some assigned nodes and a parent of the flattened tree if we're
1146 // handling the flattened tree for selection.
1147 if (mClosestCommonAncestor
1148 ->GetAsHTMLSlotElementIfFilledForSelection()) {
1149 return;
1150 }
1151 }
1152 }
1153 const Maybe<size_t> index =
1154 GetClosestCommonAncestorChildIndex(aInclusiveAncestors);
1155 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child "
"of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n"
" {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor
), ToString(*child), *index ? fmt::format(" + {}", ToString
(*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1167)
1156 fmt::format(NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child "
"of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n"
" {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor
), ToString(*child), *index ? fmt::format(" + {}", ToString
(*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1167)
1157 "The caller cannot compare the position of the child "NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child "
"of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n"
" {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor
), ToString(*child), *index ? fmt::format(" + {}", ToString
(*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1167)
1158 "of the common ancestor due to not in the child list "NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child "
"of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n"
" {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor
), ToString(*child), *index ? fmt::format(" + {}", ToString
(*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1167)
1159 "of the common ancestor (aKind={}):\n"NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child "
"of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n"
" {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor
), ToString(*child), *index ? fmt::format(" + {}", ToString
(*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1167)
1160 " {}\n" // common ancestorNS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child "
"of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n"
" {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor
), ToString(*child), *index ? fmt::format(" + {}", ToString
(*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1167)
1161 " + {}\n" // common ancestor childNS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child "
"of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n"
" {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor
), ToString(*child), *index ? fmt::format(" + {}", ToString
(*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1167)
1162 "{}", // child of common ancestor child if there isNS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child "
"of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n"
" {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor
), ToString(*child), *index ? fmt::format(" + {}", ToString
(*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1167)
1163 aKind, ToString(*mClosestCommonAncestor), ToString(*child),NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child "
"of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n"
" {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor
), ToString(*child), *index ? fmt::format(" + {}", ToString
(*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1167)
1164 *index ? fmt::format(" + {}",NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child "
"of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n"
" {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor
), ToString(*child), *index ? fmt::format(" + {}", ToString
(*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1167)
1165 ToString(*aInclusiveAncestors[*index - 1]))NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child "
"of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n"
" {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor
), ToString(*child), *index ? fmt::format(" + {}", ToString
(*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1167)
1166 : "")NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child "
"of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n"
" {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor
), ToString(*child), *index ? fmt::format(" + {}", ToString
(*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1167)
1167 .c_str())NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "The caller cannot compare the position of the child "
"of the common ancestor due to not in the child list " "of the common ancestor (aKind={}):\n"
" {}\n" " + {}\n" "{}", aKind, ToString(*mClosestCommonAncestor
), ToString(*child), *index ? fmt::format(" + {}", ToString
(*aInclusiveAncestors[*index - 1])) : "") .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1167)
;
1168 }
1169#endif
1170 }
1171
1172 AutoTArray<NodeType*, 30> mInclusiveAncestors1;
1173 AutoTArray<NodeType*, 30> mInclusiveAncestors2;
1174 NodeType* mClosestCommonAncestor = nullptr;
1175 uint32_t mNumberOfCommonAncestors = 0;
1176
1177#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1
1178 nsMutationGuard mMutationGuard;
1179 Maybe<JS::AutoAssertNoGC> mAssertNoGC;
1180#endif
1181};
1182
1183/**
1184 * This class is used to determine whether or not the user is currently
1185 * interacting with the browser. It listens to observer events to toggle the
1186 * value of the sUserActive static.
1187 *
1188 * This class is an internal implementation detail.
1189 * nsContentUtils::GetUserIsInteracting() should be used to access current
1190 * user interaction status.
1191 */
1192class nsContentUtils::UserInteractionObserver final
1193 : public nsIObserver,
1194 public BackgroundHangAnnotator {
1195 public:
1196 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
1197 NS_DECL_NSIOBSERVERvirtual nsresult Observe(nsISupports *aSubject, const char * aTopic
, const char16_t * aData) override;
1198
1199 void Init();
1200 void Shutdown();
1201 void AnnotateHang(BackgroundHangAnnotations& aAnnotations) override;
1202
1203 static Atomic<bool> sUserActive;
1204
1205 private:
1206 ~UserInteractionObserver() = default;
1207};
1208
1209static constexpr nsLiteralCString kRfpPrefs[] = {
1210 "privacy.resistFingerprinting"_ns,
1211 "privacy.resistFingerprinting.pbmode"_ns,
1212 "privacy.fingerprintingProtection"_ns,
1213 "privacy.fingerprintingProtection.pbmode"_ns,
1214 "privacy.fingerprintingProtection.overrides"_ns,
1215 "privacy.baselineFingerprintingProtection"_ns,
1216 "privacy.baselineFingerprintingProtection.overrides"_ns,
1217};
1218
1219static void RecomputeResistFingerprintingAllDocs(const char*, void*) {
1220 AutoTArray<RefPtr<Document>, 64> allDocuments;
1221 Document::GetAllInProcessDocuments(allDocuments);
1222 for (auto& doc : allDocuments) {
1223 doc->RecomputeResistFingerprinting(
1224 /* aForceRefreshRTPCallerType= */ true);
1225 if (auto* pc = doc->GetPresContext()) {
1226 pc->MediaFeatureValuesChanged(
1227 {MediaFeatureChangeReason::PreferenceChange},
1228 MediaFeatureChangePropagation::JustThisDocument);
1229 }
1230 }
1231}
1232
1233// static
1234nsresult nsContentUtils::Init() {
1235 if (sInitialized) {
1236 NS_WARNING("Init() called twice")NS_DebugBreak(NS_DEBUG_WARNING, "Init() called twice", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1236)
;
1237
1238 return NS_OK;
1239 }
1240
1241 nsHTMLTags::AddRefTable();
1242
1243 sXPConnect = nsXPConnect::XPConnect();
1244 // We hold a strong ref to sXPConnect to ensure that it does not go away until
1245 // nsLayoutStatics::Shutdown is happening. Otherwise ~nsXPConnect can be
1246 // triggered by xpcModuleDtor late in shutdown and cause crashes due to
1247 // various stuff already being torn down by then. Note that this means that
1248 // we are effectively making sure that if we leak nsLayoutStatics then we also
1249 // leak nsXPConnect.
1250 NS_ADDREF(sXPConnect)(sXPConnect)->AddRef();
1251
1252 sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager();
1253 if (!sSecurityManager) return NS_ERROR_FAILURE;
1254 NS_ADDREF(sSecurityManager)(sSecurityManager)->AddRef();
1255
1256 sSecurityManager->GetSystemPrincipal(&sSystemPrincipal);
1257 MOZ_ASSERT(sSystemPrincipal)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sSystemPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sSystemPrincipal))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("sSystemPrincipal"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1257); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sSystemPrincipal" ")"); do { MOZ_CrashSequence
(__null, 1257); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1258
1259 RefPtr<NullPrincipal> nullPrincipal =
1260 NullPrincipal::CreateWithoutOriginAttributes();
1261 if (!nullPrincipal) {
1262 return NS_ERROR_FAILURE;
1263 }
1264
1265 nullPrincipal.forget(&sNullSubjectPrincipal);
1266
1267 RefPtr<nsIPrincipal> fingerprintingProtectionPrincipal =
1268 BasePrincipal::CreateContentPrincipal(
1269 "about:fingerprintingprotection"_ns);
1270 if (!fingerprintingProtectionPrincipal) {
1271 return NS_ERROR_FAILURE;
1272 }
1273
1274 fingerprintingProtectionPrincipal.forget(&sFingerprintingProtectionPrincipal);
1275
1276 if (!InitializeEventTable()) return NS_ERROR_FAILURE;
1277
1278 sBlockedScriptRunners = new AutoTArray<nsCOMPtr<nsIRunnable>, 8>;
1279
1280#ifndef RELEASE_OR_BETA
1281 sBypassCSSOMOriginCheck = getenv("MOZ_BYPASS_CSSOM_ORIGIN_CHECK");
1282#endif
1283
1284 Element::InitCCCallbacks();
1285
1286 RefPtr<nsRFPService> rfpService = nsRFPService::GetOrCreate();
1287 MOZ_ASSERT(rfpService)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(rfpService)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(rfpService))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("rfpService", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1287); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rfpService"
")"); do { MOZ_CrashSequence(__null, 1287); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1288
1289 if (XRE_IsParentProcess()) {
1290 AsyncPrecreateStringBundles();
1291
1292#if defined(MOZ_WIDGET_ANDROID)
1293 // On Android, at-shutdown ping submission isn't reliable
1294 // (( because, on Android, we usually get killed, not shut down )).
1295 // To have a chance at submitting the ping, aim for idle after startup.
1296 nsresult rv = NS_DispatchToCurrentThreadQueue(
1297 NS_NewRunnableFunction(
1298 "AndroidUseCounterPingSubmitter",
1299 []() { glean_pings::UseCounters.Submit("idle_startup"_ns); }),
1300 EventQueuePriority::Idle);
1301 // This is mostly best-effort, so if it goes awry, just log.
1302 (void)NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1302)
;
1303#endif // defined(MOZ_WIDGET_ANDROID)
1304
1305 RunOnShutdown(
1306 [&] { glean_pings::UseCounters.Submit("app_shutdown_confirmed"_ns); },
1307 ShutdownPhase::AppShutdownConfirmed);
1308
1309 // On child process, this is initialized in ContentChild.
1310 LookAndFeel::EnsureInit();
1311 }
1312
1313 RefPtr<UserInteractionObserver> uio = new UserInteractionObserver();
1314 uio->Init();
1315 uio.forget(&sUserInteractionObserver);
1316
1317 for (const auto& pref : kRfpPrefs) {
1318 Preferences::RegisterCallback(RecomputeResistFingerprintingAllDocs, pref);
1319 }
1320
1321 mozilla::dom::ReportDeliver::Initialize();
1322
1323 sInitialized = true;
1324
1325 return NS_OK;
1326}
1327
1328bool nsContentUtils::InitJSBytecodeMimeType() {
1329 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1329); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1329); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1330 MOZ_ASSERT(!sJSScriptBytecodeMimeType)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sJSScriptBytecodeMimeType)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!sJSScriptBytecodeMimeType))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!sJSScriptBytecodeMimeType"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1330); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!sJSScriptBytecodeMimeType" ")"); do { MOZ_CrashSequence
(__null, 1330); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1331 MOZ_ASSERT(!sJSModuleBytecodeMimeType)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sJSModuleBytecodeMimeType)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!sJSModuleBytecodeMimeType))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!sJSModuleBytecodeMimeType"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1331); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!sJSModuleBytecodeMimeType" ")"); do { MOZ_CrashSequence
(__null, 1331); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1332
1333 JS::BuildIdCharVector jsBuildId;
1334 if (!JS::GetScriptTranscodingBuildId(&jsBuildId)) {
1335 return false;
1336 }
1337
1338 nsDependentCSubstring jsBuildIdStr(jsBuildId.begin(), jsBuildId.length());
1339 sJSScriptBytecodeMimeType =
1340 new nsCString("javascript/moz-script-bytecode-"_ns + jsBuildIdStr);
1341 sJSModuleBytecodeMimeType =
1342 new nsCString("javascript/moz-module-bytecode-"_ns + jsBuildIdStr);
1343 return true;
1344}
1345
1346void nsContentUtils::GetShiftText(nsAString& text) {
1347 if (!sShiftText) InitializeModifierStrings();
1348 text.Assign(*sShiftText);
1349}
1350
1351void nsContentUtils::GetControlText(nsAString& text) {
1352 if (!sControlText) InitializeModifierStrings();
1353 text.Assign(*sControlText);
1354}
1355
1356void nsContentUtils::GetCommandOrWinText(nsAString& text) {
1357 if (!sCommandOrWinText) {
1358 InitializeModifierStrings();
1359 }
1360 text.Assign(*sCommandOrWinText);
1361}
1362
1363void nsContentUtils::GetAltText(nsAString& text) {
1364 if (!sAltText) InitializeModifierStrings();
1365 text.Assign(*sAltText);
1366}
1367
1368void nsContentUtils::GetModifierSeparatorText(nsAString& text) {
1369 if (!sModifierSeparator) InitializeModifierStrings();
1370 text.Assign(*sModifierSeparator);
1371}
1372
1373void nsContentUtils::InitializeModifierStrings() {
1374 // load the display strings for the keyboard accelerators
1375 nsCOMPtr<nsIStringBundleService> bundleService =
1376 mozilla::components::StringBundle::Service();
1377 nsCOMPtr<nsIStringBundle> bundle;
1378 DebugOnly<nsresult> rv = NS_OK;
1379 if (bundleService) {
1380 rv = bundleService->CreateBundle(
1381 "chrome://global-platform/locale/platformKeys.properties",
1382 getter_AddRefs(bundle));
1383 }
1384
1385 NS_ASSERTION(do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))) && bundle)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "chrome://global/locale/platformKeys.properties could not be loaded"
, "NS_SUCCEEDED(rv) && bundle", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1387); MOZ_PretendNoReturn(); } } while (0)
1386 NS_SUCCEEDED(rv) && bundle,do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))) && bundle)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "chrome://global/locale/platformKeys.properties could not be loaded"
, "NS_SUCCEEDED(rv) && bundle", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1387); MOZ_PretendNoReturn(); } } while (0)
1387 "chrome://global/locale/platformKeys.properties could not be loaded")do { if (!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1
))) && bundle)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "chrome://global/locale/platformKeys.properties could not be loaded"
, "NS_SUCCEEDED(rv) && bundle", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1387); MOZ_PretendNoReturn(); } } while (0)
;
1388 nsAutoString shiftModifier;
1389 nsAutoString commandOrWinModifier;
1390 nsAutoString altModifier;
1391 nsAutoString controlModifier;
1392 nsAutoString modifierSeparator;
1393 if (bundle) {
1394 // macs use symbols for each modifier key, so fetch each from the bundle,
1395 // which also covers i18n
1396 bundle->GetStringFromName("VK_SHIFT", shiftModifier);
1397 bundle->GetStringFromName("VK_COMMAND_OR_WIN", commandOrWinModifier);
1398 bundle->GetStringFromName("VK_ALT", altModifier);
1399 bundle->GetStringFromName("VK_CONTROL", controlModifier);
1400 bundle->GetStringFromName("MODIFIER_SEPARATOR", modifierSeparator);
1401 }
1402 // if any of these don't exist, we get an empty string
1403 sShiftText = new nsString(std::move(shiftModifier));
1404 sCommandOrWinText = new nsString(std::move(commandOrWinModifier));
1405 sAltText = new nsString(std::move(altModifier));
1406 sControlText = new nsString(std::move(controlModifier));
1407 sModifierSeparator = new nsString(std::move(modifierSeparator));
1408}
1409
1410mozilla::EventClassID nsContentUtils::GetEventClassIDFromMessage(
1411 EventMessage aEventMessage) {
1412 switch (aEventMessage) {
1413#define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
1414 case message_: \
1415 return struct_;
1416#include "mozilla/EventNameList.inc"
1417#undef MESSAGE_TO_EVENT
1418 default:
1419 MOZ_ASSERT_UNREACHABLE("Invalid event message?")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: "
"Invalid event message?" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1419); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Invalid event message?" ")"); do
{ MOZ_CrashSequence(__null, 1419); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1420 return eBasicEventClass;
1421 }
1422}
1423
1424bool nsContentUtils::IsExternalProtocol(nsIURI* aURI) {
1425 bool doesNotReturnData = false;
1426 nsresult rv = NS_URIChainHasFlags(
1427 aURI, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA, &doesNotReturnData);
1428 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && doesNotReturnData;
1429}
1430
1431/* static */
1432nsAtom* nsContentUtils::GetEventTypeFromMessage(EventMessage aEventMessage) {
1433 switch (aEventMessage) {
1434#define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
1435 case message_: \
1436 return nsGkAtoms::on##name_;
1437#include "mozilla/EventNameList.inc"
1438#undef MESSAGE_TO_EVENT
1439 default:
1440 return nullptr;
1441 }
1442}
1443
1444/* static */
1445already_AddRefed<nsAtom> nsContentUtils::GetEventType(
1446 const WidgetEvent* aEvent) {
1447 RefPtr<nsAtom> typeAtom =
1448 aEvent->mMessage == eUnidentifiedEvent
1449 ? aEvent->mSpecifiedEventType.get()
1450 : nsContentUtils::GetEventTypeFromMessage(aEvent->mMessage);
1451 return typeAtom.forget();
1452}
1453
1454bool nsContentUtils::InitializeEventTable() {
1455 NS_ASSERTION(!sAtomEventTable, "EventTable already initialized!")do { if (!(!sAtomEventTable)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "EventTable already initialized!", "!sAtomEventTable", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1455); MOZ_PretendNoReturn(); } } while (0)
;
1456 NS_ASSERTION(!sStringEventTable, "EventTable already initialized!")do { if (!(!sStringEventTable)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "EventTable already initialized!", "!sStringEventTable", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 1456); MOZ_PretendNoReturn(); } } while (0)
;
1457
1458 static const EventNameMapping eventArray[] = {
1459#define EVENT(name_, _message, _type, _class) \
1460 {nsGkAtoms::on##name_, _type, _message, _class},
1461#define WINDOW_ONLY_EVENT EVENT
1462#define DOCUMENT_ONLY_EVENTEVENT EVENT
1463#define NON_IDL_EVENT EVENT
1464#include "mozilla/EventNameList.inc"
1465#undef WINDOW_ONLY_EVENT
1466#undef NON_IDL_EVENT
1467#undef EVENT
1468 {nullptr}};
1469
1470 sAtomEventTable =
1471 new nsTHashMap<RefPtr<nsAtom>, EventNameMapping>(std::size(eventArray));
1472 sStringEventTable =
1473 new nsTHashMap<nsStringHashKey, EventNameMapping>(std::size(eventArray));
1474 sUserDefinedEvents = new nsTArray<RefPtr<nsAtom>>(64);
1475
1476 // Subtract one from the length because of the trailing null
1477 for (uint32_t i = 0; i < std::size(eventArray) - 1; ++i) {
1478 MOZ_ASSERT(!sAtomEventTable->Contains(eventArray[i].mAtom),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sAtomEventTable->Contains(eventArray[i].mAtom))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!sAtomEventTable->Contains(eventArray[i].mAtom)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!sAtomEventTable->Contains(eventArray[i].mAtom)"
" (" "Double-defining event name; fix your EventNameList.inc"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1479
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sAtomEventTable->Contains(eventArray[i].mAtom)"
") (" "Double-defining event name; fix your EventNameList.inc"
")"); do { MOZ_CrashSequence(__null, 1479); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1479 "Double-defining event name; fix your EventNameList.inc")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sAtomEventTable->Contains(eventArray[i].mAtom))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!sAtomEventTable->Contains(eventArray[i].mAtom)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!sAtomEventTable->Contains(eventArray[i].mAtom)"
" (" "Double-defining event name; fix your EventNameList.inc"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1479
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sAtomEventTable->Contains(eventArray[i].mAtom)"
") (" "Double-defining event name; fix your EventNameList.inc"
")"); do { MOZ_CrashSequence(__null, 1479); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1480 sAtomEventTable->InsertOrUpdate(eventArray[i].mAtom, eventArray[i]);
1481 sStringEventTable->InsertOrUpdate(
1482 Substring(nsDependentAtomString(eventArray[i].mAtom), 2),
1483 eventArray[i]);
1484 }
1485
1486 return true;
1487}
1488
1489void nsContentUtils::InitializeTouchEventTable() {
1490 static bool sEventTableInitialized = false;
1491 if (!sEventTableInitialized && sAtomEventTable && sStringEventTable) {
1492 sEventTableInitialized = true;
1493 static const EventNameMapping touchEventArray[] = {
1494#define EVENT(name_, _message, _type, _class)
1495#define TOUCH_EVENT(name_, _message, _type, _class) \
1496 {nsGkAtoms::on##name_, _type, _message, _class},
1497#include "mozilla/EventNameList.inc"
1498#undef TOUCH_EVENT
1499#undef EVENT
1500 {nullptr}};
1501 // Subtract one from the length because of the trailing null
1502 for (uint32_t i = 0; i < std::size(touchEventArray) - 1; ++i) {
1503 sAtomEventTable->InsertOrUpdate(touchEventArray[i].mAtom,
1504 touchEventArray[i]);
1505 sStringEventTable->InsertOrUpdate(
1506 Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2),
1507 touchEventArray[i]);
1508 }
1509 }
1510}
1511
1512static bool Is8bit(const nsAString& aString) {
1513 static const char16_t EIGHT_BIT = char16_t(~0x00FF);
1514
1515 for (nsAString::const_char_iterator start = aString.BeginReading(),
1516 end = aString.EndReading();
1517 start != end; ++start) {
1518 if (*start & EIGHT_BIT) {
1519 return false;
1520 }
1521 }
1522
1523 return true;
1524}
1525
1526nsresult nsContentUtils::Btoa(const nsAString& aBinaryData,
1527 nsAString& aAsciiBase64String) {
1528 if (!Is8bit(aBinaryData)) {
1529 aAsciiBase64String.Truncate();
1530 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1531 }
1532
1533 return Base64Encode(aBinaryData, aAsciiBase64String);
1534}
1535
1536nsresult nsContentUtils::Atob(const nsAString& aAsciiBase64String,
1537 nsAString& aBinaryData) {
1538 if (!Is8bit(aAsciiBase64String)) {
1539 aBinaryData.Truncate();
1540 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1541 }
1542
1543 const char16_t* start = aAsciiBase64String.BeginReading();
1544 const char16_t* cur = start;
1545 const char16_t* end = aAsciiBase64String.EndReading();
1546 bool hasWhitespace = false;
1547
1548 while (cur < end) {
1549 if (nsContentUtils::IsHTMLWhitespace(*cur)) {
1550 hasWhitespace = true;
1551 break;
1552 }
1553 cur++;
1554 }
1555
1556 nsresult rv;
1557
1558 if (hasWhitespace) {
1559 nsString trimmedString;
1560
1561 if (!trimmedString.SetCapacity(aAsciiBase64String.Length(), fallible)) {
1562 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1563 }
1564
1565 trimmedString.Append(start, cur - start);
1566
1567 while (cur < end) {
1568 if (!nsContentUtils::IsHTMLWhitespace(*cur)) {
1569 trimmedString.Append(*cur);
1570 }
1571 cur++;
1572 }
1573 rv = Base64Decode(trimmedString, aBinaryData);
1574 } else {
1575 rv = Base64Decode(aAsciiBase64String, aBinaryData);
1576 }
1577
1578 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && rv == NS_ERROR_INVALID_ARG) {
1579 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1580 }
1581 return rv;
1582}
1583
1584bool nsContentUtils::IsAutocompleteEnabled(mozilla::dom::Element* aElement) {
1585 MOZ_ASSERT(aElement, "aElement should not be null!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElement))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aElement" " (" "aElement should not be null!"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1585
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ") (" "aElement should not be null!"
")"); do { MOZ_CrashSequence(__null, 1585); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1586
1587 nsAutoString autocomplete;
1588
1589 if (auto* input = HTMLInputElement::FromNodeOrNull(aElement)) {
1590 input->GetAutocomplete(autocomplete);
1591 } else if (auto* textarea = HTMLTextAreaElement::FromNodeOrNull(aElement)) {
1592 textarea->GetAutocomplete(autocomplete);
1593 }
1594
1595 if (autocomplete.IsEmpty()) {
1596 auto* control = nsGenericHTMLFormControlElement::FromNode(aElement);
1597 auto* form = control->GetFormInternal();
1598 if (!form) {
1599 return true;
1600 }
1601
1602 form->GetAutocomplete(autocomplete);
1603 }
1604
1605 return !autocomplete.EqualsLiteral("off");
1606}
1607
1608nsContentUtils::AutocompleteAttrState
1609nsContentUtils::SerializeAutocompleteAttribute(
1610 const nsAttrValue* aAttr, nsAString& aResult,
1611 AutocompleteAttrState aCachedState) {
1612 if (!aAttr ||
1613 aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) {
1614 return aCachedState;
1615 }
1616
1617 if (aCachedState == nsContentUtils::eAutocompleteAttrState_Valid) {
1618 uint32_t atomCount = aAttr->GetAtomCount();
1619 for (uint32_t i = 0; i < atomCount; i++) {
1620 if (i != 0) {
1621 aResult.Append(' ');
1622 }
1623 aResult.Append(nsDependentAtomString(aAttr->AtomAt(i)));
1624 }
1625 nsContentUtils::ASCIIToLower(aResult);
1626 return aCachedState;
1627 }
1628
1629 aResult.Truncate();
1630
1631 mozilla::dom::AutocompleteInfo info;
1632 AutocompleteAttrState state =
1633 InternalSerializeAutocompleteAttribute(aAttr, info);
1634 if (state == eAutocompleteAttrState_Valid) {
1635 // Concatenate the info fields.
1636 aResult = info.mSection;
1637
1638 if (!info.mAddressType.IsEmpty()) {
1639 if (!aResult.IsEmpty()) {
1640 aResult += ' ';
1641 }
1642 aResult += info.mAddressType;
1643 }
1644
1645 if (!info.mContactType.IsEmpty()) {
1646 if (!aResult.IsEmpty()) {
1647 aResult += ' ';
1648 }
1649 aResult += info.mContactType;
1650 }
1651
1652 if (!info.mFieldName.IsEmpty()) {
1653 if (!aResult.IsEmpty()) {
1654 aResult += ' ';
1655 }
1656 aResult += info.mFieldName;
1657 }
1658
1659 // The autocomplete attribute value "webauthn" is interpreted as both a
1660 // field name and a credential type. The corresponding IDL-exposed autofill
1661 // value is "webauthn", not "webauthn webauthn".
1662 if (!info.mCredentialType.IsEmpty() &&
1663 !(info.mCredentialType.Equals(u"webauthn"_ns) &&
1664 info.mCredentialType.Equals(aResult))) {
1665 if (!aResult.IsEmpty()) {
1666 aResult += ' ';
1667 }
1668 aResult += info.mCredentialType;
1669 }
1670 }
1671
1672 return state;
1673}
1674
1675nsContentUtils::AutocompleteAttrState
1676nsContentUtils::SerializeAutocompleteAttribute(
1677 const nsAttrValue* aAttr, mozilla::dom::AutocompleteInfo& aInfo,
1678 AutocompleteAttrState aCachedState, bool aGrantAllValidValue) {
1679 if (!aAttr ||
1680 aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) {
1681 return aCachedState;
1682 }
1683
1684 return InternalSerializeAutocompleteAttribute(aAttr, aInfo,
1685 aGrantAllValidValue);
1686}
1687
1688/**
1689 * Helper to validate the @autocomplete tokens.
1690 *
1691 * @return {AutocompleteAttrState} The state of the attribute (invalid/valid).
1692 */
1693nsContentUtils::AutocompleteAttrState
1694nsContentUtils::InternalSerializeAutocompleteAttribute(
1695 const nsAttrValue* aAttrVal, mozilla::dom::AutocompleteInfo& aInfo,
1696 bool aGrantAllValidValue) {
1697 // No autocomplete attribute so we are done
1698 if (!aAttrVal) {
1699 return eAutocompleteAttrState_Invalid;
1700 }
1701
1702 uint32_t numTokens = aAttrVal->GetAtomCount();
1703 if (!numTokens || numTokens > INT32_MAX(2147483647)) {
1704 return eAutocompleteAttrState_Invalid;
1705 }
1706
1707 uint32_t index = numTokens - 1;
1708 nsString tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1709 AutocompleteCategory category;
1710 nsAttrValue enumValue;
1711 nsAutoString credentialTypeStr;
1712
1713 bool result = enumValue.ParseEnumValue(
1714 tokenString, kAutocompleteCredentialTypeTable, false);
1715 if (result) {
1716 if (!enumValue.Equals(u"webauthn"_ns, eIgnoreCase) || numTokens > 5) {
1717 return eAutocompleteAttrState_Invalid;
1718 }
1719 enumValue.ToString(credentialTypeStr);
1720 ASCIIToLower(credentialTypeStr);
1721 // category is Credential and the indexth token is "webauthn"
1722 if (index == 0) {
1723 aInfo.mFieldName.Assign(credentialTypeStr);
1724 aInfo.mCredentialType.Assign(credentialTypeStr);
1725 return eAutocompleteAttrState_Valid;
1726 }
1727
1728 --index;
1729 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1730
1731 // Only the Normal and Contact categories are allowed with webauthn
1732 // - disallow Credential
1733 if (enumValue.ParseEnumValue(tokenString, kAutocompleteCredentialTypeTable,
1734 false)) {
1735 return eAutocompleteAttrState_Invalid;
1736 }
1737 // - disallow Off and Automatic
1738 if (enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable,
1739 false)) {
1740 if (enumValue.Equals(u"off"_ns, eIgnoreCase) ||
1741 enumValue.Equals(u"on"_ns, eIgnoreCase)) {
1742 return eAutocompleteAttrState_Invalid;
1743 }
1744 }
1745
1746 // Proceed to process the remaining tokens as if "webauthn" was not present.
1747 // We need to decrement numTokens to enforce the correct per-category limits
1748 // on the maximum number of tokens.
1749 --numTokens;
1750 }
1751
1752 bool unsupported = false;
1753 if (!aGrantAllValidValue) {
1754 unsupported = enumValue.ParseEnumValue(
1755 tokenString, kAutocompleteUnsupportedFieldNameTable, false);
1756 if (unsupported) {
1757 return eAutocompleteAttrState_Invalid;
1758 }
1759 }
1760
1761 nsAutoString fieldNameStr;
1762 result =
1763 enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable, false);
1764
1765 if (result) {
1766 // Off/Automatic/Normal categories.
1767 if (enumValue.Equals(u"off"_ns, eIgnoreCase) ||
1768 enumValue.Equals(u"on"_ns, eIgnoreCase)) {
1769 if (numTokens > 1) {
1770 return eAutocompleteAttrState_Invalid;
1771 }
1772 enumValue.ToString(fieldNameStr);
1773 ASCIIToLower(fieldNameStr);
1774 aInfo.mFieldName.Assign(fieldNameStr);
1775 aInfo.mCredentialType.Assign(credentialTypeStr);
1776 aInfo.mCanAutomaticallyPersist =
1777 !enumValue.Equals(u"off"_ns, eIgnoreCase);
1778 return eAutocompleteAttrState_Valid;
1779 }
1780
1781 // Only allow on/off if form autofill @autocomplete values aren't enabled
1782 // and it doesn't grant all valid values.
1783 if (!StaticPrefs::dom_forms_autocomplete_formautofill() &&
1784 !aGrantAllValidValue) {
1785 return eAutocompleteAttrState_Invalid;
1786 }
1787
1788 // Normal category
1789 if (numTokens > 3) {
1790 return eAutocompleteAttrState_Invalid;
1791 }
1792 category = eAutocompleteCategory_NORMAL;
1793 } else { // Check if the last token is of the contact category instead.
1794 // Only allow on/off if form autofill @autocomplete values aren't enabled
1795 // and it doesn't grant all valid values.
1796 if (!StaticPrefs::dom_forms_autocomplete_formautofill() &&
1797 !aGrantAllValidValue) {
1798 return eAutocompleteAttrState_Invalid;
1799 }
1800
1801 result = enumValue.ParseEnumValue(
1802 tokenString, kAutocompleteContactFieldNameTable, false);
1803 if (!result || numTokens > 4) {
1804 return eAutocompleteAttrState_Invalid;
1805 }
1806
1807 category = eAutocompleteCategory_CONTACT;
1808 }
1809
1810 enumValue.ToString(fieldNameStr);
1811 ASCIIToLower(fieldNameStr);
1812
1813 aInfo.mFieldName.Assign(fieldNameStr);
1814 aInfo.mCredentialType.Assign(credentialTypeStr);
1815 aInfo.mCanAutomaticallyPersist = !enumValue.ParseEnumValue(
1816 tokenString, kAutocompleteNoPersistFieldNameTable, false);
1817
1818 // We are done if this was the only token.
1819 if (numTokens == 1) {
1820 return eAutocompleteAttrState_Valid;
1821 }
1822
1823 --index;
1824 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1825
1826 if (category == eAutocompleteCategory_CONTACT) {
1827 if (!aGrantAllValidValue) {
1828 unsupported = enumValue.ParseEnumValue(
1829 tokenString, kAutocompleteUnsupportedContactFieldHintTable, false);
1830 if (unsupported) {
1831 return eAutocompleteAttrState_Invalid;
1832 }
1833 }
1834
1835 nsAttrValue contactFieldHint;
1836 result = contactFieldHint.ParseEnumValue(
1837 tokenString, kAutocompleteContactFieldHintTable, false);
1838 if (result) {
1839 nsAutoString contactFieldHintString;
1840 contactFieldHint.ToString(contactFieldHintString);
1841 ASCIIToLower(contactFieldHintString);
1842 aInfo.mContactType.Assign(contactFieldHintString);
1843 if (index == 0) {
1844 return eAutocompleteAttrState_Valid;
1845 }
1846 --index;
1847 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1848 }
1849 }
1850
1851 // Check for billing/shipping tokens
1852 nsAttrValue fieldHint;
1853 if (fieldHint.ParseEnumValue(tokenString, kAutocompleteFieldHintTable,
1854 false)) {
1855 nsString fieldHintString;
1856 fieldHint.ToString(fieldHintString);
1857 ASCIIToLower(fieldHintString);
1858 aInfo.mAddressType.Assign(fieldHintString);
1859 if (index == 0) {
1860 return eAutocompleteAttrState_Valid;
1861 }
1862 --index;
1863 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1864 }
1865
1866 // Check for section-* token
1867 const nsDependentSubstring& section = Substring(tokenString, 0, 8);
1868 if (section.LowerCaseEqualsASCII("section-")) {
1869 ASCIIToLower(tokenString);
1870 aInfo.mSection.Assign(tokenString);
1871 if (index == 0) {
1872 return eAutocompleteAttrState_Valid;
1873 }
1874 }
1875
1876 // Clear the fields as the autocomplete attribute is invalid.
1877 aInfo.mSection.Truncate();
1878 aInfo.mAddressType.Truncate();
1879 aInfo.mContactType.Truncate();
1880 aInfo.mFieldName.Truncate();
1881 aInfo.mCredentialType.Truncate();
1882
1883 return eAutocompleteAttrState_Invalid;
1884}
1885
1886// Parse an integer according to HTML spec
1887template <class CharT>
1888int32_t nsContentUtils::ParseHTMLIntegerImpl(
1889 const CharT* aStart, const CharT* aEnd,
1890 ParseHTMLIntegerResultFlags* aResult) {
1891 int result = eParseHTMLInteger_NoFlags;
1892
1893 const CharT* iter = aStart;
1894
1895 while (iter != aEnd && nsContentUtils::IsHTMLWhitespace(*iter)) {
1896 result |= eParseHTMLInteger_NonStandard;
1897 ++iter;
1898 }
1899
1900 if (iter == aEnd) {
1901 result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
1902 *aResult = (ParseHTMLIntegerResultFlags)result;
1903 return 0;
1904 }
1905
1906 int sign = 1;
1907 if (*iter == CharT('-')) {
1908 sign = -1;
1909 result |= eParseHTMLInteger_Negative;
1910 ++iter;
1911 } else if (*iter == CharT('+')) {
1912 result |= eParseHTMLInteger_NonStandard;
1913 ++iter;
1914 }
1915
1916 bool foundValue = false;
1917 CheckedInt32 value = 0;
1918
1919 // Check for leading zeros first.
1920 uint64_t leadingZeros = 0;
1921 while (iter != aEnd) {
1922 if (*iter != CharT('0')) {
1923 break;
1924 }
1925
1926 ++leadingZeros;
1927 foundValue = true;
1928 ++iter;
1929 }
1930
1931 while (iter != aEnd) {
1932 if (*iter >= CharT('0') && *iter <= CharT('9')) {
1933 value = (value * 10) + (*iter - CharT('0')) * sign;
1934 ++iter;
1935 if (!value.isValid()) {
1936 result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorOverflow;
1937 break;
1938 }
1939 foundValue = true;
1940 } else {
1941 break;
1942 }
1943 }
1944
1945 if (!foundValue) {
1946 result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
1947 }
1948
1949 if (value.isValid() &&
1950 ((leadingZeros > 1 || (leadingZeros == 1 && !(value == 0))) ||
1951 (sign == -1 && value == 0))) {
1952 result |= eParseHTMLInteger_NonStandard;
1953 }
1954
1955 if (iter != aEnd) {
1956 result |= eParseHTMLInteger_DidNotConsumeAllInput;
1957 }
1958
1959 *aResult = (ParseHTMLIntegerResultFlags)result;
1960 return value.isValid() ? value.value() : 0;
1961}
1962
1963// Parse an integer according to HTML spec
1964int32_t nsContentUtils::ParseHTMLInteger(const char16_t* aStart,
1965 const char16_t* aEnd,
1966 ParseHTMLIntegerResultFlags* aResult) {
1967 return ParseHTMLIntegerImpl(aStart, aEnd, aResult);
1968}
1969
1970int32_t nsContentUtils::ParseHTMLInteger(const char* aStart, const char* aEnd,
1971 ParseHTMLIntegerResultFlags* aResult) {
1972 return ParseHTMLIntegerImpl(aStart, aEnd, aResult);
1973}
1974
1975Maybe<double> nsContentUtils::ParseHTMLFloatingPointNumber(
1976 const nsAString& aString) {
1977 // Check if it is a valid floating-point number first since the result of
1978 // nsString.ToDouble() is more lenient than the spec,
1979 // https://html.spec.whatwg.org/#valid-floating-point-number
1980 nsAString::const_iterator iter, end;
1981 aString.BeginReading(iter);
1982 aString.EndReading(end);
1983
1984 if (iter == end) {
1985 return {};
1986 }
1987
1988 if (*iter == char16_t('-') && ++iter == end) {
1989 return {};
1990 }
1991
1992 if (IsAsciiDigit(*iter)) {
1993 for (; iter != end && IsAsciiDigit(*iter); ++iter);
1994 } else if (*iter == char16_t('.')) {
1995 // Do nothing, jumps to fraction part
1996 } else {
1997 return {};
1998 }
1999
2000 // Fraction
2001 if (*iter == char16_t('.')) {
2002 ++iter;
2003 if (iter == end || !IsAsciiDigit(*iter)) {
2004 // U+002E FULL STOP character (.) must be followed by one or more ASCII
2005 // digits
2006 return {};
2007 }
2008
2009 for (; iter != end && IsAsciiDigit(*iter); ++iter);
2010 }
2011
2012 if (iter != end && (*iter == char16_t('e') || *iter == char16_t('E'))) {
2013 ++iter;
2014 if (*iter == char16_t('-') || *iter == char16_t('+')) {
2015 ++iter;
2016 }
2017
2018 if (iter == end || !IsAsciiDigit(*iter)) {
2019 // Should have one or more ASCII digits
2020 return {};
2021 }
2022
2023 for (; iter != end && IsAsciiDigit(*iter); ++iter);
2024 }
2025
2026 if (iter != end) {
2027 return {};
2028 }
2029
2030 nsresult rv;
2031 double result = PromiseFlatStringTPromiseFlatString<char16_t>(aString).ToDouble(&rv);
2032 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2033 return {};
2034 }
2035 return Some(result);
2036}
2037
2038#define SKIP_WHITESPACE(iter, end_iter, end_res)while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(
iter))) { ++(iter); } if ((iter) == (end_iter)) { return (end_res
); }
\
2039 while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \
2040 ++(iter); \
2041 } \
2042 if ((iter) == (end_iter)) { \
2043 return (end_res); \
2044 }
2045
2046#define SKIP_ATTR_NAME(iter, end_iter)while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*
(iter)) && *(iter) != '=') { ++(iter); }
\
2047 while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*(iter)) && \
2048 *(iter) != '=') { \
2049 ++(iter); \
2050 }
2051
2052bool nsContentUtils::GetPseudoAttributeValue(const nsString& aSource,
2053 nsAtom* aName, nsAString& aValue) {
2054 aValue.Truncate();
2055
2056 const char16_t* start = aSource.get();
2057 const char16_t* end = start + aSource.Length();
2058 const char16_t* iter;
2059
2060 while (start != end) {
2061 SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start
))) { ++(start); } if ((start) == (end)) { return (false); }
2062 iter = start;
2063 SKIP_ATTR_NAME(iter, end)while ((iter) != (end) && !nsCRT::IsAsciiSpace(*(iter
)) && *(iter) != '=') { ++(iter); }
2064
2065 if (start == iter) {
2066 return false;
2067 }
2068
2069 // Remember the attr name.
2070 const nsDependentSubstring& attrName = Substring(start, iter);
2071
2072 // Now check whether this is a valid name="value" pair.
2073 start = iter;
2074 SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start
))) { ++(start); } if ((start) == (end)) { return (false); }
2075 if (*start != '=') {
2076 // No '=', so this is not a name="value" pair. We don't know
2077 // what it is, and we have no way to handle it.
2078 return false;
2079 }
2080
2081 // Have to skip the value.
2082 ++start;
2083 SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start
))) { ++(start); } if ((start) == (end)) { return (false); }
2084 char16_t q = *start;
2085 if (q != kQuote && q != kApostrophe) {
2086 // Not a valid quoted value, so bail.
2087 return false;
2088 }
2089
2090 ++start; // Point to the first char of the value.
2091 iter = start;
2092
2093 while (iter != end && *iter != q) {
2094 ++iter;
2095 }
2096
2097 if (iter == end) {
2098 // Oops, unterminated quoted string.
2099 return false;
2100 }
2101
2102 // At this point attrName holds the name of the "attribute" and
2103 // the value is between start and iter.
2104
2105 if (aName->Equals(attrName)) {
2106 // We'll accumulate as many characters as possible (until we hit either
2107 // the end of the string or the beginning of an entity). Chunks will be
2108 // delimited by start and chunkEnd.
2109 const char16_t* chunkEnd = start;
2110 while (chunkEnd != iter) {
2111 if (*chunkEnd == kLessThan) {
2112 aValue.Truncate();
2113
2114 return false;
2115 }
2116
2117 if (*chunkEnd == kAmpersand) {
2118 aValue.Append(start, chunkEnd - start);
2119
2120 const char16_t* afterEntity = nullptr;
2121 char16_t result[2];
2122 uint32_t count = MOZ_XMLTranslateEntity(
2123 reinterpret_cast<const char*>(chunkEnd),
2124 reinterpret_cast<const char*>(iter),
2125 reinterpret_cast<const char**>(&afterEntity), result);
2126 if (count == 0) {
2127 aValue.Truncate();
2128
2129 return false;
2130 }
2131
2132 aValue.Append(result, count);
2133
2134 // Advance to after the entity and begin a new chunk.
2135 start = chunkEnd = afterEntity;
2136 } else {
2137 ++chunkEnd;
2138 }
2139 }
2140
2141 // Append remainder.
2142 aValue.Append(start, iter - start);
2143
2144 return true;
2145 }
2146
2147 // Resume scanning after the end of the attribute value (past the quote
2148 // char).
2149 start = iter + 1;
2150 }
2151
2152 return false;
2153}
2154
2155bool nsContentUtils::IsJavaScriptLanguage(const nsString& aName) {
2156 // Create MIME type as "text/" + given input
2157 nsAutoString mimeType(u"text/");
2158 mimeType.Append(aName);
2159
2160 return IsJavascriptMIMEType(mimeType);
2161}
2162
2163void nsContentUtils::SplitMimeType(const nsAString& aValue, nsString& aType,
2164 nsString& aParams) {
2165 aType.Truncate();
2166 aParams.Truncate();
2167 int32_t semiIndex = aValue.FindChar(char16_t(';'));
2168 if (-1 != semiIndex) {
2169 aType = Substring(aValue, 0, semiIndex);
2170 aParams =
2171 Substring(aValue, semiIndex + 1, aValue.Length() - (semiIndex + 1));
2172 aParams.StripWhitespace();
2173 } else {
2174 aType = aValue;
2175 }
2176 aType.StripWhitespace();
2177}
2178
2179/**
2180 * A helper function that parses a sandbox attribute (of an <iframe> or a CSP
2181 * directive) and converts it to the set of flags used internally.
2182 *
2183 * @param aSandboxAttr the sandbox attribute
2184 * @return the set of flags (SANDBOXED_NONE if aSandboxAttr is
2185 * null)
2186 */
2187uint32_t nsContentUtils::ParseSandboxAttributeToFlags(
2188 const nsAttrValue* aSandboxAttr) {
2189 if (!aSandboxAttr) {
2190 return SANDBOXED_NONE;
2191 }
2192
2193 uint32_t out = SANDBOX_ALL_FLAGS;
2194
2195#define SANDBOX_KEYWORD(string, atom, flags) \
2196 if (aSandboxAttr->Contains(nsGkAtoms::atom, eIgnoreCase)) { \
2197 out &= ~(flags); \
2198 }
2199#include "IframeSandboxKeywordList.inc"
2200#undef SANDBOX_KEYWORD
2201
2202 return out;
2203}
2204
2205/**
2206 * A helper function that checks if a string matches a valid sandbox flag.
2207 *
2208 * @param aFlag the potential sandbox flag.
2209 * @return true if the flag is a sandbox flag.
2210 */
2211bool nsContentUtils::IsValidSandboxFlag(const nsAString& aFlag) {
2212#define SANDBOX_KEYWORD(string, atom, flags) \
2213 if (EqualsIgnoreASCIICase(nsDependentAtomString(nsGkAtoms::atom), aFlag)) { \
2214 return true; \
2215 }
2216#include "IframeSandboxKeywordList.inc"
2217#undef SANDBOX_KEYWORD
2218 return false;
2219}
2220
2221/**
2222 * A helper function that returns a string attribute corresponding to the
2223 * sandbox flags.
2224 *
2225 * @param aFlags the sandbox flags
2226 * @param aString the attribute corresponding to the flags (null if aFlags
2227 * is zero)
2228 */
2229void nsContentUtils::SandboxFlagsToString(uint32_t aFlags, nsAString& aString) {
2230 if (!aFlags) {
2231 SetDOMStringToNull(aString);
2232 return;
2233 }
2234
2235 aString.Truncate();
2236
2237#define SANDBOX_KEYWORD(string, atom, flags) \
2238 if (!(aFlags & (flags))) { \
2239 if (!aString.IsEmpty()) { \
2240 aString.AppendLiteral(u" "); \
2241 } \
2242 aString.Append(nsDependentAtomString(nsGkAtoms::atom)); \
2243 }
2244#include "IframeSandboxKeywordList.inc"
2245#undef SANDBOX_KEYWORD
2246}
2247
2248nsIBidiKeyboard* nsContentUtils::GetBidiKeyboard() {
2249 if (!sBidiKeyboard) {
2250 sBidiKeyboard = nsIWidget::CreateBidiKeyboard();
2251 }
2252 return sBidiKeyboard;
2253}
2254
2255// static
2256bool nsContentUtils::IsAlphanumeric(uint32_t aChar) {
2257 nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);
2258
2259 return (cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber);
2260}
2261
2262// static
2263bool nsContentUtils::IsAlphanumericOrSymbol(uint32_t aChar) {
2264 nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);
2265
2266 return cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber ||
2267 cat == nsUGenCategory::kSymbol;
2268}
2269
2270// static
2271bool nsContentUtils::IsHyphen(uint32_t aChar) {
2272 // Characters treated as hyphens for the purpose of "emergency" breaking
2273 // when the content would otherwise overflow.
2274 return aChar == uint32_t('-') || // HYPHEN-MINUS
2275 aChar == 0x2010 || // HYPHEN
2276 aChar == 0x2012 || // FIGURE DASH
2277 aChar == 0x2013 || // EN DASH
2278 aChar == 0x058A; // ARMENIAN HYPHEN
2279}
2280
2281/* static */
2282bool nsContentUtils::IsHTMLWhitespace(char16_t aChar) {
2283 return aChar == char16_t(0x0009) || aChar == char16_t(0x000A) ||
2284 aChar == char16_t(0x000C) || aChar == char16_t(0x000D) ||
2285 aChar == char16_t(0x0020);
2286}
2287
2288/* static */
2289bool nsContentUtils::IsHTMLWhitespaceOrNBSP(char16_t aChar) {
2290 return IsHTMLWhitespace(aChar) || aChar == char16_t(0xA0);
2291}
2292
2293/* static */
2294bool nsContentUtils::IsHTMLBlockLevelElement(nsIContent* aContent) {
2295 return aContent->IsAnyOfHTMLElements(
2296 nsGkAtoms::address, nsGkAtoms::article, nsGkAtoms::aside,
2297 nsGkAtoms::blockquote, nsGkAtoms::center, nsGkAtoms::dir, nsGkAtoms::div,
2298 nsGkAtoms::dl, // XXX why not dt and dd?
2299 nsGkAtoms::fieldset,
2300 nsGkAtoms::figure, // XXX shouldn't figcaption be on this list
2301 nsGkAtoms::footer, nsGkAtoms::form, nsGkAtoms::h1, nsGkAtoms::h2,
2302 nsGkAtoms::h3, nsGkAtoms::h4, nsGkAtoms::h5, nsGkAtoms::h6,
2303 nsGkAtoms::header, nsGkAtoms::hgroup, nsGkAtoms::hr, nsGkAtoms::li,
2304 nsGkAtoms::listing, nsGkAtoms::menu, nsGkAtoms::nav, nsGkAtoms::ol,
2305 nsGkAtoms::p, nsGkAtoms::pre, nsGkAtoms::section, nsGkAtoms::table,
2306 nsGkAtoms::ul, nsGkAtoms::xmp);
2307}
2308
2309// static
2310int32_t nsContentUtils::ParseLegacyFontSize(const nsAString& aValue) {
2311 nsAString::const_iterator iter, end;
2312 aValue.BeginReading(iter);
2313 aValue.EndReading(end);
2314
2315 while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
2316 ++iter;
2317 }
2318
2319 if (iter == end) {
2320 return 0;
2321 }
2322
2323 bool relative = false;
2324 bool negate = false;
2325 if (*iter == char16_t('-')) {
2326 relative = true;
2327 negate = true;
2328 ++iter;
2329 } else if (*iter == char16_t('+')) {
2330 relative = true;
2331 ++iter;
2332 }
2333
2334 if (iter == end || *iter < char16_t('0') || *iter > char16_t('9')) {
2335 return 0;
2336 }
2337
2338 // We don't have to worry about overflow, since we can bail out as soon as
2339 // we're bigger than 7.
2340 int32_t value = 0;
2341 while (iter != end && *iter >= char16_t('0') && *iter <= char16_t('9')) {
2342 value = 10 * value + (*iter - char16_t('0'));
2343 if (value >= 7) {
2344 break;
2345 }
2346 ++iter;
2347 }
2348
2349 if (relative) {
2350 if (negate) {
2351 value = 3 - value;
2352 } else {
2353 value = 3 + value;
2354 }
2355 }
2356
2357 return std::clamp(value, 1, 7);
2358}
2359
2360/* static */
2361void nsContentUtils::GetOfflineAppManifest(Document* aDocument, nsIURI** aURI) {
2362 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2362); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2362); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2363 MOZ_ASSERT(aDocument)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDocument))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aDocument", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 2363); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { MOZ_CrashSequence(__null, 2363); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2364 *aURI = nullptr;
2365
2366 if (aDocument->GetController().isSome()) {
2367 return;
2368 }
2369
2370 Element* docElement = aDocument->GetRootElement();
2371 if (!docElement) {
2372 return;
2373 }
2374
2375 nsAutoString manifestSpec;
2376 docElement->GetAttr(nsGkAtoms::manifest, manifestSpec);
2377
2378 // Manifest URIs can't have fragment identifiers.
2379 if (manifestSpec.IsEmpty() || manifestSpec.Contains('#')) {
2380 return;
2381 }
2382
2383 nsContentUtils::NewURIWithDocumentCharset(aURI, manifestSpec, aDocument,
2384 aDocument->GetDocBaseURI());
2385}
2386
2387/* static */
2388bool nsContentUtils::OfflineAppAllowed(nsIURI* aURI) { return false; }
2389
2390/* static */
2391bool nsContentUtils::OfflineAppAllowed(nsIPrincipal* aPrincipal) {
2392 return false;
2393}
2394// Static
2395bool nsContentUtils::IsErrorPage(nsIURI* aURI) {
2396 if (!aURI) {
2397 return false;
2398 }
2399
2400 if (!aURI->SchemeIs("about")) {
2401 return false;
2402 }
2403
2404 nsAutoCString name;
2405 nsresult rv = NS_GetAboutModuleName(aURI, name);
2406 NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 2406); return false; } } while (false)
;
2407
2408 return name.EqualsLiteral("certerror") || name.EqualsLiteral("neterror") ||
2409 name.EqualsLiteral("blocked");
2410}
2411
2412// static
2413void nsContentUtils::Shutdown() {
2414 sInitialized = false;
2415
2416 nsHTMLTags::ReleaseTable();
2417
2418 NS_IF_RELEASE(sContentPolicyService)do { if (sContentPolicyService) { (sContentPolicyService)->
Release(); (sContentPolicyService) = 0; } } while (0)
;
2419 sTriedToGetContentPolicy = false;
2420 for (StaticRefPtr<nsIStringBundle>& bundle : sStringBundles) {
2421 bundle = nullptr;
2422 }
2423
2424 NS_IF_RELEASE(sStringBundleService)do { if (sStringBundleService) { (sStringBundleService)->Release
(); (sStringBundleService) = 0; } } while (0)
;
2425 NS_IF_RELEASE(sConsoleService)do { if (sConsoleService) { (sConsoleService)->Release(); (
sConsoleService) = 0; } } while (0)
;
2426 NS_IF_RELEASE(sXPConnect)do { if (sXPConnect) { (sXPConnect)->Release(); (sXPConnect
) = 0; } } while (0)
;
2427 NS_IF_RELEASE(sSecurityManager)do { if (sSecurityManager) { (sSecurityManager)->Release()
; (sSecurityManager) = 0; } } while (0)
;
2428 NS_IF_RELEASE(sSystemPrincipal)do { if (sSystemPrincipal) { (sSystemPrincipal)->Release()
; (sSystemPrincipal) = 0; } } while (0)
;
2429 NS_IF_RELEASE(sNullSubjectPrincipal)do { if (sNullSubjectPrincipal) { (sNullSubjectPrincipal)->
Release(); (sNullSubjectPrincipal) = 0; } } while (0)
;
2430 NS_IF_RELEASE(sFingerprintingProtectionPrincipal)do { if (sFingerprintingProtectionPrincipal) { (sFingerprintingProtectionPrincipal
)->Release(); (sFingerprintingProtectionPrincipal) = 0; } }
while (0)
;
2431
2432 sBidiKeyboard = nullptr;
2433
2434 delete sAtomEventTable;
2435 sAtomEventTable = nullptr;
2436 delete sStringEventTable;
2437 sStringEventTable = nullptr;
2438 delete sUserDefinedEvents;
2439 sUserDefinedEvents = nullptr;
2440
2441 // Managers left in the list remove themselves from it when they're deleted,
2442 // which can happen after this point.
2443 NS_ASSERTION(NodeOwnedObjectList<EventListenerManager>::IsEmpty(),do { if (!(NodeOwnedObjectList<EventListenerManager>::IsEmpty
())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Node event listener manager list not empty at shutdown!"
, "NodeOwnedObjectList<EventListenerManager>::IsEmpty()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2444); MOZ_PretendNoReturn
(); } } while (0)
2444 "Node event listener manager list not empty at shutdown!")do { if (!(NodeOwnedObjectList<EventListenerManager>::IsEmpty
())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Node event listener manager list not empty at shutdown!"
, "NodeOwnedObjectList<EventListenerManager>::IsEmpty()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2444); MOZ_PretendNoReturn
(); } } while (0)
;
2445
2446 MOZ_ASSERT_IF(sDOMArenaHashtable, sDOMArenaHashtable->Count() == 0)do { if (sDOMArenaHashtable) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(sDOMArenaHashtable->Count
() == 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(sDOMArenaHashtable->Count() == 0))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("sDOMArenaHashtable->Count() == 0"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2446); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sDOMArenaHashtable->Count() == 0" ")");
do { MOZ_CrashSequence(__null, 2446); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2447 delete sDOMArenaHashtable;
2448 sDOMArenaHashtable = nullptr;
2449
2450 NS_ASSERTION(!sBlockedScriptRunners || sBlockedScriptRunners->Length() == 0,do { if (!(!sBlockedScriptRunners || sBlockedScriptRunners->
Length() == 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "How'd this happen?"
, "!sBlockedScriptRunners || sBlockedScriptRunners->Length() == 0"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2451); MOZ_PretendNoReturn
(); } } while (0)
2451 "How'd this happen?")do { if (!(!sBlockedScriptRunners || sBlockedScriptRunners->
Length() == 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "How'd this happen?"
, "!sBlockedScriptRunners || sBlockedScriptRunners->Length() == 0"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2451); MOZ_PretendNoReturn
(); } } while (0)
;
2452 delete sBlockedScriptRunners;
2453 sBlockedScriptRunners = nullptr;
2454
2455 delete sShiftText;
2456 sShiftText = nullptr;
2457 delete sControlText;
2458 sControlText = nullptr;
2459 delete sCommandOrWinText;
2460 sCommandOrWinText = nullptr;
2461 delete sAltText;
2462 sAltText = nullptr;
2463 delete sModifierSeparator;
2464 sModifierSeparator = nullptr;
2465
2466 delete sJSScriptBytecodeMimeType;
2467 sJSScriptBytecodeMimeType = nullptr;
2468
2469 delete sJSModuleBytecodeMimeType;
2470 sJSModuleBytecodeMimeType = nullptr;
2471
2472 NS_IF_RELEASE(sSameOriginChecker)do { if (sSameOriginChecker) { (sSameOriginChecker)->Release
(); (sSameOriginChecker) = 0; } } while (0)
;
2473
2474 if (sUserInteractionObserver) {
2475 sUserInteractionObserver->Shutdown();
2476 NS_RELEASE(sUserInteractionObserver)do { (sUserInteractionObserver)->Release(); (sUserInteractionObserver
) = 0; } while (0)
;
2477 }
2478
2479 for (const auto& pref : kRfpPrefs) {
2480 Preferences::UnregisterCallback(RecomputeResistFingerprintingAllDocs, pref);
2481 }
2482
2483 TextControlState::Shutdown();
2484}
2485
2486/**
2487 * Checks whether two nodes come from the same origin. aTrustedNode is
2488 * considered 'safe' in that a user can operate on it.
2489 */
2490// static
2491nsresult nsContentUtils::CheckSameOrigin(const nsINode* aTrustedNode,
2492 const nsINode* unTrustedNode) {
2493 MOZ_ASSERT(aTrustedNode)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTrustedNode)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aTrustedNode))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aTrustedNode", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 2493); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTrustedNode"
")"); do { MOZ_CrashSequence(__null, 2493); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2494 MOZ_ASSERT(unTrustedNode)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(unTrustedNode)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(unTrustedNode))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("unTrustedNode",
"/root/firefox-clang/dom/base/nsContentUtils.cpp", 2494); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "unTrustedNode" ")"); do { MOZ_CrashSequence
(__null, 2494); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2495
2496 /*
2497 * Get hold of each node's principal
2498 */
2499
2500 nsIPrincipal* trustedPrincipal = aTrustedNode->NodePrincipal();
2501 nsIPrincipal* unTrustedPrincipal = unTrustedNode->NodePrincipal();
2502
2503 if (trustedPrincipal == unTrustedPrincipal) {
2504 return NS_OK;
2505 }
2506
2507 bool equal;
2508 // XXXbz should we actually have a Subsumes() check here instead? Or perhaps
2509 // a separate method for that, with callers using one or the other?
2510 if (NS_FAILED(trustedPrincipal->Equals(unTrustedPrincipal, &equal))((bool)(__builtin_expect(!!(NS_FAILED_impl(trustedPrincipal->
Equals(unTrustedPrincipal, &equal))), 0)))
||
2511 !equal) {
2512 return NS_ERROR_DOM_PROP_ACCESS_DENIED;
2513 }
2514
2515 return NS_OK;
2516}
2517
2518// static
2519bool nsContentUtils::CanCallerAccess(nsIPrincipal* aSubjectPrincipal,
2520 nsIPrincipal* aPrincipal) {
2521 bool subsumes;
2522 nsresult rv = aSubjectPrincipal->Subsumes(aPrincipal, &subsumes);
2523 NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 2523); return false; } } while (false)
;
2524
2525 if (subsumes) {
2526 return true;
2527 }
2528
2529 // The subject doesn't subsume aPrincipal. Allow access only if the subject
2530 // is chrome.
2531 return IsCallerChrome();
2532}
2533
2534// static
2535bool nsContentUtils::CanCallerAccess(const nsINode* aNode) {
2536 nsIPrincipal* subject = SubjectPrincipal();
2537 if (subject->IsSystemPrincipal()) {
2538 return true;
2539 }
2540
2541 if (aNode->ChromeOnlyAccess()) {
2542 return false;
2543 }
2544
2545 return CanCallerAccess(subject, aNode->NodePrincipal());
2546}
2547
2548// static
2549bool nsContentUtils::CanCallerAccess(nsPIDOMWindowInner* aWindow) {
2550 nsCOMPtr<nsIScriptObjectPrincipal> scriptObject = do_QueryInterface(aWindow);
2551 NS_ENSURE_TRUE(scriptObject, false)do { if ((__builtin_expect(!!(!(scriptObject)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "scriptObject" ") failed"
, nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp",
2551); return false; } } while (false)
;
2552
2553 return CanCallerAccess(SubjectPrincipal(), scriptObject->GetPrincipal());
2554}
2555
2556// static
2557bool nsContentUtils::PrincipalHasPermission(nsIPrincipal& aPrincipal,
2558 const nsAtom* aPerm) {
2559 // Chrome gets access by default.
2560 if (aPrincipal.IsSystemPrincipal()) {
2561 return true;
2562 }
2563
2564 // Otherwise, only allow if caller is an addon with the permission.
2565 return BasePrincipal::Cast(aPrincipal).AddonHasPermission(aPerm);
2566}
2567
2568// static
2569bool nsContentUtils::CallerHasPermission(JSContext* aCx, const nsAtom* aPerm) {
2570 return PrincipalHasPermission(*SubjectPrincipal(aCx), aPerm);
2571}
2572
2573// static
2574nsIPrincipal* nsContentUtils::GetAttrTriggeringPrincipal(
2575 nsIContent* aContent, const nsAString& aAttrValue,
2576 nsIPrincipal* aSubjectPrincipal) {
2577 nsIPrincipal* contentPrin = aContent ? aContent->NodePrincipal() : nullptr;
2578
2579 // If the subject principal is the same as the content principal, or no
2580 // explicit subject principal was provided, we don't need to do any further
2581 // checks. Just return the content principal.
2582 if (contentPrin == aSubjectPrincipal || !aSubjectPrincipal) {
2583 return contentPrin;
2584 }
2585
2586 // Only use the subject principal if the URL string we are going to end up
2587 // fetching is under the control of that principal, which is never the case
2588 // for relative URLs.
2589 if (aAttrValue.IsEmpty() ||
2590 !IsAbsoluteURL(NS_ConvertUTF16toUTF8(aAttrValue))) {
2591 return contentPrin;
2592 }
2593
2594 // Only use the subject principal as the attr triggering principal if it
2595 // should override the CSP of the node's principal.
2596 if (BasePrincipal::Cast(aSubjectPrincipal)->OverridesCSP(contentPrin)) {
2597 return aSubjectPrincipal;
2598 }
2599
2600 return contentPrin;
2601}
2602
2603// static
2604bool nsContentUtils::CanNavigate(mozilla::dom::BrowsingContext* aSource,
2605 mozilla::dom::BrowsingContext* aTarget,
2606 nsIPrincipal* aDocumentPrincipal,
2607 bool aConsiderOpener) {
2608 MOZ_DIAGNOSTIC_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSource->Group() == aTarget->Group())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aSource->Group() == aTarget->Group()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aSource->Group() == aTarget->Group()"
" (" "Source and target BrowsingContexts must be in the same group"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2610
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aSource->Group() == aTarget->Group()"
") (" "Source and target BrowsingContexts must be in the same group"
")"); do { MOZ_CrashSequence(__null, 2610); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2609 aSource->Group() == aTarget->Group(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSource->Group() == aTarget->Group())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aSource->Group() == aTarget->Group()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aSource->Group() == aTarget->Group()"
" (" "Source and target BrowsingContexts must be in the same group"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2610
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aSource->Group() == aTarget->Group()"
") (" "Source and target BrowsingContexts must be in the same group"
")"); do { MOZ_CrashSequence(__null, 2610); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2610 "Source and target BrowsingContexts must be in the same group")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSource->Group() == aTarget->Group())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aSource->Group() == aTarget->Group()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aSource->Group() == aTarget->Group()"
" (" "Source and target BrowsingContexts must be in the same group"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2610
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aSource->Group() == aTarget->Group()"
") (" "Source and target BrowsingContexts must be in the same group"
")"); do { MOZ_CrashSequence(__null, 2610); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2611 if (aSource->Group() != aTarget->Group()) {
2612 return false;
2613 }
2614
2615 auto isFileScheme = [](nsIPrincipal* aPrincipal) -> bool {
2616 // NOTE: This code previously checked for a file scheme using
2617 // `nsIPrincipal::GetURI()` combined with `NS_GetInnermostURI`. We no longer
2618 // use GetURI, as it has been deprecated, and it makes more sense to take
2619 // advantage of the pre-computed origin, which will already use the
2620 // innermost URI (bug 1810619)
2621 nsAutoCString origin, scheme;
2622 return NS_SUCCEEDED(aPrincipal->GetOriginNoSuffix(origin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->GetOriginNoSuffix
(origin))), 1)))
&&
2623 NS_SUCCEEDED(net_ExtractURLScheme(origin, scheme))((bool)(__builtin_expect(!!(!NS_FAILED_impl(net_ExtractURLScheme
(origin, scheme))), 1)))
&&
2624 scheme == "file"_ns;
2625 };
2626
2627 // A frame can navigate itself and its own root.
2628 if (aTarget == aSource || aTarget == aSource->Top()) {
2629 return true;
2630 }
2631
2632 // If the target frame doesn't yet have a WindowContext, start checking
2633 // principals from its direct ancestor instead. It would inherit its principal
2634 // from this document upon creation.
2635 dom::WindowContext* initialWc = aTarget->GetCurrentWindowContext();
2636 if (!initialWc) {
2637 initialWc = aTarget->GetParentWindowContext();
2638 }
2639
2640 // A frame can navigate any frame with a same-origin ancestor.
2641 bool isFileDocument = isFileScheme(aDocumentPrincipal);
2642 for (dom::WindowContext* wc = initialWc; wc;
2643 wc = wc->GetParentWindowContext()) {
2644 nsIPrincipal* documentPrincipal = nullptr;
2645 if (XRE_IsParentProcess()) {
2646 dom::WindowGlobalParent* wgp = wc->Canonical();
2647 if (!wgp) {
2648 continue;
2649 }
2650 documentPrincipal = wgp->DocumentPrincipal();
2651 } else {
2652 dom::WindowGlobalChild* wgc = wc->GetWindowGlobalChild();
2653 if (!wgc) {
2654 continue; // not same-origin.
2655 }
2656 documentPrincipal = wgc->DocumentPrincipal();
2657 }
2658
2659 if (aDocumentPrincipal->Equals(documentPrincipal)) {
2660 return true;
2661 }
2662
2663 // Not strictly equal, special case if both are file: URIs.
2664 //
2665 // file: URIs are considered the same domain for the purpose of frame
2666 // navigation, regardless of script accessibility (bug 420425).
2667 if (isFileDocument && isFileScheme(documentPrincipal)) {
2668 return true;
2669 }
2670 }
2671
2672 // If the target is a top-level document, a frame can navigate it
2673 // when the source is allowed to navigate the opener
2674 if (aConsiderOpener && !aTarget->GetParent()) {
2675 if (RefPtr<dom::BrowsingContext> opener = aTarget->GetOpener()) {
2676 return CanNavigate(aSource, opener, aDocumentPrincipal, false);
2677 }
2678 }
2679
2680 return false;
2681}
2682
2683// static
2684bool nsContentUtils::IsAbsoluteURL(const nsACString& aURL) {
2685 nsAutoCString scheme;
2686 if (NS_FAILED(net_ExtractURLScheme(aURL, scheme))((bool)(__builtin_expect(!!(NS_FAILED_impl(net_ExtractURLScheme
(aURL, scheme))), 0)))
) {
2687 // If we can't extract a scheme, it's not an absolute URL.
2688 return false;
2689 }
2690
2691 // If it parses as an absolute StandardURL, it's definitely an absolute URL,
2692 // so no need to check with the IO service.
2693 if (net_IsAbsoluteURL(aURL)) {
2694 return true;
2695 }
2696
2697 nsresult rv = NS_OK;
2698 nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service(&rv);
2699 MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 2699); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2699); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2700 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2701 return false;
2702 }
2703
2704 uint32_t flags;
2705 if (NS_SUCCEEDED(io->GetProtocolFlags(scheme.get(), &flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(io->GetProtocolFlags
(scheme.get(), &flags))), 1)))
) {
2706 return flags & nsIProtocolHandler::URI_NORELATIVE;
2707 }
2708
2709 return false;
2710}
2711
2712// static
2713bool nsContentUtils::InProlog(nsINode* aNode) {
2714 MOZ_ASSERT(aNode, "missing node to nsContentUtils::InProlog")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNode)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(aNode))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aNode" " (" "missing node to nsContentUtils::InProlog"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2714
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode" ") (" "missing node to nsContentUtils::InProlog"
")"); do { MOZ_CrashSequence(__null, 2714); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2715
2716 nsINode* parent = aNode->GetParentNode();
2717 if (!parent || !parent->IsDocument()) {
2718 return false;
2719 }
2720
2721 const Document* doc = parent->AsDocument();
2722 const nsIContent* root = doc->GetRootElement();
2723 if (!root) {
2724 return true;
2725 }
2726 const Maybe<uint32_t> indexOfNode = doc->ComputeIndexOf(aNode);
2727 const Maybe<uint32_t> indexOfRoot = doc->ComputeIndexOf(root);
2728 if (MOZ_LIKELY(indexOfNode.isSome() && indexOfRoot.isSome())(__builtin_expect(!!(indexOfNode.isSome() && indexOfRoot
.isSome()), 1))
) {
2729 return *indexOfNode < *indexOfRoot;
2730 }
2731 // XXX Keep the odd traditional behavior for now.
2732 return indexOfNode.isNothing() && indexOfRoot.isSome();
2733}
2734
2735bool nsContentUtils::IsCallerChrome() {
2736 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2736); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2736); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2737 return SubjectPrincipal() == sSystemPrincipal;
2738}
2739
2740#ifdef FUZZING
2741bool nsContentUtils::IsFuzzingEnabled() {
2742 return StaticPrefs::fuzzing_enabled();
2743}
2744#endif
2745
2746/* static */
2747bool nsContentUtils::IsCallerChromeOrElementTransformGettersEnabled(
2748 JSContext* aCx, JSObject*) {
2749 return ThreadsafeIsSystemCaller(aCx) ||
2750 StaticPrefs::dom_element_transform_getters_enabled();
2751}
2752
2753// Older Should RFP Functions ----------------------------------
2754
2755/* static */
2756bool nsContentUtils::ShouldResistFingerprinting(bool aIsPrivateMode,
2757 RFPTarget aTarget) {
2758 return nsRFPService::IsRFPEnabledFor(aIsPrivateMode, aTarget, Nothing());
2759}
2760
2761/* static */
2762bool nsContentUtils::ShouldResistFingerprinting(nsIGlobalObject* aGlobalObject,
2763 RFPTarget aTarget) {
2764 if (!aGlobalObject) {
2765 return ShouldResistFingerprinting("Null Object", aTarget);
2766 }
2767 return aGlobalObject->ShouldResistFingerprinting(aTarget);
2768}
2769
2770// Newer Should RFP Functions ----------------------------------
2771// Utilities ---------------------------------------------------
2772
2773inline void LogDomainAndList(const char* urlType, nsAutoCString& list,
2774 nsAutoCString& url, bool isExemptDomain) {
2775 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"%s \"%s\" is %s the exempt list \"%s\"", urlType, TPromiseFlatString
<char>(url).get(), isExemptDomain ? "in" : "NOT in", TPromiseFlatString
<char>(list).get()); } } while (0)
2776 ("%s \"%s\" is %s the exempt list \"%s\"", urlType,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"%s \"%s\" is %s the exempt list \"%s\"", urlType, TPromiseFlatString
<char>(url).get(), isExemptDomain ? "in" : "NOT in", TPromiseFlatString
<char>(list).get()); } } while (0)
2777 PromiseFlatCString(url).get(), isExemptDomain ? "in" : "NOT in",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"%s \"%s\" is %s the exempt list \"%s\"", urlType, TPromiseFlatString
<char>(url).get(), isExemptDomain ? "in" : "NOT in", TPromiseFlatString
<char>(list).get()); } } while (0)
2778 PromiseFlatCString(list).get()))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"%s \"%s\" is %s the exempt list \"%s\"", urlType, TPromiseFlatString
<char>(url).get(), isExemptDomain ? "in" : "NOT in", TPromiseFlatString
<char>(list).get()); } } while (0)
;
2779}
2780
2781inline already_AddRefed<nsICookieJarSettings> GetCookieJarSettings(
2782 nsILoadInfo* aLoadInfo) {
2783 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
2784 nsresult rv =
2785 aLoadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings));
2786 if (rv == NS_ERROR_NOT_IMPLEMENTED) {
2787 // The TRRLoadInfo in particular does not implement this method
2788 // In that instance. We will return false and let other code decide if
2789 // we shouldRFP for this connection
2790 return nullptr;
2791 }
2792 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 2792)
) {
2793 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called CookieJarSettingsSaysShouldResistFingerprinting but the "
"loadinfo's CookieJarSettings couldn't be retrieved"); } } while
(0)
2794 ("Called CookieJarSettingsSaysShouldResistFingerprinting but the "do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called CookieJarSettingsSaysShouldResistFingerprinting but the "
"loadinfo's CookieJarSettings couldn't be retrieved"); } } while
(0)
2795 "loadinfo's CookieJarSettings couldn't be retrieved"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called CookieJarSettingsSaysShouldResistFingerprinting but the "
"loadinfo's CookieJarSettings couldn't be retrieved"); } } while
(0)
;
2796 return nullptr;
2797 }
2798
2799 MOZ_ASSERT(cookieJarSettings)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(cookieJarSettings)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(cookieJarSettings))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("cookieJarSettings"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 2799); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "cookieJarSettings" ")"); do { MOZ_CrashSequence
(__null, 2799); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2800 return cookieJarSettings.forget();
2801}
2802
2803bool nsContentUtils::ETPSaysShouldNotResistFingerprinting(
2804 nsICookieJarSettings* aCookieJarSettings, bool aIsPBM) {
2805 // A positive return from this function should always be obeyed.
2806 // A negative return means we should keep checking things.
2807
2808 // We do not want this check to apply to RFP, only to FPP.
2809 if (nsRFPService::IsRFPPrefEnabled(aIsPBM)) {
2810 // In RFP, never use the ETP toggle to exempt.
2811 // We can safely return false here even if we are not in PBM mode
2812 // and RFP_pbmode is enabled because we will later see that and
2813 // return false from the ShouldRFP function entirely.
2814 return false;
2815 }
2816
2817 return ContentBlockingAllowList::Check(aCookieJarSettings);
2818}
2819
2820bool nsContentUtils::ETPSaysShouldNotResistFingerprinting(
2821 nsIChannel* aChannel, nsILoadInfo* aLoadInfo) {
2822 bool isPBM = NS_UsePrivateBrowsing(aChannel);
2823
2824 nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
2825 GetCookieJarSettings(aLoadInfo);
2826 if (!cookieJarSettings) {
2827 return false;
2828 }
2829
2830 return ETPSaysShouldNotResistFingerprinting(cookieJarSettings, isPBM);
2831}
2832
2833inline bool CookieJarSettingsSaysShouldResistFingerprinting(
2834 nsILoadInfo* aLoadInfo) {
2835 // A positive return from this function should always be obeyed.
2836 // A negative return means we should keep checking things.
2837
2838 nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
2839 GetCookieJarSettings(aLoadInfo);
2840 if (!cookieJarSettings) {
2841 return false;
2842 }
2843 return cookieJarSettings->GetShouldResistFingerprinting();
2844}
2845
2846inline bool SchemeSaysShouldNotResistFingerprinting(nsIURI* aURI) {
2847 return aURI->SchemeIs("chrome") || aURI->SchemeIs("resource") ||
2848 aURI->SchemeIs("view-source") || aURI->SchemeIs("moz-extension") ||
2849 (aURI->SchemeIs("about") && !NS_IsContentAccessibleAboutURI(aURI));
2850}
2851
2852inline bool SchemeSaysShouldNotResistFingerprinting(nsIPrincipal* aPrincipal) {
2853 if (aPrincipal->SchemeIs("chrome") || aPrincipal->SchemeIs("resource") ||
2854 aPrincipal->SchemeIs("view-source") ||
2855 aPrincipal->SchemeIs("moz-extension")) {
2856 return true;
2857 }
2858
2859 if (!aPrincipal->SchemeIs("about")) {
2860 return false;
2861 }
2862
2863 bool isContentAccessibleAboutURI;
2864 (void)aPrincipal->IsContentAccessibleAboutURI(&isContentAccessibleAboutURI);
2865 return !isContentAccessibleAboutURI;
2866}
2867
2868// mFirstPartyDomain and mPartitionKey are serialized either as a bare host
2869// ("example.com") or in site format ("(https,example.com[,port][,f])"),
2870// depending on privacy.firstparty.isolate.use_site and
2871// privacy.dynamic_firstparty.use_site respectively. Those two prefs are
2872// independent, and ParsePartitionKey() only consults the latter, so detect the
2873// format here instead of letting it decide for a first-party domain.
2874inline void TopLevelInfoToBaseDomain(const nsAString& aInfo,
2875 nsAString& aBaseDomain) {
2876 if (aInfo.IsEmpty() || aInfo.First() != '(') {
2877 aBaseDomain = aInfo;
2878 return;
2879 }
2880
2881 nsAutoString scheme;
2882 int32_t port;
2883 bool foreignByAncestorContext;
2884 if (!OriginAttributes::ParsePartitionKey(aInfo, scheme, aBaseDomain, port,
2885 foreignByAncestorContext)) {
2886 aBaseDomain.Truncate();
2887 }
2888}
2889
2890inline bool PartionKeyIsAlsoExempted(
2891 const mozilla::OriginAttributes& aOriginAttributes) {
2892 // If we've gotten here we have (probably) passed the CookieJarSettings
2893 // check that would tell us that if we _are_ a subdocument, then we are on
2894 // an exempted top-level domain and we should see if we ourselves are
2895 // exempted. But we may have gotten here because we directly called the
2896 // _dangerous function and we haven't done that check, but we _were_
2897 // instatiated from a state where we could have been partitioned.
2898 // So perform this last-ditch check for that scenario.
2899 // We arbitrarily use https as the scheme, but it doesn't matter.
2900 nsAutoString baseDomain;
2901 if (StaticPrefs::privacy_firstparty_isolate() &&
2902 !aOriginAttributes.mFirstPartyDomain.IsEmpty()) {
2903 TopLevelInfoToBaseDomain(aOriginAttributes.mFirstPartyDomain, baseDomain);
2904 } else if (!aOriginAttributes.mPartitionKey.IsEmpty()) {
2905 TopLevelInfoToBaseDomain(aOriginAttributes.mPartitionKey, baseDomain);
2906 }
2907
2908 nsresult rv = NS_ERROR_NOT_INITIALIZED;
2909 nsCOMPtr<nsIURI> uri;
2910 if (!baseDomain.IsEmpty()) {
2911 rv = NS_NewURI(getter_AddRefs(uri), u"https://"_ns + baseDomain);
2912 }
2913
2914 if (!NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2915 nsAutoCString list;
2916 nsRFPService::GetExemptedDomainsLowercase(list);
2917 bool isExemptPartitionKey = nsContentUtils::IsURIInList(uri, list);
2918 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
2919 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
2920 nsAutoCString url;
2921 uri->GetHost(url);
2922 LogDomainAndList("Partition Key", list, url, isExemptPartitionKey);
2923 }
2924 return isExemptPartitionKey;
2925 }
2926 return true;
2927}
2928
2929// Functions ---------------------------------------------------
2930
2931/* static */
2932bool nsContentUtils::ShouldResistFingerprinting(const char* aJustification,
2933 RFPTarget aTarget) {
2934 // See comment in header file for information about usage
2935 // We hardcode PBM to true to be the more restrictive option.
2936 return nsContentUtils::ShouldResistFingerprinting(true, aTarget);
2937}
2938
2939namespace {
2940
2941// This function is only called within this file for Positive Return Checks
2942bool ShouldResistFingerprinting_(const char* aJustification,
2943 bool aIsPrivateMode, RFPTarget aTarget) {
2944 // See comment in header file for information about usage
2945 return nsContentUtils::ShouldResistFingerprinting(aIsPrivateMode, aTarget);
2946}
2947
2948} // namespace
2949
2950/* static */
2951bool nsContentUtils::ShouldResistFingerprinting(CallerType aCallerType,
2952 nsIGlobalObject* aGlobalObject,
2953 RFPTarget aTarget) {
2954 if (aCallerType == CallerType::System) {
2955 return false;
2956 }
2957 return ShouldResistFingerprinting(aGlobalObject, aTarget);
2958}
2959
2960/* static */
2961bool nsContentUtils::ShouldResistFingerprinting(nsIDocShell* aDocShell,
2962 RFPTarget aTarget) {
2963 if (!aDocShell) {
2964 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsIDocShell*) "
"with NULL docshell"); } } while (0)
2965 ("Called nsContentUtils::ShouldResistFingerprinting(nsIDocShell*) "do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsIDocShell*) "
"with NULL docshell"); } } while (0)
2966 "with NULL docshell"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsIDocShell*) "
"with NULL docshell"); } } while (0)
;
2967 return ShouldResistFingerprinting("Null Object", aTarget);
2968 }
2969 return ShouldResistFingerprinting(aDocShell->GetDocument(), aTarget);
2970}
2971
2972/* static */
2973bool nsContentUtils::ShouldResistFingerprinting(const Document* aDocument,
2974 RFPTarget aTarget) {
2975 if (!aDocument) {
2976 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(const Document*) "
"with NULL document"); } } while (0)
2977 nsContentUtils::ResistFingerprintingLog(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(const Document*) "
"with NULL document"); } } while (0)
2978 ("Called nsContentUtils::ShouldResistFingerprinting(const Document*) "do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(const Document*) "
"with NULL document"); } } while (0)
2979 "with NULL document"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(const Document*) "
"with NULL document"); } } while (0)
;
2980 return ShouldResistFingerprinting("Null Object", aTarget);
2981 }
2982 return aDocument->ShouldResistFingerprinting(aTarget);
2983}
2984
2985/* static */
2986bool nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel,
2987 RFPTarget aTarget) {
2988 if (!aChannel) {
2989 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsIChannel* "
"aChannel) with NULL channel"); } } while (0)
2990 ("Called nsContentUtils::ShouldResistFingerprinting(nsIChannel* "do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsIChannel* "
"aChannel) with NULL channel"); } } while (0)
2991 "aChannel) with NULL channel"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsIChannel* "
"aChannel) with NULL channel"); } } while (0)
;
2992 return ShouldResistFingerprinting("Null Object", aTarget);
2993 }
2994
2995 bool isPBM = NS_UsePrivateBrowsing(aChannel);
2996
2997 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
2998 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
2999 nsCOMPtr<nsIURI> channelURI;
3000 (void)NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
3001 nsAutoCString channelSpec;
3002 channelURI->GetSpec(channelSpec);
3003 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIChannel*) for %s (PBM: %s)"
, channelSpec.get(), isPBM ? "Yes" : "No"); } } while (0)
3004 ("Inside ShouldResistFingerprinting(nsIChannel*) for %s (PBM: %s)",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIChannel*) for %s (PBM: %s)"
, channelSpec.get(), isPBM ? "Yes" : "No"); } } while (0)
3005 channelSpec.get(), isPBM ? "Yes" : "No"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIChannel*) for %s (PBM: %s)"
, channelSpec.get(), isPBM ? "Yes" : "No"); } } while (0)
;
3006 }
3007
3008 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
3009 if (!loadInfo) {
3010 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsIChannel* "
"aChannel) but the channel's loadinfo was NULL"); } } while (
0)
3011 ("Called nsContentUtils::ShouldResistFingerprinting(nsIChannel* "do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsIChannel* "
"aChannel) but the channel's loadinfo was NULL"); } } while (
0)
3012 "aChannel) but the channel's loadinfo was NULL"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsIChannel* "
"aChannel) but the channel's loadinfo was NULL"); } } while (
0)
;
3013 return ShouldResistFingerprinting("Null Object", aTarget);
3014 }
3015
3016 // With this check, we can ensure that the prefs and target say yes, so only
3017 // an exemption would cause us to return false.
3018 if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) {
3019 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIChannel*)" " Positive return check said false (PBM: %s)"
, isPBM ? "Yes" : "No"); } } while (0)
3020 ("Inside ShouldResistFingerprinting(nsIChannel*)"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIChannel*)" " Positive return check said false (PBM: %s)"
, isPBM ? "Yes" : "No"); } } while (0)
3021 " Positive return check said false (PBM: %s)",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIChannel*)" " Positive return check said false (PBM: %s)"
, isPBM ? "Yes" : "No"); } } while (0)
3022 isPBM ? "Yes" : "No"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIChannel*)" " Positive return check said false (PBM: %s)"
, isPBM ? "Yes" : "No"); } } while (0)
;
3023 return false;
3024 }
3025
3026 auto contentType = loadInfo->GetExternalContentPolicyType();
3027
3028 if (sSecurityManager && (contentType == ExtContentPolicy::TYPE_DOCUMENT ||
3029 contentType == ExtContentPolicy::TYPE_SUBDOCUMENT)) {
3030 nsCOMPtr<nsIPrincipal> resultPrincipal;
3031 nsresult rv = sSecurityManager->GetChannelResultPrincipal(
3032 aChannel, getter_AddRefs(resultPrincipal));
3033 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && IsPDFJS(resultPrincipal)) {
3034 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIChannel*)" " PDF.js document exempted"
); } } while (0)
3035 ("Inside ShouldResistFingerprinting(nsIChannel*)"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIChannel*)" " PDF.js document exempted"
); } } while (0)
3036 " PDF.js document exempted"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIChannel*)" " PDF.js document exempted"
); } } while (0)
;
3037 return false;
3038 }
3039 }
3040
3041 if (ETPSaysShouldNotResistFingerprinting(aChannel, loadInfo)) {
3042 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIChannel*)" " ETPSaysShouldNotResistFingerprinting said false"
); } } while (0)
3043 ("Inside ShouldResistFingerprinting(nsIChannel*)"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIChannel*)" " ETPSaysShouldNotResistFingerprinting said false"
); } } while (0)
3044 " ETPSaysShouldNotResistFingerprinting said false"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIChannel*)" " ETPSaysShouldNotResistFingerprinting said false"
); } } while (0)
;
3045 return false;
3046 }
3047
3048 if (CookieJarSettingsSaysShouldResistFingerprinting(loadInfo)) {
3049 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIChannel*)" " CookieJarSettingsSaysShouldResistFingerprinting said true"
); } } while (0)
3050 ("Inside ShouldResistFingerprinting(nsIChannel*)"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIChannel*)" " CookieJarSettingsSaysShouldResistFingerprinting said true"
); } } while (0)
3051 " CookieJarSettingsSaysShouldResistFingerprinting said true"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIChannel*)" " CookieJarSettingsSaysShouldResistFingerprinting said true"
); } } while (0)
;
3052 return true;
3053 }
3054
3055 // Document types have no loading principal. Subdocument types do have a
3056 // loading principal, but it is the loading principal of the parent
3057 // document; not the subdocument.
3058 // Case 1: Document or Subdocument load
3059 if (contentType == ExtContentPolicy::TYPE_DOCUMENT ||
3060 contentType == ExtContentPolicy::TYPE_SUBDOCUMENT) {
3061 nsCOMPtr<nsIURI> channelURI;
3062 nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
3063 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" " ("
"Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3066
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { MOZ_CrashSequence(__null, 3066); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3064 NS_SUCCEEDED(rv),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" " ("
"Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3066
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { MOZ_CrashSequence(__null, 3066); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3065 "Failed to get URI in "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" " ("
"Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3066
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { MOZ_CrashSequence(__null, 3066); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3066 "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" " ("
"Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3066
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { MOZ_CrashSequence(__null, 3066); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3067 // this check is to ensure that we do not crash in non-debug builds.
3068 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3069 return true;
3070 }
3071
3072 nsAutoCString loadingPrincipalSpec;
3073 nsAutoCString channelSpec;
3074 channelURI->GetSpec(channelSpec);
3075
3076 if (contentType == ExtContentPolicy::TYPE_SUBDOCUMENT) {
3077 MOZ_LOG_DEBUG_ONLY(do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Sub Document Type. FinalChannelURI is %s, Loading Principal %s\n"
, channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo
->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec
), loadingPrincipalSpec.get() : "is NULL"); } } while (0)
3078 nsContentUtils::ResistFingerprintingLog(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Sub Document Type. FinalChannelURI is %s, Loading Principal %s\n"
, channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo
->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec
), loadingPrincipalSpec.get() : "is NULL"); } } while (0)
3079 ("Sub Document Type. FinalChannelURI is %s, Loading Principal %s\n",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Sub Document Type. FinalChannelURI is %s, Loading Principal %s\n"
, channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo
->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec
), loadingPrincipalSpec.get() : "is NULL"); } } while (0)
3080 channelSpec.get(),do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Sub Document Type. FinalChannelURI is %s, Loading Principal %s\n"
, channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo
->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec
), loadingPrincipalSpec.get() : "is NULL"); } } while (0)
3081 loadInfo->GetLoadingPrincipal()do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Sub Document Type. FinalChannelURI is %s, Loading Principal %s\n"
, channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo
->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec
), loadingPrincipalSpec.get() : "is NULL"); } } while (0)
3082 ? loadInfo->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec),do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Sub Document Type. FinalChannelURI is %s, Loading Principal %s\n"
, channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo
->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec
), loadingPrincipalSpec.get() : "is NULL"); } } while (0)
3083 loadingPrincipalSpec.get() : "is NULL"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Sub Document Type. FinalChannelURI is %s, Loading Principal %s\n"
, channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo
->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec
), loadingPrincipalSpec.get() : "is NULL"); } } while (0)
;
3084 } else {
3085 MOZ_LOG_DEBUG_ONLY(do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Document Type. FinalChannelURI is %s, Loading Principal %s\n"
, channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo
->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec
), loadingPrincipalSpec.get() : "is NULL"); } } while (0)
3086 nsContentUtils::ResistFingerprintingLog(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Document Type. FinalChannelURI is %s, Loading Principal %s\n"
, channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo
->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec
), loadingPrincipalSpec.get() : "is NULL"); } } while (0)
3087 ("Document Type. FinalChannelURI is %s, Loading Principal %s\n",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Document Type. FinalChannelURI is %s, Loading Principal %s\n"
, channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo
->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec
), loadingPrincipalSpec.get() : "is NULL"); } } while (0)
3088 channelSpec.get(),do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Document Type. FinalChannelURI is %s, Loading Principal %s\n"
, channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo
->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec
), loadingPrincipalSpec.get() : "is NULL"); } } while (0)
3089 loadInfo->GetLoadingPrincipal()do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Document Type. FinalChannelURI is %s, Loading Principal %s\n"
, channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo
->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec
), loadingPrincipalSpec.get() : "is NULL"); } } while (0)
3090 ? loadInfo->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec),do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Document Type. FinalChannelURI is %s, Loading Principal %s\n"
, channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo
->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec
), loadingPrincipalSpec.get() : "is NULL"); } } while (0)
3091 loadingPrincipalSpec.get() : "is NULL"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Document Type. FinalChannelURI is %s, Loading Principal %s\n"
, channelSpec.get(), loadInfo->GetLoadingPrincipal() ? loadInfo
->GetLoadingPrincipal()->GetOrigin(loadingPrincipalSpec
), loadingPrincipalSpec.get() : "is NULL"); } } while (0)
;
3092 }
3093
3094 return ShouldResistFingerprinting_dangerous(
3095 channelURI, loadInfo->GetOriginAttributes(), "Internal Call", aTarget);
3096 }
3097
3098 // Case 2: Subresource Load
3099 // Because this code is only used for subresource loads, this
3100 // will check the parent's principal
3101 nsIPrincipal* principal = loadInfo->GetLoadingPrincipal();
3102
3103 MOZ_ASSERT_IF(principal && !principal->IsSystemPrincipal() &&do { if (principal && !principal->IsSystemPrincipal
() && !principal->GetIsAddonOrExpandedAddonPrincipal
()) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(BasePrincipal::Cast(principal)->OriginAttributesRef
() == loadInfo->GetOriginAttributes())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(BasePrincipal::Cast(principal
)->OriginAttributesRef() == loadInfo->GetOriginAttributes
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3106); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { MOZ_CrashSequence(__null, 3106); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3104 !principal->GetIsAddonOrExpandedAddonPrincipal(),do { if (principal && !principal->IsSystemPrincipal
() && !principal->GetIsAddonOrExpandedAddonPrincipal
()) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(BasePrincipal::Cast(principal)->OriginAttributesRef
() == loadInfo->GetOriginAttributes())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(BasePrincipal::Cast(principal
)->OriginAttributesRef() == loadInfo->GetOriginAttributes
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3106); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { MOZ_CrashSequence(__null, 3106); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3105 BasePrincipal::Cast(principal)->OriginAttributesRef() ==do { if (principal && !principal->IsSystemPrincipal
() && !principal->GetIsAddonOrExpandedAddonPrincipal
()) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(BasePrincipal::Cast(principal)->OriginAttributesRef
() == loadInfo->GetOriginAttributes())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(BasePrincipal::Cast(principal
)->OriginAttributesRef() == loadInfo->GetOriginAttributes
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3106); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { MOZ_CrashSequence(__null, 3106); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3106 loadInfo->GetOriginAttributes())do { if (principal && !principal->IsSystemPrincipal
() && !principal->GetIsAddonOrExpandedAddonPrincipal
()) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(BasePrincipal::Cast(principal)->OriginAttributesRef
() == loadInfo->GetOriginAttributes())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(BasePrincipal::Cast(principal
)->OriginAttributesRef() == loadInfo->GetOriginAttributes
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3106); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { MOZ_CrashSequence(__null, 3106); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3107 return ShouldResistFingerprinting_dangerous(principal, "Internal Call",
3108 aTarget);
3109}
3110
3111/* static */
3112bool nsContentUtils::ShouldResistFingerprinting_dangerous(
3113 nsIURI* aURI, const mozilla::OriginAttributes& aOriginAttributes,
3114 const char* aJustification, RFPTarget aTarget) {
3115 // With this check, we can ensure that the prefs and target say yes, so only
3116 // an exemption would cause us to return false.
3117 bool isPBM = aOriginAttributes.IsPrivateBrowsing();
3118
3119 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) and the URI is %s (PBM: %s)"
, aURI->GetSpecOrDefault().get(), isPBM ? "Yes" : "No"); }
} while (0)
3120 ("Inside ShouldResistFingerprinting_dangerous(nsIURI*,"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) and the URI is %s (PBM: %s)"
, aURI->GetSpecOrDefault().get(), isPBM ? "Yes" : "No"); }
} while (0)
3121 " OriginAttributes) and the URI is %s (PBM: %s)",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) and the URI is %s (PBM: %s)"
, aURI->GetSpecOrDefault().get(), isPBM ? "Yes" : "No"); }
} while (0)
3122 aURI->GetSpecOrDefault().get(), isPBM ? "Yes" : "No"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) and the URI is %s (PBM: %s)"
, aURI->GetSpecOrDefault().get(), isPBM ? "Yes" : "No"); }
} while (0)
;
3123
3124 if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) {
3125 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) Positive return check said false (PBM: %s)"
, isPBM ? "Yes" : "No"); } } while (0)
3126 ("Inside ShouldResistFingerprinting_dangerous(nsIURI*,"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) Positive return check said false (PBM: %s)"
, isPBM ? "Yes" : "No"); } } while (0)
3127 " OriginAttributes) Positive return check said false (PBM: %s)",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) Positive return check said false (PBM: %s)"
, isPBM ? "Yes" : "No"); } } while (0)
3128 isPBM ? "Yes" : "No"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) Positive return check said false (PBM: %s)"
, isPBM ? "Yes" : "No"); } } while (0)
;
3129 return false;
3130 }
3131
3132 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) and the URI is %s"
, aURI->GetSpecOrDefault().get()); } } while (0)
3133 ("Inside ShouldResistFingerprinting_dangerous(nsIURI*,"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) and the URI is %s"
, aURI->GetSpecOrDefault().get()); } } while (0)
3134 " OriginAttributes) and the URI is %s",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) and the URI is %s"
, aURI->GetSpecOrDefault().get()); } } while (0)
3135 aURI->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting_dangerous(nsIURI*," " OriginAttributes) and the URI is %s"
, aURI->GetSpecOrDefault().get()); } } while (0)
;
3136
3137 // Exclude internal schemes and web extensions
3138 if (SchemeSaysShouldNotResistFingerprinting(aURI)) {
3139 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIURI*)" " SchemeSaysShouldNotResistFingerprinting said false"
); } } while (0)
3140 ("Inside ShouldResistFingerprinting(nsIURI*)"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIURI*)" " SchemeSaysShouldNotResistFingerprinting said false"
); } } while (0)
3141 " SchemeSaysShouldNotResistFingerprinting said false"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIURI*)" " SchemeSaysShouldNotResistFingerprinting said false"
); } } while (0)
;
3142 return false;
3143 }
3144
3145 bool isExemptDomain = false;
3146 nsAutoCString list;
3147 nsRFPService::GetExemptedDomainsLowercase(list);
3148 isExemptDomain = IsURIInList(aURI, list);
3149
3150 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
3151 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
3152 nsAutoCString url;
3153 aURI->GetHost(url);
3154 LogDomainAndList("URI", list, url, isExemptDomain);
3155 }
3156
3157 if (isExemptDomain) {
3158 isExemptDomain &= PartionKeyIsAlsoExempted(aOriginAttributes);
3159 }
3160
3161 return !isExemptDomain;
3162}
3163
3164/* static */
3165bool nsContentUtils::ShouldResistFingerprinting_dangerous(
3166 nsIPrincipal* aPrincipal, const char* aJustification, RFPTarget aTarget) {
3167 if (!aPrincipal) {
3168 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsILoadInfo* "
"aChannel) but the loadinfo's loadingprincipal was NULL"); }
} while (0)
3169 ("Called nsContentUtils::ShouldResistFingerprinting(nsILoadInfo* "do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsILoadInfo* "
"aChannel) but the loadinfo's loadingprincipal was NULL"); }
} while (0)
3170 "aChannel) but the loadinfo's loadingprincipal was NULL"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsILoadInfo* "
"aChannel) but the loadinfo's loadingprincipal was NULL"); }
} while (0)
;
3171 return ShouldResistFingerprinting("Null object", aTarget);
3172 }
3173
3174 const auto& originAttributes =
3175 BasePrincipal::Cast(aPrincipal)->OriginAttributesRef();
3176 // With this check, we can ensure that the prefs and target say yes, so only
3177 // an exemption would cause us to return false.
3178 bool isPBM = originAttributes.IsPrivateBrowsing();
3179
3180 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
3181 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
3182 nsAutoCString origin;
3183 aPrincipal->GetOrigin(origin);
3184 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIPrincipal*) for %s (PBM: %s)"
, origin.get(), isPBM ? "Yes" : "No"); } } while (0)
3185 nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIPrincipal*) for %s (PBM: %s)"
, origin.get(), isPBM ? "Yes" : "No"); } } while (0)
3186 ("Inside ShouldResistFingerprinting(nsIPrincipal*) for %s (PBM: %s)",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIPrincipal*) for %s (PBM: %s)"
, origin.get(), isPBM ? "Yes" : "No"); } } while (0)
3187 origin.get(), isPBM ? "Yes" : "No"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIPrincipal*) for %s (PBM: %s)"
, origin.get(), isPBM ? "Yes" : "No"); } } while (0)
;
3188 }
3189
3190 if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) {
3191 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIPrincipal*) Positive return "
"check said false (PBM: %s)", isPBM ? "Yes" : "No"); } } while
(0)
3192 ("Inside ShouldResistFingerprinting(nsIPrincipal*) Positive return "do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIPrincipal*) Positive return "
"check said false (PBM: %s)", isPBM ? "Yes" : "No"); } } while
(0)
3193 "check said false (PBM: %s)",do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIPrincipal*) Positive return "
"check said false (PBM: %s)", isPBM ? "Yes" : "No"); } } while
(0)
3194 isPBM ? "Yes" : "No"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIPrincipal*) Positive return "
"check said false (PBM: %s)", isPBM ? "Yes" : "No"); } } while
(0)
;
3195 return false;
3196 }
3197
3198 if (aPrincipal->IsSystemPrincipal()) {
3199 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIPrincipal*) System " "Principal said false"
); } } while (0)
3200 ("Inside ShouldResistFingerprinting(nsIPrincipal*) System "do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIPrincipal*) System " "Principal said false"
); } } while (0)
3201 "Principal said false"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIPrincipal*) System " "Principal said false"
); } } while (0)
;
3202 return false;
3203 }
3204
3205 // Exclude internal schemes and web extensions
3206 if (SchemeSaysShouldNotResistFingerprinting(aPrincipal)) {
3207 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIPrincipal*)" " SchemeSaysShouldNotResistFingerprinting said false"
); } } while (0)
3208 ("Inside ShouldResistFingerprinting(nsIPrincipal*)"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIPrincipal*)" " SchemeSaysShouldNotResistFingerprinting said false"
); } } while (0)
3209 " SchemeSaysShouldNotResistFingerprinting said false"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIPrincipal*)" " SchemeSaysShouldNotResistFingerprinting said false"
); } } while (0)
;
3210 return false;
3211 }
3212
3213 // Web extension principals are also excluded
3214 if (BasePrincipal::Cast(aPrincipal)->AddonPolicyCore()) {
3215 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIPrincipal*)" " and AddonPolicy said false"
); } } while (0)
3216 ("Inside ShouldResistFingerprinting(nsIPrincipal*)"do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIPrincipal*)" " and AddonPolicy said false"
); } } while (0)
3217 " and AddonPolicy said false"))do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Debug)), 0))) {
mozilla::detail::log_print(moz_real_module, LogLevel::Debug,
"Inside ShouldResistFingerprinting(nsIPrincipal*)" " and AddonPolicy said false"
); } } while (0)
;
3218 return false;
3219 }
3220
3221 bool isExemptDomain = false;
3222 nsAutoCString list;
3223 nsRFPService::GetExemptedDomainsLowercase(list);
3224 aPrincipal->IsURIInList(list, &isExemptDomain);
3225
3226 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
3227 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
3228 nsAutoCString origin;
3229 aPrincipal->GetOrigin(origin);
3230 LogDomainAndList("URI", list, origin, isExemptDomain);
3231 }
3232
3233 if (isExemptDomain) {
3234 isExemptDomain &= PartionKeyIsAlsoExempted(originAttributes);
3235 }
3236
3237 return !isExemptDomain;
3238}
3239
3240// --------------------------------------------------------------------
3241
3242/* static */
3243void nsContentUtils::CalcRoundedWindowSizeForResistingFingerprinting(
3244 int32_t aChromeWidth, int32_t aChromeHeight, int32_t aScreenWidth,
3245 int32_t aScreenHeight, int32_t aInputWidth, int32_t aInputHeight,
3246 bool aSetOuterWidth, bool aSetOuterHeight, int32_t* aOutputWidth,
3247 int32_t* aOutputHeight) {
3248 MOZ_ASSERT(aOutputWidth)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aOutputWidth)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aOutputWidth))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aOutputWidth", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3248); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOutputWidth"
")"); do { MOZ_CrashSequence(__null, 3248); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3249 MOZ_ASSERT(aOutputHeight)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aOutputHeight)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aOutputHeight))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aOutputHeight",
"/root/firefox-clang/dom/base/nsContentUtils.cpp", 3249); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aOutputHeight" ")"); do { MOZ_CrashSequence
(__null, 3249); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3250
3251 int32_t availContentWidth = 0;
3252 int32_t availContentHeight = 0;
3253
3254 availContentWidth = std::min(StaticPrefs::privacy_window_maxInnerWidth(),
3255 aScreenWidth - aChromeWidth);
3256#ifdef MOZ_WIDGET_GTK1
3257 // In the GTK window, it will not report outside system decorations
3258 // when we get available window size, see Bug 581863. So, we leave a
3259 // 40 pixels space for them when calculating the available content
3260 // height. It is not necessary for the width since the content width
3261 // is usually pretty much the same as the chrome width.
3262 availContentHeight = std::min(StaticPrefs::privacy_window_maxInnerHeight(),
3263 (-40 + aScreenHeight) - aChromeHeight);
3264#else
3265 availContentHeight = std::min(StaticPrefs::privacy_window_maxInnerHeight(),
3266 aScreenHeight - aChromeHeight);
3267#endif
3268
3269 // Ideally, we'd like to round window size to 1000x1000, but the
3270 // screen space could be too small to accommodate this size in some
3271 // cases. If it happens, we would round the window size to the nearest
3272 // 200x100.
3273 availContentWidth = availContentWidth - (availContentWidth % 200);
3274 availContentHeight = availContentHeight - (availContentHeight % 100);
3275
3276 // If aIsOuter is true, we are setting the outer window. So we
3277 // have to consider the chrome UI.
3278 int32_t chromeOffsetWidth = aSetOuterWidth ? aChromeWidth : 0;
3279 int32_t chromeOffsetHeight = aSetOuterHeight ? aChromeHeight : 0;
3280 int32_t resultWidth = 0, resultHeight = 0;
3281
3282 // if the original size is greater than the maximum available size, we set
3283 // it to the maximum size. And if the original value is less than the
3284 // minimum rounded size, we set it to the minimum 200x100.
3285 if (aInputWidth > (availContentWidth + chromeOffsetWidth)) {
3286 resultWidth = availContentWidth + chromeOffsetWidth;
3287 } else if (aInputWidth < (200 + chromeOffsetWidth)) {
3288 resultWidth = 200 + chromeOffsetWidth;
3289 } else {
3290 // Otherwise, we round the window to the nearest upper rounded 200x100.
3291 resultWidth = NSToIntCeil((aInputWidth - chromeOffsetWidth) / 200.0) * 200 +
3292 chromeOffsetWidth;
3293 }
3294
3295 if (aInputHeight > (availContentHeight + chromeOffsetHeight)) {
3296 resultHeight = availContentHeight + chromeOffsetHeight;
3297 } else if (aInputHeight < (100 + chromeOffsetHeight)) {
3298 resultHeight = 100 + chromeOffsetHeight;
3299 } else {
3300 resultHeight =
3301 NSToIntCeil((aInputHeight - chromeOffsetHeight) / 100.0) * 100 +
3302 chromeOffsetHeight;
3303 }
3304
3305 *aOutputWidth = resultWidth;
3306 *aOutputHeight = resultHeight;
3307}
3308
3309bool nsContentUtils::ThreadsafeIsCallerChrome() {
3310 return NS_IsMainThread() ? IsCallerChrome()
3311 : IsCurrentThreadRunningChromeWorker();
3312}
3313
3314bool nsContentUtils::IsCallerUAWidget() {
3315 JSContext* cx = GetCurrentJSContext();
3316 if (!cx) {
3317 return false;
3318 }
3319
3320 JS::Realm* realm = JS::GetCurrentRealmOrNull(cx);
3321 if (!realm) {
3322 return false;
3323 }
3324
3325 return xpc::IsUAWidgetScope(realm);
3326}
3327
3328bool nsContentUtils::IsSystemCaller(JSContext* aCx) {
3329 // Note that SubjectPrincipal() assumes we are in a compartment here.
3330 return SubjectPrincipal(aCx) == sSystemPrincipal;
3331}
3332
3333bool nsContentUtils::ThreadsafeIsSystemCaller(JSContext* aCx) {
3334 CycleCollectedJSContext* ccjscx = CycleCollectedJSContext::Get();
3335 MOZ_ASSERT(ccjscx->Context() == aCx)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ccjscx->Context() == aCx)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(ccjscx->Context() == aCx)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("ccjscx->Context() == aCx"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3335); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ccjscx->Context() == aCx" ")"); do { MOZ_CrashSequence
(__null, 3335); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3336
3337 return ccjscx->IsSystemCaller();
3338}
3339
3340// static
3341bool nsContentUtils::LookupBindingMember(
3342 JSContext* aCx, nsIContent* aContent, JS::Handle<jsid> aId,
3343 JS::MutableHandle<JS::PropertyDescriptor> aDesc) {
3344 return true;
3345}
3346
3347nsINode* nsContentUtils::GetNearestInProcessCrossDocParentNode(
3348 nsINode* aChild) {
3349 if (aChild->IsDocument()) {
3350 for (BrowsingContext* bc = aChild->AsDocument()->GetBrowsingContext(); bc;
3351 bc = bc->GetParent()) {
3352 if (bc->GetEmbedderElement()) {
3353 return bc->GetEmbedderElement();
3354 }
3355 }
3356 return nullptr;
3357 }
3358
3359 nsINode* parent = aChild->GetParentNode();
3360 if (parent && parent->IsContent() && aChild->IsContent()) {
3361 parent = aChild->AsContent()->GetFlattenedTreeParent();
3362 }
3363
3364 return parent;
3365}
3366
3367bool nsContentUtils::ContentIsHostIncludingDescendantOf(
3368 const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) {
3369 MOZ_ASSERT(aPossibleDescendant, "The possible descendant is null!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPossibleDescendant)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPossibleDescendant))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("aPossibleDescendant"
" (" "The possible descendant is null!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3369); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { MOZ_CrashSequence
(__null, 3369); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3370 MOZ_ASSERT(aPossibleAncestor, "The possible ancestor is null!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPossibleAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPossibleAncestor))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aPossibleAncestor"
" (" "The possible ancestor is null!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { MOZ_CrashSequence
(__null, 3370); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3371
3372 while (true) {
3373 if (aPossibleDescendant == aPossibleAncestor) {
3374 return true;
3375 }
3376 if (nsINode* parent = aPossibleDescendant->GetParentNode()) {
3377 aPossibleDescendant = parent;
3378 continue;
3379 }
3380 if (auto* df = DocumentFragment::FromNode(aPossibleDescendant)) {
3381 if (nsINode* host = df->GetHost()) {
3382 aPossibleDescendant = host;
3383 continue;
3384 }
3385 }
3386 break;
3387 }
3388 return false;
3389}
3390
3391// static
3392bool nsContentUtils::ContentIsCrossDocDescendantOf(nsINode* aPossibleDescendant,
3393 nsINode* aPossibleAncestor) {
3394 MOZ_ASSERT(aPossibleDescendant, "The possible descendant is null!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPossibleDescendant)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPossibleDescendant))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("aPossibleDescendant"
" (" "The possible descendant is null!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3394); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { MOZ_CrashSequence
(__null, 3394); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3395 MOZ_ASSERT(aPossibleAncestor, "The possible ancestor is null!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPossibleAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPossibleAncestor))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aPossibleAncestor"
" (" "The possible ancestor is null!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3395); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { MOZ_CrashSequence
(__null, 3395); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3396
3397 do {
3398 if (aPossibleDescendant == aPossibleAncestor) {
3399 return true;
3400 }
3401
3402 aPossibleDescendant =
3403 GetNearestInProcessCrossDocParentNode(aPossibleDescendant);
3404 } while (aPossibleDescendant);
3405
3406 return false;
3407}
3408
3409// static
3410bool nsContentUtils::ContentIsFlattenedTreeDescendantOf(
3411 const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) {
3412 MOZ_ASSERT(aPossibleDescendant, "The possible descendant is null!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPossibleDescendant)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPossibleDescendant))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("aPossibleDescendant"
" (" "The possible descendant is null!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3412); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { MOZ_CrashSequence
(__null, 3412); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3413 MOZ_ASSERT(aPossibleAncestor, "The possible ancestor is null!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPossibleAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPossibleAncestor))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aPossibleAncestor"
" (" "The possible ancestor is null!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3413); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { MOZ_CrashSequence
(__null, 3413); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3414
3415 do {
3416 if (aPossibleDescendant == aPossibleAncestor) {
3417 return true;
3418 }
3419 aPossibleDescendant = aPossibleDescendant->GetFlattenedTreeParentNode();
3420 } while (aPossibleDescendant);
3421
3422 return false;
3423}
3424
3425// static
3426bool nsContentUtils::ContentIsFlattenedTreeDescendantOfForStyle(
3427 const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) {
3428 MOZ_ASSERT(aPossibleDescendant, "The possible descendant is null!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPossibleDescendant)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPossibleDescendant))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("aPossibleDescendant"
" (" "The possible descendant is null!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3428); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { MOZ_CrashSequence
(__null, 3428); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3429 MOZ_ASSERT(aPossibleAncestor, "The possible ancestor is null!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPossibleAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPossibleAncestor))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aPossibleAncestor"
" (" "The possible ancestor is null!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3429); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { MOZ_CrashSequence
(__null, 3429); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3430
3431 do {
3432 if (aPossibleDescendant == aPossibleAncestor) {
3433 return true;
3434 }
3435 aPossibleDescendant =
3436 aPossibleDescendant->GetFlattenedTreeParentNodeForStyle();
3437 } while (aPossibleDescendant);
3438
3439 return false;
3440}
3441
3442// static
3443nsINode* nsContentUtils::Retarget(nsINode* aTargetA, const nsINode* aTargetB) {
3444 while (true && aTargetA) {
3445 // If A's root is not a shadow root...
3446 nsINode* root = aTargetA->SubtreeRoot();
3447 if (!root->IsShadowRoot()) {
3448 // ...then return A.
3449 return aTargetA;
3450 }
3451
3452 // or A's root is a shadow-including inclusive ancestor of B...
3453 if (aTargetB && aTargetB->IsShadowIncludingInclusiveDescendantOf(root)) {
3454 // ...then return A.
3455 return aTargetA;
3456 }
3457
3458 aTargetA = ShadowRoot::FromNode(root)->GetHost();
3459 }
3460
3461 return nullptr;
3462}
3463
3464// static
3465Element* nsContentUtils::GetAnElementForTiming(Element* aTarget,
3466 const Document* aDocument,
3467 nsIGlobalObject* aGlobal) {
3468 if (!aTarget->IsInComposedDoc()) {
3469 return nullptr;
3470 }
3471
3472 if (!aDocument) {
3473 nsCOMPtr<nsPIDOMWindowInner> inner = do_QueryInterface(aGlobal);
3474 if (!inner) {
3475 return nullptr;
3476 }
3477 aDocument = inner->GetExtantDoc();
3478 }
3479
3480 MOZ_ASSERT(aDocument)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDocument))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aDocument", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { MOZ_CrashSequence(__null, 3480); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3481
3482 if (aTarget->GetUncomposedDocOrConnectedShadowRoot() != aDocument ||
3483 !aDocument->IsCurrentActiveDocument()) {
3484 return nullptr;
3485 }
3486
3487 return aTarget;
3488}
3489
3490// static
3491nsresult nsContentUtils::GetInclusiveAncestors(nsINode* aNode,
3492 nsTArray<nsINode*>& aArray) {
3493 while (aNode) {
3494 aArray.AppendElement(aNode);
3495 aNode = aNode->GetParentNode();
3496 }
3497 return NS_OK;
3498}
3499
3500// static
3501template <typename GetParentFunc, typename ComputeChildIndexFunc>
3502nsresult static GetInclusiveAncestorsAndOffsetsHelper(
3503 nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes,
3504 nsTArray<Maybe<uint32_t>>& aAncestorOffsets, GetParentFunc aGetParentFunc,
3505 ComputeChildIndexFunc aComputeChildIndexFunc) {
3506 NS_ENSURE_ARG_POINTER(aNode)do { if ((__builtin_expect(!!(!(aNode)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aNode" ") failed", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3506); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3507
3508 if (!aNode->IsContent()) {
3509 return NS_ERROR_FAILURE;
3510 }
3511 nsIContent* content = aNode->AsContent();
3512
3513 if (!aAncestorNodes.IsEmpty()) {
3514 NS_WARNING("aAncestorNodes is not empty")NS_DebugBreak(NS_DEBUG_WARNING, "aAncestorNodes is not empty"
, nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp",
3514)
;
3515 aAncestorNodes.Clear();
3516 }
3517
3518 if (!aAncestorOffsets.IsEmpty()) {
3519 NS_WARNING("aAncestorOffsets is not empty")NS_DebugBreak(NS_DEBUG_WARNING, "aAncestorOffsets is not empty"
, nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp",
3519)
;
3520 aAncestorOffsets.Clear();
3521 }
3522
3523 // insert the node itself
3524 aAncestorNodes.AppendElement(content);
3525 aAncestorOffsets.AppendElement(Some(aOffset));
3526
3527 // insert all the ancestors
3528 nsIContent* child = content;
3529 nsIContent* parent = aGetParentFunc(child);
3530 while (parent) {
3531 aAncestorNodes.AppendElement(parent->AsContent());
3532 aAncestorOffsets.AppendElement(aComputeChildIndexFunc(parent, child));
3533 child = parent;
3534 parent = aGetParentFunc(child);
3535 }
3536
3537 return NS_OK;
3538}
3539
3540nsresult nsContentUtils::GetInclusiveAncestorsAndOffsets(
3541 nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes,
3542 nsTArray<Maybe<uint32_t>>& aAncestorOffsets) {
3543 return GetInclusiveAncestorsAndOffsetsHelper(
3544 aNode, aOffset, aAncestorNodes, aAncestorOffsets,
3545 [](nsIContent* aContent) { return aContent->GetParent(); },
3546 [](nsIContent* aParent, nsIContent* aChild) {
3547 return aParent->ComputeIndexOf(aChild);
3548 });
3549}
3550
3551nsresult nsContentUtils::GetFlattenedTreeAncestorsAndOffsetsForSelection(
3552 nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes,
3553 nsTArray<Maybe<uint32_t>>& aAncestorOffsets) {
3554 return GetInclusiveAncestorsAndOffsetsHelper(
3555 aNode, aOffset, aAncestorNodes, aAncestorOffsets,
3556 [](nsIContent* aContent) -> nsIContent* {
3557 return nsIContent::FromNodeOrNull(
3558 GetParentNodeForComparison<TreeKind::FlatForSelection>::Get(
3559 aContent));
3560 },
3561 [](nsIContent* aParent, nsIContent* aChild) {
3562 return GetParentNodeForComparison<
3563 TreeKind::FlatForSelection>::ComputeChildIndex(aParent, aChild);
3564 });
3565}
3566
3567/* static */
3568nsINode* nsContentUtils::GetCommonAncestorHelper(nsINode* aNode1,
3569 nsINode* aNode2) {
3570 MOZ_ASSERT(aNode1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNode1)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aNode1))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aNode1", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3570); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ")"
); do { MOZ_CrashSequence(__null, 3570); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3571 MOZ_ASSERT(aNode2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNode2)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aNode2))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aNode2", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3571); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ")"
); do { MOZ_CrashSequence(__null, 3571); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3572 return CommonAncestors<GetParentNode>(*aNode1, *aNode2)
3573 .GetClosestCommonAncestor();
3574}
3575
3576/* static */
3577nsINode* nsContentUtils::GetClosestCommonShadowIncludingInclusiveAncestor(
3578 nsINode* aNode1, nsINode* aNode2) {
3579 if (aNode1 == aNode2) {
3580 return aNode1;
3581 }
3582
3583 MOZ_ASSERT(aNode1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNode1)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aNode1))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aNode1", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3583); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ")"
); do { MOZ_CrashSequence(__null, 3583); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3584 MOZ_ASSERT(aNode2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNode2)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aNode2))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aNode2", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3584); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ")"
); do { MOZ_CrashSequence(__null, 3584); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3585 return CommonAncestors<GetParentOrShadowHostNode>(*aNode1, *aNode2)
3586 .GetClosestCommonAncestor();
3587}
3588
3589/* static */
3590nsIContent* nsContentUtils::GetCommonFlattenedTreeAncestorHelper(
3591 nsIContent* aContent1, nsIContent* aContent2) {
3592 MOZ_ASSERT(aContent1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContent1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aContent1))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aContent1", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3592); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent1" ")"
); do { MOZ_CrashSequence(__null, 3592); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3593 MOZ_ASSERT(aContent2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContent2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aContent2))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aContent2", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3593); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent2" ")"
); do { MOZ_CrashSequence(__null, 3593); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3594 return CommonAncestors<GetFlattenedTreeParent>(*aContent1, *aContent2)
3595 .GetClosestCommonAncestor();
3596}
3597
3598/* static */
3599nsINode* nsContentUtils::GetCommonFlattenedTreeAncestorForSelection(
3600 nsINode* aNode1, nsINode* aNode2) {
3601 if (aNode1 == aNode2) {
3602 return aNode1;
3603 }
3604 MOZ_ASSERT(aNode1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNode1)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aNode1))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aNode1", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3604); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ")"
); do { MOZ_CrashSequence(__null, 3604); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3605 MOZ_ASSERT(aNode2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNode2)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aNode2))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aNode2", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3605); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ")"
); do { MOZ_CrashSequence(__null, 3605); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3606 return CommonAncestors<GetFlattenedTreeParentNodeForSelection>(*aNode1,
3607 *aNode2)
3608 .GetClosestCommonAncestor();
3609}
3610
3611/* static */
3612Element* nsContentUtils::GetCommonFlattenedTreeAncestorForStyle(
3613 Element* aElement1, Element* aElement2) {
3614 MOZ_ASSERT(aElement1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElement1))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aElement1", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3614); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement1" ")"
); do { MOZ_CrashSequence(__null, 3614); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3615 MOZ_ASSERT(aElement2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElement2))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aElement2", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3615); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement2" ")"
); do { MOZ_CrashSequence(__null, 3615); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3616 return CommonAncestors<GetFlattenedTreeParentElementForStyle>(*aElement1,
3617 *aElement2)
3618 .GetClosestCommonAncestor();
3619}
3620
3621/* static */
3622template <TreeKind aKind, typename Dummy>
3623Maybe<int32_t> nsContentUtils::CompareChildNodes(
3624 const nsINode& aParent, const nsIContent* aChild1,
3625 const nsIContent* aChild2, NodeIndexCache* aIndexCache /* = nullptr */) {
3626 MOZ_ASSERT_IF(aKind != TreeKind::DOM && aChild1,do { if (aKind != TreeKind::DOM && aChild1) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<aKind>::Get(aChild1) == &aParent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison<
aKind>::Get(aChild1) == &aParent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3627); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3627); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3627 GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent)do { if (aKind != TreeKind::DOM && aChild1) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<aKind>::Get(aChild1) == &aParent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison<
aKind>::Get(aChild1) == &aParent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3627); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3627); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3628 MOZ_ASSERT_IF(aKind != TreeKind::DOM && aChild2,do { if (aKind != TreeKind::DOM && aChild2) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<aKind>::Get(aChild2) == &aParent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison<
aKind>::Get(aChild2) == &aParent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3629); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3629); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3629 GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent)do { if (aKind != TreeKind::DOM && aChild2) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<aKind>::Get(aChild2) == &aParent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison<
aKind>::Get(aChild2) == &aParent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3629); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3629); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3630 // See the explanation of TreeKindToCompareChildren. aParent may be computed
3631 // with TreeKind::ShadowIncludingDOM if aKind is TreeKind::DOM.
3632 MOZ_ASSERT_IF(do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild1) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3636); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3636); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3633 aKind == TreeKind::DOM && aChild1,do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild1) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3636); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3636); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3634 GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent ||do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild1) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3636); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3636); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3635 GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get(do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild1) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3636); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3636); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3636 aChild1) == &aParent)do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild1) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3636); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3636); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3637 MOZ_ASSERT_IF(do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild2) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3641); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3641); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3638 aKind == TreeKind::DOM && aChild2,do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild2) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3641); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3641); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3639 GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent ||do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild2) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3641); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3641); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3640 GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get(do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild2) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3641); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3641); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3641 aChild2) == &aParent)do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild2) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3641); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3641); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3642
3643 // FIXME: bug 1946003 and bug 1946008.
3644 if ((aChild1 && NS_WARN_IF(aChild1->IsDocumentFragment())NS_warn_if_impl(aChild1->IsDocumentFragment(), "aChild1->IsDocumentFragment()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3644)
) ||
3645 (aChild2 && NS_WARN_IF(aChild2->IsDocumentFragment())NS_warn_if_impl(aChild2->IsDocumentFragment(), "aChild2->IsDocumentFragment()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3645)
)) [[unlikely]] {
3646 return Nothing();
3647 }
3648 if (MOZ_UNLIKELY(aChild1 == aChild2)(__builtin_expect(!!(aChild1 == aChild2), 0))) {
3649 return Some(0);
3650 }
3651 MOZ_ASSERT(aChild1 || aChild2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChild1 || aChild2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChild1 || aChild2))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aChild1 || aChild2"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3651); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aChild1 || aChild2" ")"); do { MOZ_CrashSequence
(__null, 3651); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3652 // Native anonymous content (e.g. ::before/::after pseudo-elements) is not in
3653 // the regular child list, so the sibling/index fast paths below cannot order
3654 // it against regular children or the end-of-children boundary (a null child).
3655 // GetIndexInParent assigns flat-tree-consistent indices to NAC roots, so use
3656 // it to order the points instead.
3657 if (MOZ_UNLIKELY((aChild1 && aChild1->IsRootOfNativeAnonymousSubtree()) ||(__builtin_expect(!!((aChild1 && aChild1->IsRootOfNativeAnonymousSubtree
()) || (aChild2 && aChild2->IsRootOfNativeAnonymousSubtree
())), 0))
3658 (aChild2 && aChild2->IsRootOfNativeAnonymousSubtree()))(__builtin_expect(!!((aChild1 && aChild1->IsRootOfNativeAnonymousSubtree
()) || (aChild2 && aChild2->IsRootOfNativeAnonymousSubtree
())), 0))
) {
3659 const nsINode& parent =
3660 aChild1 ? *GetParentNodeForComparison<aKind>::Get(aChild1)
3661 : *GetParentNodeForComparison<aKind>::Get(aChild2);
3662 // A null child is the boundary at the end of the parent's regular child
3663 // list (offset == number of regular children). Regular children occupy
3664 // indices [0, regularCount) in the index space assigned by
3665 // GetIndexInParent, while trailing NAC (other anonymous subtrees and
3666 // ::after) start at regularCount. The discriminator here must match the
3667 // one in GetIndexInParent so the boundary lands in the same index space:
3668 // only the flat tree indexes regular children via the flattened iterator;
3669 // DOM and ShadowIncludingDOM both index them via ComputeIndexOf.
3670 const int32_t regularCount =
3671 aKind == TreeKind::Flat
3672 ? int32_t(FlattenedChildIterator::GetLength(&parent))
3673 : int32_t(parent.GetChildCount());
3674 const auto indexOf = [&](const nsIContent* aChild) -> Maybe<int32_t> {
3675 if (!aChild) {
3676 return Some(regularCount);
3677 }
3678 return aIndexCache ? aIndexCache->ComputeIndexOf<aKind>(&parent, aChild)
3679 : GetIndexInParent<aKind>(&parent, aChild);
3680 };
3681 const Maybe<int32_t> child1Index = indexOf(aChild1);
3682 const Maybe<int32_t> child2Index = indexOf(aChild2);
3683 if (MOZ_LIKELY(child1Index.isSome() && child2Index.isSome())(__builtin_expect(!!(child1Index.isSome() && child2Index
.isSome()), 1))
) {
3684 if (*child1Index != *child2Index) {
3685 return Some(*child1Index < *child2Index ? -1 : 1);
3686 }
3687 // Equal indices only happen when one child is the end-of-children
3688 // boundary (null) and the other is the first trailing NAC subtree at the
3689 // same index. The boundary precedes trailing NAC in tree order.
3690 if (!aChild1) {
3691 return Some(-1);
3692 }
3693 if (!aChild2) {
3694 return Some(1);
3695 }
3696 }
3697 // XXX Keep the odd traditional behavior for now.
3698 return Some(1);
3699 }
3700 if (!aChild1) { // i.e., end of parent vs aChild2
3701 return Some(1);
3702 }
3703 if (!aChild2) { // i.e., aChild1 vs. end of parent
3704 return Some(-1);
3705 }
3706
3707 if constexpr (aKind == TreeKind::FlatForSelection) {
3708 // If we're handling flattened tree for selection, aChild1 and/or aChild2
3709 // may be:
3710 // - fallback content of a <slot> which has some assigned nodes
3711 // - unassigned child node of a shadow host
3712 // Even though they are not part of the flattened tree, but they are also
3713 // valid for range boundaries. Therefore, we need to handle the case here.
3714 if (aParent.GetAsHTMLSlotElementIfFilledForSelection() ||
3715 aParent.GetShadowRootForSelection()) {
3716 if (aChild1->GetParentNode() == &aParent) {
3717 if (aChild2->GetParentNode() == &aParent) {
3718 // If both aChild1 and aChild2 are the fallback content or the
3719 // unassigned children of a shadow host, compare them in the DOM.
3720 return CompareChildNodes<TreeKind::DOM>(aParent, aChild1, aChild2);
3721 }
3722 // If only aChild1 is the fallback content or the unassigned child,
3723 // let's treat it as after the last assigned node.
3724 return Some(1);
3725 }
3726 if (aChild2->GetParentNode() == &aParent) {
3727 // If only aChild2 is the fallback content or the unassigned child,
3728 // let's treat it as after the last assigned node for now.
3729 return Some(-1);
3730 }
3731 }
3732 }
3733
3734 if constexpr (ShouldHandleAssignedNodesOnSlot<aKind>()) {
3735 HTMLSlotElement* const slot1 = aChild1->GetAssignedSlot<aKind>();
3736 HTMLSlotElement* const slot2 = aChild2->GetAssignedSlot<aKind>();
3737 if (slot1 || slot2) {
3738 // If they are assigned into a same <slot>, compare the index.
3739 if (slot1 == slot2) {
3740 const auto* slot = HTMLSlotElement::FromNode(aParent);
3741 MOZ_ASSERT(slot)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slot)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(slot))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("slot", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3741); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slot" ")");
do { MOZ_CrashSequence(__null, 3741); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3742
3743 constexpr auto NoIndex = size_t(-1);
3744 auto child1Index = NoIndex;
3745 auto child2Index = NoIndex;
3746 size_t index = 0;
3747 for (nsINode* node : slot->AssignedNodes()) {
3748 if (node == aChild1) {
3749 child1Index = index;
3750 if (child2Index != NoIndex) {
3751 break;
3752 }
3753 } else if (node == aChild2) {
3754 child2Index = index;
3755 if (child1Index != NoIndex) {
3756 break;
3757 }
3758 }
3759 index++;
3760 }
3761
3762 MOZ_ASSERT(child1Index != NoIndex)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(child1Index != NoIndex)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(child1Index != NoIndex))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("child1Index != NoIndex"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3762); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "child1Index != NoIndex" ")"); do { MOZ_CrashSequence
(__null, 3762); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3763 MOZ_ASSERT(child2Index != NoIndex)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(child2Index != NoIndex)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(child2Index != NoIndex))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("child2Index != NoIndex"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3763); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "child2Index != NoIndex" ")"); do { MOZ_CrashSequence
(__null, 3763); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3764
3765 return Some(child1Index < child2Index ? -1 : 1);
3766 }
3767 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "aChild1 and aChild2 are not in same "
"<slot>:\naChild1={}\nslot1={}\naChild2={}\nslot2={}\n"
, ToString(*aChild1).c_str(), ToString(RefPtr{slot1}).c_str()
, ToString(*aChild2).c_str(), ToString(RefPtr{slot2}).c_str()
) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3773)
3768 fmt::format(NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "aChild1 and aChild2 are not in same "
"<slot>:\naChild1={}\nslot1={}\naChild2={}\nslot2={}\n"
, ToString(*aChild1).c_str(), ToString(RefPtr{slot1}).c_str()
, ToString(*aChild2).c_str(), ToString(RefPtr{slot2}).c_str()
) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3773)
3769 "aChild1 and aChild2 are not in same "NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "aChild1 and aChild2 are not in same "
"<slot>:\naChild1={}\nslot1={}\naChild2={}\nslot2={}\n"
, ToString(*aChild1).c_str(), ToString(RefPtr{slot1}).c_str()
, ToString(*aChild2).c_str(), ToString(RefPtr{slot2}).c_str()
) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3773)
3770 "<slot>:\naChild1={}\nslot1={}\naChild2={}\nslot2={}\n",NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "aChild1 and aChild2 are not in same "
"<slot>:\naChild1={}\nslot1={}\naChild2={}\nslot2={}\n"
, ToString(*aChild1).c_str(), ToString(RefPtr{slot1}).c_str()
, ToString(*aChild2).c_str(), ToString(RefPtr{slot2}).c_str()
) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3773)
3771 ToString(*aChild1).c_str(), ToString(RefPtr{slot1}).c_str(),NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "aChild1 and aChild2 are not in same "
"<slot>:\naChild1={}\nslot1={}\naChild2={}\nslot2={}\n"
, ToString(*aChild1).c_str(), ToString(RefPtr{slot1}).c_str()
, ToString(*aChild2).c_str(), ToString(RefPtr{slot2}).c_str()
) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3773)
3772 ToString(*aChild2).c_str(), ToString(RefPtr{slot2}).c_str())NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "aChild1 and aChild2 are not in same "
"<slot>:\naChild1={}\nslot1={}\naChild2={}\nslot2={}\n"
, ToString(*aChild1).c_str(), ToString(RefPtr{slot1}).c_str()
, ToString(*aChild2).c_str(), ToString(RefPtr{slot2}).c_str()
) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3773)
3773 .c_str())NS_DebugBreak(NS_DEBUG_WARNING, fmt::format( "aChild1 and aChild2 are not in same "
"<slot>:\naChild1={}\nslot1={}\naChild2={}\nslot2={}\n"
, ToString(*aChild1).c_str(), ToString(RefPtr{slot1}).c_str()
, ToString(*aChild2).c_str(), ToString(RefPtr{slot2}).c_str()
) .c_str(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3773)
;
3774 MOZ_ASSERT(!slot1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!slot1)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(!slot1))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!slot1", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3774); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!slot1" ")"
); do { MOZ_CrashSequence(__null, 3774); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3775 MOZ_ASSERT(!slot2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!slot2)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(!slot2))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!slot2", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3775); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!slot2" ")"
); do { MOZ_CrashSequence(__null, 3775); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3776 return Nothing();
3777 }
3778 }
3779
3780 ChildIteratorBase<aKind> iter(&aParent);
3781
3782 // If the parent node is not a shadow host, we can use
3783 // nsINode::GetNextSibling() and nsINode::GetPreviousSibling() in any trees
3784 // so that we can check whether aChild1 and aChild2 are adjacent siblings.
3785 if (MOZ_LIKELY(!iter.ShadowDOMInvolved())(__builtin_expect(!!(!iter.ShadowDOMInvolved()), 1))) {
3786 if (aChild1->GetNextSibling() == aChild2) {
3787 return Some(-1);
3788 }
3789 if (aChild2->GetNextSibling() == aChild1) {
3790 return Some(1);
3791 }
3792 }
3793
3794 // Retrieving the first child and the last child is not expensive so, let's
3795 // check whether aChild1 or aChild2 is the first/last child.
3796 const nsIContent* lastChild = iter.GetLastChild();
3797 MOZ_ASSERT(lastChild)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(lastChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(lastChild))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("lastChild", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3797); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastChild" ")"
); do { MOZ_CrashSequence(__null, 3797); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3798 if (aChild1 == lastChild) {
3799 return Some(1);
3800 }
3801 if (aChild2 == lastChild) {
3802 return Some(-1);
3803 }
3804 const nsIContent* firstChild = iter.GetFirstChild();
3805 MOZ_ASSERT(firstChild)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(firstChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(firstChild))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("firstChild", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3805); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstChild"
")"); do { MOZ_CrashSequence(__null, 3805); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3806 MOZ_ASSERT(firstChild != lastChild)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(firstChild != lastChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(firstChild != lastChild))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("firstChild != lastChild"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3806); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "firstChild != lastChild" ")"); do { MOZ_CrashSequence
(__null, 3806); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3807 if (aChild1 == firstChild) {
3808 return Some(-1);
3809 }
3810 if (aChild2 == firstChild) {
3811 return Some(1);
3812 }
3813
3814 // nsINode::ComputeIndexOf() computes the index with scanning siblings from
3815 // the first child in the worst case. However, if the node caches the
3816 // computed result, the scan range may be narrowed in fortunate cases.
3817 // Therefore, if the node uses the cache, we should use it because the callers
3818 // may need to compute the index again. In such cases, the cache saves the
3819 // computation cost.
3820 if (aParent.MaybeCachesComputedIndex()) {
3821 Maybe<uint32_t> child1Index;
3822 Maybe<uint32_t> child2Index;
3823 if (aIndexCache) {
3824 Maybe<int32_t> maybeGenContentChild1Index;
3825 Maybe<int32_t> maybeGenContentChild2Index;
3826 aIndexCache->ComputeIndicesOf<aKind>(&aParent, aChild1, aChild2,
3827 maybeGenContentChild1Index,
3828 maybeGenContentChild2Index);
3829 // Negative offset if the child is generated content or native anonymous
3830 // content. However, this method does not support such nodes. Therefore,
3831 // we should treat them as "disconnected".
3832 if (maybeGenContentChild1Index && *maybeGenContentChild1Index >= 0) {
3833 child1Index.emplace(static_cast<uint32_t>(*maybeGenContentChild1Index));
3834 }
3835 if (maybeGenContentChild2Index && *maybeGenContentChild2Index >= 0) {
3836 child2Index.emplace(static_cast<uint32_t>(*maybeGenContentChild2Index));
3837 }
3838#ifdef DEBUG1
3839 const Maybe<uint32_t> child1IndexDebug =
3840 aParent.ComputeIndexOf<aKind>(aChild1);
3841 NS_WARNING_ASSERTION(do { if (!(child1Index == child1IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child1IndexDebug), ToString
(child1Index), ToString(aParent), ToString(*aChild1)) .c_str(
), "child1Index == child1IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3847); } } while (false)
3842 child1Index == child1IndexDebug,do { if (!(child1Index == child1IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child1IndexDebug), ToString
(child1Index), ToString(aParent), ToString(*aChild1)) .c_str(
), "child1Index == child1IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3847); } } while (false)
3843 fmt::format("aIndexCache causes wrong index: expected {}, but got "do { if (!(child1Index == child1IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child1IndexDebug), ToString
(child1Index), ToString(aParent), ToString(*aChild1)) .c_str(
), "child1Index == child1IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3847); } } while (false)
3844 "{}\naParent={}\naChild1={}\n",do { if (!(child1Index == child1IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child1IndexDebug), ToString
(child1Index), ToString(aParent), ToString(*aChild1)) .c_str(
), "child1Index == child1IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3847); } } while (false)
3845 ToString(child1IndexDebug), ToString(child1Index),do { if (!(child1Index == child1IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child1IndexDebug), ToString
(child1Index), ToString(aParent), ToString(*aChild1)) .c_str(
), "child1Index == child1IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3847); } } while (false)
3846 ToString(aParent), ToString(*aChild1))do { if (!(child1Index == child1IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child1IndexDebug), ToString
(child1Index), ToString(aParent), ToString(*aChild1)) .c_str(
), "child1Index == child1IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3847); } } while (false)
3847 .c_str())do { if (!(child1Index == child1IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child1IndexDebug), ToString
(child1Index), ToString(aParent), ToString(*aChild1)) .c_str(
), "child1Index == child1IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3847); } } while (false)
;
3848 MOZ_ASSERT(child1Index == child1IndexDebug)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(child1Index == child1IndexDebug)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(child1Index == child1IndexDebug
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"child1Index == child1IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3848); AnnotateMozCrashReason("MOZ_ASSERT" "(" "child1Index == child1IndexDebug"
")"); do { MOZ_CrashSequence(__null, 3848); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3849 const Maybe<uint32_t> child2IndexDebug =
3850 aParent.ComputeIndexOf<aKind>(aChild2);
3851 NS_WARNING_ASSERTION(do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString
(child2Index), ToString(aParent), ToString(*aChild2)) .c_str(
), "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3857); } } while (false)
3852 child2Index == child2IndexDebug,do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString
(child2Index), ToString(aParent), ToString(*aChild2)) .c_str(
), "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3857); } } while (false)
3853 fmt::format("aIndexCache causes wrong index: expected {}, but got "do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString
(child2Index), ToString(aParent), ToString(*aChild2)) .c_str(
), "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3857); } } while (false)
3854 "{}\naParent={}\naChild1={}\n",do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString
(child2Index), ToString(aParent), ToString(*aChild2)) .c_str(
), "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3857); } } while (false)
3855 ToString(child2IndexDebug), ToString(child2Index),do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString
(child2Index), ToString(aParent), ToString(*aChild2)) .c_str(
), "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3857); } } while (false)
3856 ToString(aParent), ToString(*aChild2))do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString
(child2Index), ToString(aParent), ToString(*aChild2)) .c_str(
), "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3857); } } while (false)
3857 .c_str())do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString
(child2Index), ToString(aParent), ToString(*aChild2)) .c_str(
), "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3857); } } while (false)
;
3858 MOZ_ASSERT(child2Index == child2IndexDebug)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(child2Index == child2IndexDebug)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(child2Index == child2IndexDebug
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3858); AnnotateMozCrashReason("MOZ_ASSERT" "(" "child2Index == child2IndexDebug"
")"); do { MOZ_CrashSequence(__null, 3858); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3859#endif // #ifdef DEBUG
3860 } else {
3861 child1Index = aParent.ComputeIndexOf<aKind>(aChild1);
3862 child2Index = aParent.ComputeIndexOf<aKind>(aChild2);
3863 }
3864 if (MOZ_LIKELY(child1Index.isSome() && child2Index.isSome())(__builtin_expect(!!(child1Index.isSome() && child2Index
.isSome()), 1))
) {
3865 MOZ_ASSERT(*child1Index != *child2Index)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(*child1Index != *child2Index)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*child1Index != *child2Index
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"*child1Index != *child2Index", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3865); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*child1Index != *child2Index"
")"); do { MOZ_CrashSequence(__null, 3865); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3866 return Some(*child1Index < *child2Index ? -1 : 1);
3867 }
3868 // XXX Keep the odd traditional behavior for now.
3869 return Some(child1Index.isNothing() && child2Index.isSome() ? -1 : 1);
3870 }
3871
3872 // On the other hand, it does not use the cache, let's scan siblings starting
3873 // from aChild1. Then, if we find aChild2, the position is aChild1 < aChild2.
3874 // Otherwise, aChild2 < aChild1. This narrows the scanning range than using
3875 // ComputeIndexOf(), i.e., even in the worst case, this is faster than a call
3876 // of ComputeIndexOf().
3877 if (NS_WARN_IF(!iter.Seek(aChild1))NS_warn_if_impl(!iter.Seek(aChild1), "!iter.Seek(aChild1)", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3877)
) {
3878 return Nothing{};
3879 }
3880 for (const nsIContent* followingSiblingOfChild1 = iter.GetNextChild();
3881 followingSiblingOfChild1;
3882 followingSiblingOfChild1 = iter.GetNextChild()) {
3883 if (followingSiblingOfChild1 == aChild2) {
3884 return Some(-1);
3885 }
3886 }
3887 MOZ_ASSERT(aParent.ComputeIndexOf<aKind>(aChild2).isSome())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParent.ComputeIndexOf<aKind>(aChild2).isSome(
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aParent.ComputeIndexOf<aKind>(aChild2).isSome(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aParent.ComputeIndexOf<aKind>(aChild2).isSome()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3887); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent.ComputeIndexOf<aKind>(aChild2).isSome()"
")"); do { MOZ_CrashSequence(__null, 3887); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3888 return Some(1);
3889}
3890
3891/* static */
3892template <TreeKind aKind, typename Dummy>
3893Maybe<int32_t> nsContentUtils::CompareClosestCommonAncestorChildren(
3894 const nsINode& aParent, const nsIContent* aChild1,
3895 const nsIContent* aChild2, nsContentUtils::NodeIndexCache* aIndexCache) {
3896 MOZ_ASSERT_IF(aKind != TreeKind::DOM && aChild1,do { if (aKind != TreeKind::DOM && aChild1) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<aKind>::Get(aChild1) == &aParent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison<
aKind>::Get(aChild1) == &aParent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3897); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3897); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3897 GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent)do { if (aKind != TreeKind::DOM && aChild1) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<aKind>::Get(aChild1) == &aParent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison<
aKind>::Get(aChild1) == &aParent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3897); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3897); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3898 MOZ_ASSERT_IF(aKind != TreeKind::DOM && aChild2,do { if (aKind != TreeKind::DOM && aChild2) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<aKind>::Get(aChild2) == &aParent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison<
aKind>::Get(aChild2) == &aParent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3899); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3899); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3899 GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent)do { if (aKind != TreeKind::DOM && aChild2) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<aKind>::Get(aChild2) == &aParent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison<
aKind>::Get(aChild2) == &aParent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3899); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3899); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3900 // See the explanation of TreeKindToCompareChildren. aParent may be computed
3901 // with TreeKind::ShadowIncludingDOM if aKind is TreeKind::DOM.
3902 MOZ_ASSERT_IF(do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild1) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3906); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3906); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3903 aKind == TreeKind::DOM && aChild1,do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild1) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3906); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3906); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3904 GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent ||do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild1) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3906); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3906); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3905 GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get(do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild1) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3906); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3906); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3906 aChild1) == &aParent)do { if (aKind == TreeKind::DOM && aChild1) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild1) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild1) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3906); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3906); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3907 MOZ_ASSERT_IF(do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild2) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3911); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3911); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3908 aKind == TreeKind::DOM && aChild2,do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild2) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3911); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3911); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3909 GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent ||do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild2) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3911); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3911); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3910 GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get(do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild2) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3911); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3911); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3911 aChild2) == &aParent)do { if (aKind == TreeKind::DOM && aChild2) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(aChild2) == &aParent || GetParentNodeForComparison<TreeKind
::ShadowIncludingDOM>::Get( aChild2) == &aParent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3911); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3911); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3912
3913 if (aChild1 && aChild2) {
3914 if (MOZ_UNLIKELY(aChild1->IsShadowRoot())(__builtin_expect(!!(aChild1->IsShadowRoot()), 0))) {
3915 // Shadow roots come before light DOM per
3916 // https://dom.spec.whatwg.org/#concept-shadow-including-tree-order
3917 MOZ_ASSERT(!aChild2->IsShadowRoot(), "Two shadow roots?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aChild2->IsShadowRoot())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aChild2->IsShadowRoot())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aChild2->IsShadowRoot()"
" (" "Two shadow roots?" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3917); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChild2->IsShadowRoot()"
") (" "Two shadow roots?" ")"); do { MOZ_CrashSequence(__null
, 3917); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
3918 return Some(-1);
3919 }
3920 if (MOZ_UNLIKELY(aChild2->IsShadowRoot())(__builtin_expect(!!(aChild2->IsShadowRoot()), 0))) {
3921 return Some(1);
3922 }
3923 }
3924 // FIXME: bug 1946003 and bug 1946008.
3925 if (MOZ_UNLIKELY((aChild1 && aChild1->IsDocumentFragment()) ||(__builtin_expect(!!((aChild1 && aChild1->IsDocumentFragment
()) || (aChild2 && aChild2->IsDocumentFragment()))
, 0))
3926 (aChild2 && aChild2->IsDocumentFragment()))(__builtin_expect(!!((aChild1 && aChild1->IsDocumentFragment
()) || (aChild2 && aChild2->IsDocumentFragment()))
, 0))
) {
3927 // XXX Keep the odd traditional behavior for now. I think that we should
3928 // return Nothing in this case.
3929 return Some(1);
3930 }
3931
3932 const Maybe<int32_t> comp = nsContentUtils::CompareChildNodes<aKind>(
3933 aParent, aChild1, aChild2, aIndexCache);
3934 if (MOZ_UNLIKELY(comp.isNothing())(__builtin_expect(!!(comp.isNothing()), 0))) {
3935 NS_ASSERTION(comp.isSome(),do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "nsContentUtils::CompareChildNodes() must return Some here. "
"It should've already checked before we call it.", "comp.isSome()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3937); MOZ_PretendNoReturn
(); } } while (0)
3936 "nsContentUtils::CompareChildNodes() must return Some here. "do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "nsContentUtils::CompareChildNodes() must return Some here. "
"It should've already checked before we call it.", "comp.isSome()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3937); MOZ_PretendNoReturn
(); } } while (0)
3937 "It should've already checked before we call it.")do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "nsContentUtils::CompareChildNodes() must return Some here. "
"It should've already checked before we call it.", "comp.isSome()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3937); MOZ_PretendNoReturn
(); } } while (0)
;
3938 // XXX Keep the odd traditional behavior for now. I think that we should
3939 // return Nothing in this case.
3940 return Some(1);
3941 }
3942#ifdef DEBUG1
3943 const auto NodeIsNullOrValidChild = [](const nsINode& aParent,
3944 const nsIContent* aChild) {
3945 if (!aChild || aParent.ComputeIndexOf<aKind>(aChild).isSome()) {
3946 return true;
3947 }
3948 if constexpr (aKind == TreeKind::FlatForSelection) {
3949 const Element* const excluderShadowHostOrSlotElement =
3950 aChild->GetClosestFlatTreeAncestorElementForNonFlatTreeNode<
3951 TreeKind::FlatForSelection>();
3952 if (excluderShadowHostOrSlotElement &&
3953 (excluderShadowHostOrSlotElement == &aParent ||
3954 excluderShadowHostOrSlotElement->GetShadowRootForSelection() ==
3955 &aParent)) {
3956 return true;
3957 }
3958 }
3959 return false;
3960 };
3961 const auto ChildrenHaveSameIndex = [](const nsIContent* aChild1,
3962 const nsIContent* aChild2) {
3963 if (aChild1 == aChild2) {
3964 return true;
3965 }
3966 const bool child1IsAtEndOfParent =
3967 !aChild1 ||
3968 (aKind == TreeKind::FlatForSelection &&
3969 aChild1->GetClosestFlatTreeAncestorElementForNonFlatTreeNode<
3970 TreeKind::FlatForSelection>());
3971 const bool child2IsAtEndOfParent =
3972 !aChild2 ||
3973 (aKind == TreeKind::FlatForSelection &&
3974 aChild2->GetClosestFlatTreeAncestorElementForNonFlatTreeNode<
3975 TreeKind::FlatForSelection>());
3976 return child1IsAtEndOfParent && child2IsAtEndOfParent;
3977 };
3978 const auto ChildIndexIsLessThanTheOtherChildIndex =
3979 [](const nsINode& aParent, const nsIContent* aChild1,
3980 const nsIContent* aChild2) {
3981 const uint32_t child1Index =
3982 aChild1 ? aParent.ComputeIndexOf<aKind>(aChild1).valueOr(
3983 aParent.GetChildCount<aKind>())
3984 : aParent.GetChildCount<aKind>();
3985 const uint32_t child2Index =
3986 aChild2 ? aParent.ComputeIndexOf<aKind>(aChild2).valueOr(
3987 aParent.GetChildCount<aKind>())
3988 : aParent.GetChildCount<aKind>();
3989 return child1Index < child2Index;
3990 };
3991 NS_WARNING_ASSERTION(do { if (!(NodeIsNullOrValidChild(aParent, aChild1))) { NS_DebugBreak
(NS_DEBUG_WARNING, fmt::format("aKind={}: aChild1 is not a child of aParent:\n{}\nin:\n{}"
, aKind, ToString(*aChild1), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3995); }
} while (false)
3992 NodeIsNullOrValidChild(aParent, aChild1),do { if (!(NodeIsNullOrValidChild(aParent, aChild1))) { NS_DebugBreak
(NS_DEBUG_WARNING, fmt::format("aKind={}: aChild1 is not a child of aParent:\n{}\nin:\n{}"
, aKind, ToString(*aChild1), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3995); }
} while (false)
3993 fmt::format("aKind={}: aChild1 is not a child of aParent:\n{}\nin:\n{}",do { if (!(NodeIsNullOrValidChild(aParent, aChild1))) { NS_DebugBreak
(NS_DEBUG_WARNING, fmt::format("aKind={}: aChild1 is not a child of aParent:\n{}\nin:\n{}"
, aKind, ToString(*aChild1), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3995); }
} while (false)
3994 aKind, ToString(*aChild1), ToString(aParent))do { if (!(NodeIsNullOrValidChild(aParent, aChild1))) { NS_DebugBreak
(NS_DEBUG_WARNING, fmt::format("aKind={}: aChild1 is not a child of aParent:\n{}\nin:\n{}"
, aKind, ToString(*aChild1), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3995); }
} while (false)
3995 .c_str())do { if (!(NodeIsNullOrValidChild(aParent, aChild1))) { NS_DebugBreak
(NS_DEBUG_WARNING, fmt::format("aKind={}: aChild1 is not a child of aParent:\n{}\nin:\n{}"
, aKind, ToString(*aChild1), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3995); }
} while (false)
;
3996 NS_WARNING_ASSERTION(do { if (!(NodeIsNullOrValidChild(aParent, aChild2))) { NS_DebugBreak
(NS_DEBUG_WARNING, fmt::format("aKind={}:aChild2 is not a child of aParent:\n{}\nin:\n{}"
, aKind, ToString(*aChild2), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4000); }
} while (false)
3997 NodeIsNullOrValidChild(aParent, aChild2),do { if (!(NodeIsNullOrValidChild(aParent, aChild2))) { NS_DebugBreak
(NS_DEBUG_WARNING, fmt::format("aKind={}:aChild2 is not a child of aParent:\n{}\nin:\n{}"
, aKind, ToString(*aChild2), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4000); }
} while (false)
3998 fmt::format("aKind={}:aChild2 is not a child of aParent:\n{}\nin:\n{}",do { if (!(NodeIsNullOrValidChild(aParent, aChild2))) { NS_DebugBreak
(NS_DEBUG_WARNING, fmt::format("aKind={}:aChild2 is not a child of aParent:\n{}\nin:\n{}"
, aKind, ToString(*aChild2), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4000); }
} while (false)
3999 aKind, ToString(*aChild2), ToString(aParent))do { if (!(NodeIsNullOrValidChild(aParent, aChild2))) { NS_DebugBreak
(NS_DEBUG_WARNING, fmt::format("aKind={}:aChild2 is not a child of aParent:\n{}\nin:\n{}"
, aKind, ToString(*aChild2), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4000); }
} while (false)
4000 .c_str())do { if (!(NodeIsNullOrValidChild(aParent, aChild2))) { NS_DebugBreak
(NS_DEBUG_WARNING, fmt::format("aKind={}:aChild2 is not a child of aParent:\n{}\nin:\n{}"
, aKind, ToString(*aChild2), ToString(aParent)) .c_str(), "NodeIsNullOrValidChild(aParent, aChild2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4000); }
} while (false)
;
4001 MOZ_ASSERT_IF(!*comp, aChild1 == aChild2)do { if (!*comp) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(aChild1 == aChild2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChild1 == aChild2))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aChild1 == aChild2"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4001); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aChild1 == aChild2" ")"); do { MOZ_CrashSequence
(__null, 4001); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
4002 const DebugOnly<bool> eitherIsNAC =
4003 (aChild1 && aChild1->IsRootOfNativeAnonymousSubtree()) ||
4004 (aChild2 && aChild2->IsRootOfNativeAnonymousSubtree());
4005 const DebugOnly<bool> eitherIsNotPartOfTree =
4006 ShouldHandleAssignedNodesOnSlot<aKind>() &&
4007 ((aParent.GetShadowRoot<aKind>() &&
4008 ((aChild1 && aChild1->GetParentNode() == &aParent) ||
4009 (aChild2 && aChild2->GetParentNode() == &aParent))) ||
4010 ((aParent.GetAsHTMLSlotElementIfFilled<aKind>() &&
4011 ((aChild1 && !aChild1->GetAssignedSlot<aKind>()) ||
4012 (aChild2 && !aChild2->GetAssignedSlot<aKind>())))));
4013 MOZ_ASSERT_IF(!eitherIsNAC && !*comp,do { if (!eitherIsNAC && !*comp) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(ChildrenHaveSameIndex
(aChild1, aChild2))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(ChildrenHaveSameIndex(aChild1
, aChild2)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("ChildrenHaveSameIndex(aChild1, aChild2)", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4014); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChildrenHaveSameIndex(aChild1, aChild2)"
")"); do { MOZ_CrashSequence(__null, 4014); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4014 ChildrenHaveSameIndex(aChild1, aChild2))do { if (!eitherIsNAC && !*comp) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(ChildrenHaveSameIndex
(aChild1, aChild2))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(ChildrenHaveSameIndex(aChild1
, aChild2)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("ChildrenHaveSameIndex(aChild1, aChild2)", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4014); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChildrenHaveSameIndex(aChild1, aChild2)"
")"); do { MOZ_CrashSequence(__null, 4014); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4015 MOZ_ASSERT_IF(do { if (!eitherIsNAC && !eitherIsNotPartOfTree &&
*comp < 0) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1
, aChild2))>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(ChildIndexIsLessThanTheOtherChildIndex
(aParent, aChild1, aChild2)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4017); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2)"
")"); do { MOZ_CrashSequence(__null, 4017); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4016 !eitherIsNAC && !eitherIsNotPartOfTree && *comp < 0,do { if (!eitherIsNAC && !eitherIsNotPartOfTree &&
*comp < 0) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1
, aChild2))>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(ChildIndexIsLessThanTheOtherChildIndex
(aParent, aChild1, aChild2)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4017); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2)"
")"); do { MOZ_CrashSequence(__null, 4017); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4017 ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2))do { if (!eitherIsNAC && !eitherIsNotPartOfTree &&
*comp < 0) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1
, aChild2))>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(ChildIndexIsLessThanTheOtherChildIndex
(aParent, aChild1, aChild2)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4017); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2)"
")"); do { MOZ_CrashSequence(__null, 4017); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4018 MOZ_ASSERT_IF(do { if (!eitherIsNAC && !eitherIsNotPartOfTree &&
*comp > 0) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2
, aChild1))>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(ChildIndexIsLessThanTheOtherChildIndex
(aParent, aChild2, aChild1)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4020); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1)"
")"); do { MOZ_CrashSequence(__null, 4020); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4019 !eitherIsNAC && !eitherIsNotPartOfTree && *comp > 0,do { if (!eitherIsNAC && !eitherIsNotPartOfTree &&
*comp > 0) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2
, aChild1))>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(ChildIndexIsLessThanTheOtherChildIndex
(aParent, aChild2, aChild1)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4020); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1)"
")"); do { MOZ_CrashSequence(__null, 4020); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4020 ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1))do { if (!eitherIsNAC && !eitherIsNotPartOfTree &&
*comp > 0) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2
, aChild1))>::isValid, "invalid assertion condition"); if (
(__builtin_expect(!!(!(!!(ChildIndexIsLessThanTheOtherChildIndex
(aParent, aChild2, aChild1)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4020); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1)"
")"); do { MOZ_CrashSequence(__null, 4020); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4021#endif // #ifdef DEBUG
4022 return comp;
4023}
4024
4025/* static */
4026template <TreeKind aKind, typename Dummy>
4027Maybe<int32_t> nsContentUtils::CompareChildOffsetAndChildNode(
4028 const nsINode& aParent, uint32_t aOffset1, const nsIContent& aChild2,
4029 NodeIndexCache* aIndexCache /* = nullptr */) {
4030 MOZ_ASSERT_IF(aKind != TreeKind::DOM,do { if (aKind != TreeKind::DOM) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<aKind>::Get(&aChild2) == &aParent)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(GetParentNodeForComparison<aKind>::Get(&aChild2)
== &aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4031); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4031); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4031 GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent)do { if (aKind != TreeKind::DOM) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<aKind>::Get(&aChild2) == &aParent)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(GetParentNodeForComparison<aKind>::Get(&aChild2)
== &aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4031); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4031); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4032 // See the explanation of TreeKindToCompareChildren. aParent may be computed
4033 // with TreeKind::ShadowIncludingDOM if aKind is TreeKind::DOM.
4034 MOZ_ASSERT_IF(do { if (aKind == TreeKind::DOM) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &
aParent)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(&aChild2) == &aParent || GetParentNodeForComparison<
TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &
aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4038); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4038); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4035 aKind == TreeKind::DOM,do { if (aKind == TreeKind::DOM) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &
aParent)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(&aChild2) == &aParent || GetParentNodeForComparison<
TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &
aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4038); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4038); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4036 GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent ||do { if (aKind == TreeKind::DOM) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &
aParent)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(&aChild2) == &aParent || GetParentNodeForComparison<
TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &
aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4038); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4038); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4037 GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get(do { if (aKind == TreeKind::DOM) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &
aParent)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(&aChild2) == &aParent || GetParentNodeForComparison<
TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &
aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4038); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4038); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4038 &aChild2) == &aParent)do { if (aKind == TreeKind::DOM) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(GetParentNodeForComparison
<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison
<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &
aParent)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(GetParentNodeForComparison<TreeKind::DOM>::Get
(&aChild2) == &aParent || GetParentNodeForComparison<
TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &
aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4038); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4038); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4039
4040 if (NS_WARN_IF(aChild2.IsDocumentFragment())NS_warn_if_impl(aChild2.IsDocumentFragment(), "aChild2.IsDocumentFragment()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4040)
) {
4041 return Nothing();
4042 }
4043 // Native anonymous content (e.g. ::before/::after) is not in the regular
4044 // child list, so order it against the [parentNode, aOffset1] boundary using
4045 // the flat-tree index space from GetIndexInParent. aOffset1 indexes regular
4046 // children [0, N); the NAC child sits at child2Index in the same space, and
4047 // the boundary precedes it iff aOffset1 <= child2Index.
4048 if (MOZ_UNLIKELY(aChild2.IsRootOfNativeAnonymousSubtree())(__builtin_expect(!!(aChild2.IsRootOfNativeAnonymousSubtree()
), 0))
) {
4049 const Maybe<int32_t> child2Index =
4050 aIndexCache ? aIndexCache->ComputeIndexOf<aKind>(&aParent, &aChild2)
4051 : GetIndexInParent<aKind>(&aParent, &aChild2);
4052 if (NS_WARN_IF(child2Index.isNothing())NS_warn_if_impl(child2Index.isNothing(), "child2Index.isNothing()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4052)
) {
4053 // XXX Keep the odd traditional behavior for now.
4054 return Some(1);
4055 }
4056 return Some(int32_t(aOffset1) <= *child2Index ? -1 : 1);
4057 }
4058
4059 MOZ_ASSERT(GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetParentNodeForComparison<aKind>::Get(&aChild2
) == &aParent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison<
aKind>::Get(&aChild2) == &aParent))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4059); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4059); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4060
4061 const uint32_t parentNodeChildCount = aParent.GetChildCount<aKind>();
4062 if (NS_WARN_IF(aOffset1 > parentNodeChildCount)NS_warn_if_impl(aOffset1 > parentNodeChildCount, "aOffset1 > parentNodeChildCount"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4062)
) {
4063 // If the root caller's boundary points after end of aParent, let's treat
4064 // it's after the fallback content for now... If you find a bug and you know
4065 // better result in this case, feel free to change.
4066 return Some(1);
4067 }
4068
4069 if constexpr (aKind == TreeKind::FlatForSelection) {
4070 // If we're handling flattened tree for selection, aChild2 may be a fallback
4071 // content of a <slot> which has some assigned nodes or an unassigned child
4072 // node of a shadow host. Then, aChild2 is not part of the flattened tree,
4073 // but it is also valid for range boundaries. Therefore, we need to handle
4074 // the case here.
4075 if (aChild2.GetParentNode() == &aParent &&
4076 (aParent.GetAsHTMLSlotElementIfFilledForSelection() ||
4077 aParent.GetShadowRootForSelection())) {
4078 // Treat the fallback content and the unassigned node is after the last
4079 // assigned node or the shadow.
4080 // XXX I'm not sure whether we should treat the end of aParent and a
4081 // fallback content node are the same position or not. For now, we treat
4082 // them as the same, but if you find a bug and you know better result in
4083 // this case, feel free to change here.
4084 return aOffset1 == parentNodeChildCount ? Some(0) : Some(-1);
4085 }
4086 }
4087
4088 if (aOffset1 == parentNodeChildCount) {
4089 return Some(1); // Comparing with after the last child and a child.
4090 }
4091
4092 MOZ_ASSERT(aParent.GetFirstChild<aKind>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParent.GetFirstChild<aKind>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aParent.GetFirstChild<aKind
>()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aParent.GetFirstChild<aKind>()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4092); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent.GetFirstChild<aKind>()"
")"); do { MOZ_CrashSequence(__null, 4092); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4093 const nsIContent& firstChild = *aParent.GetFirstChild<aKind>();
4094 if (&aChild2 == &firstChild) {
4095 return Some(!aOffset1 ? 0 : 1);
4096 }
4097
4098 MOZ_ASSERT(aParent.GetLastChild<aKind>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParent.GetLastChild<aKind>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aParent.GetLastChild<aKind
>()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aParent.GetLastChild<aKind>()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4098); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent.GetLastChild<aKind>()"
")"); do { MOZ_CrashSequence(__null, 4098); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4099 const nsIContent& lastChild = *aParent.GetLastChild<aKind>();
4100 NS_WARNING_ASSERTION(do { if (!(&firstChild != &lastChild)) { NS_DebugBreak
(NS_DEBUG_WARNING, fmt::format("The should be 2 or more children:\nchild={}\naChild2={}\n"
, ToString(firstChild), ToString(aChild2)) .c_str(), "&firstChild != &lastChild"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4104); }
} while (false)
4101 &firstChild != &lastChild,do { if (!(&firstChild != &lastChild)) { NS_DebugBreak
(NS_DEBUG_WARNING, fmt::format("The should be 2 or more children:\nchild={}\naChild2={}\n"
, ToString(firstChild), ToString(aChild2)) .c_str(), "&firstChild != &lastChild"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4104); }
} while (false)
4102 fmt::format("The should be 2 or more children:\nchild={}\naChild2={}\n",do { if (!(&firstChild != &lastChild)) { NS_DebugBreak
(NS_DEBUG_WARNING, fmt::format("The should be 2 or more children:\nchild={}\naChild2={}\n"
, ToString(firstChild), ToString(aChild2)) .c_str(), "&firstChild != &lastChild"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4104); }
} while (false)
4103 ToString(firstChild), ToString(aChild2))do { if (!(&firstChild != &lastChild)) { NS_DebugBreak
(NS_DEBUG_WARNING, fmt::format("The should be 2 or more children:\nchild={}\naChild2={}\n"
, ToString(firstChild), ToString(aChild2)) .c_str(), "&firstChild != &lastChild"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4104); }
} while (false)
4104 .c_str())do { if (!(&firstChild != &lastChild)) { NS_DebugBreak
(NS_DEBUG_WARNING, fmt::format("The should be 2 or more children:\nchild={}\naChild2={}\n"
, ToString(firstChild), ToString(aChild2)) .c_str(), "&firstChild != &lastChild"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4104); }
} while (false)
;
4105 MOZ_ASSERT(&firstChild != &lastChild)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(&firstChild != &lastChild)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(&firstChild != &lastChild
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"&firstChild != &lastChild", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4105); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&firstChild != &lastChild"
")"); do { MOZ_CrashSequence(__null, 4105); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4106 if (&aChild2 == &lastChild) {
4107 return Some(aOffset1 == parentNodeChildCount - 1 ? 0 : -1);
4108 }
4109 Maybe<uint32_t> child2Index;
4110 if (aIndexCache) {
4111 const Maybe<int32_t> maybeGenContentChild2Index =
4112 aIndexCache->ComputeIndexOf<aKind>(&aParent, &aChild2);
4113 if (maybeGenContentChild2Index && *maybeGenContentChild2Index >= 0) {
4114 child2Index.emplace(static_cast<uint32_t>(*maybeGenContentChild2Index));
4115 }
4116#ifdef DEBUG1
4117 const Maybe<uint32_t> child2IndexDebug =
4118 aParent.ComputeIndexOf<aKind>(&aChild2);
4119 NS_WARNING_ASSERTION(do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString
(child2Index), ToString(aParent), ToString(aChild2)) .c_str()
, "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4125); } } while (false)
4120 child2Index == child2IndexDebug,do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString
(child2Index), ToString(aParent), ToString(aChild2)) .c_str()
, "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4125); } } while (false)
4121 fmt::format("aIndexCache causes wrong index: expected {}, but got "do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString
(child2Index), ToString(aParent), ToString(aChild2)) .c_str()
, "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4125); } } while (false)
4122 "{}\naParent={}\naChild1={}\n",do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString
(child2Index), ToString(aParent), ToString(aChild2)) .c_str()
, "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4125); } } while (false)
4123 ToString(child2IndexDebug), ToString(child2Index),do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString
(child2Index), ToString(aParent), ToString(aChild2)) .c_str()
, "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4125); } } while (false)
4124 ToString(aParent), ToString(aChild2))do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString
(child2Index), ToString(aParent), ToString(aChild2)) .c_str()
, "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4125); } } while (false)
4125 .c_str())do { if (!(child2Index == child2IndexDebug)) { NS_DebugBreak(
NS_DEBUG_WARNING, fmt::format("aIndexCache causes wrong index: expected {}, but got "
"{}\naParent={}\naChild1={}\n", ToString(child2IndexDebug), ToString
(child2Index), ToString(aParent), ToString(aChild2)) .c_str()
, "child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4125); } } while (false)
;
4126 MOZ_ASSERT(child2Index == child2IndexDebug)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(child2Index == child2IndexDebug)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(child2Index == child2IndexDebug
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"child2Index == child2IndexDebug", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4126); AnnotateMozCrashReason("MOZ_ASSERT" "(" "child2Index == child2IndexDebug"
")"); do { MOZ_CrashSequence(__null, 4126); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4127#endif // #ifdef DEBUG
4128 } else {
4129 child2Index = aParent.ComputeIndexOf<aKind>(&aChild2);
4130 }
4131 if (NS_WARN_IF(child2Index.isNothing())NS_warn_if_impl(child2Index.isNothing(), "child2Index.isNothing()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4131)
) {
4132 return Some(1);
4133 }
4134 return Some(aOffset1 == *child2Index ? 0
4135 : (aOffset1 < *child2Index ? -1 : 1));
4136}
4137
4138/* static */
4139template <TreeKind aKind, typename Dummy>
4140Maybe<int32_t> nsContentUtils::CompareChildNodeAndChildOffset(
4141 const nsINode& aParent, const nsIContent& aChild1, uint32_t aOffset2,
4142 NodeIndexCache* aIndexCache /* = nullptr */) {
4143 const Maybe<int32_t> comp = CompareChildOffsetAndChildNode<aKind>(
4144 aParent, aOffset2, aChild1, aIndexCache);
4145 if (comp.isNothing()) {
4146 return comp;
4147 }
4148 return Some(*comp * -1);
4149}
4150
4151/* static */
4152template <TreeKind aKind>
4153Maybe<int32_t> nsContentUtils::ComparePointsWithIndices(
4154 const nsINode* aParent1, uint32_t aOffset1, const nsINode* aParent2,
4155 uint32_t aOffset2, NodeIndexCache* aIndexCache,
4156 const nsINode* aAncestorLimiter) {
4157 MOZ_ASSERT(aParent1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParent1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aParent1))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aParent1", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4157); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent1" ")"
); do { MOZ_CrashSequence(__null, 4157); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4158 MOZ_ASSERT(aParent2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParent2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aParent2))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aParent2", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4158); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent2" ")"
); do { MOZ_CrashSequence(__null, 4158); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4159
4160 if (aParent1 == aParent2) {
4161 MOZ_ASSERT_IF(aAncestorLimiter, IsInclusiveDescendantForComparison<aKind>(do { if (aAncestorLimiter) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(IsInclusiveDescendantForComparison
<aKind>( *aParent1, *aAncestorLimiter))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInclusiveDescendantForComparison
<aKind>( *aParent1, *aAncestorLimiter)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsInclusiveDescendantForComparison<aKind>( *aParent1, *aAncestorLimiter)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4162); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInclusiveDescendantForComparison<aKind>( *aParent1, *aAncestorLimiter)"
")"); do { MOZ_CrashSequence(__null, 4162); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4162 *aParent1, *aAncestorLimiter))do { if (aAncestorLimiter) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(IsInclusiveDescendantForComparison
<aKind>( *aParent1, *aAncestorLimiter))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInclusiveDescendantForComparison
<aKind>( *aParent1, *aAncestorLimiter)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsInclusiveDescendantForComparison<aKind>( *aParent1, *aAncestorLimiter)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4162); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInclusiveDescendantForComparison<aKind>( *aParent1, *aAncestorLimiter)"
")"); do { MOZ_CrashSequence(__null, 4162); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4163 return Some(aOffset1 < aOffset2 ? -1 : (aOffset1 > aOffset2 ? 1 : 0));
4164 }
4165
4166 const CommonAncestors<GetParentNodeForComparison<aKind>> commonAncestors(
4167 *aParent1, *aParent2, aAncestorLimiter);
4168 const nsINode* const closestCommonAncestor =
4169 commonAncestors.GetClosestCommonAncestor();
4170 if (MOZ_UNLIKELY(!closestCommonAncestor)(__builtin_expect(!!(!closestCommonAncestor), 0))) {
4171 return Nothing();
4172 }
4173
4174 const nsIContent* closestCommonAncestorChild1 = nsIContent::FromNodeOrNull(
4175 commonAncestors.GetClosestCommonAncestorChild1());
4176 const nsIContent* closestCommonAncestorChild2 = nsIContent::FromNodeOrNull(
4177 commonAncestors.GetClosestCommonAncestorChild2());
4178 MOZ_ASSERT(closestCommonAncestorChild1 != closestCommonAncestorChild2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(closestCommonAncestorChild1 != closestCommonAncestorChild2
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(closestCommonAncestorChild1 != closestCommonAncestorChild2
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"closestCommonAncestorChild1 != closestCommonAncestorChild2",
"/root/firefox-clang/dom/base/nsContentUtils.cpp", 4178); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1 != closestCommonAncestorChild2"
")"); do { MOZ_CrashSequence(__null, 4178); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4179 MOZ_ASSERT_IF(!closestCommonAncestorChild1,do { if (!closestCommonAncestorChild1) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(!commonAncestors
.GetClosestCommonAncestorChild1())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!commonAncestors.GetClosestCommonAncestorChild1
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!commonAncestors.GetClosestCommonAncestorChild1()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4180); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 4180); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4180 !commonAncestors.GetClosestCommonAncestorChild1())do { if (!closestCommonAncestorChild1) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(!commonAncestors
.GetClosestCommonAncestorChild1())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!commonAncestors.GetClosestCommonAncestorChild1
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!commonAncestors.GetClosestCommonAncestorChild1()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4180); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 4180); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4181 MOZ_ASSERT_IF(!closestCommonAncestorChild2,do { if (!closestCommonAncestorChild2) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(!commonAncestors
.GetClosestCommonAncestorChild2())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!commonAncestors.GetClosestCommonAncestorChild2
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!commonAncestors.GetClosestCommonAncestorChild2()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4182); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 4182); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4182 !commonAncestors.GetClosestCommonAncestorChild2())do { if (!closestCommonAncestorChild2) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(!commonAncestors
.GetClosestCommonAncestorChild2())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!commonAncestors.GetClosestCommonAncestorChild2
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!commonAncestors.GetClosestCommonAncestorChild2()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4182); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 4182); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4183 commonAncestors
4184 .template WarnIfClosestCommonAncestorChildrenAreNotInChildList<aKind>();
4185 if (closestCommonAncestorChild1 && closestCommonAncestorChild2) {
4186 return CompareClosestCommonAncestorChildren<
4187 TreeKindToCompareChildren<aKind>()>(
4188 *closestCommonAncestor, closestCommonAncestorChild1,
4189 closestCommonAncestorChild2, aIndexCache);
4190 }
4191
4192 if (closestCommonAncestorChild2) {
4193 // aParent1 is the common ancestor.
4194 MOZ_ASSERT(GetParentNodeForComparison<aKind>::Get(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2
) == aParent1)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(GetParentNodeForComparison<aKind
>::Get( closestCommonAncestorChild2) == aParent1))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aParent1"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4195); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aParent1"
")"); do { MOZ_CrashSequence(__null, 4195); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4195 closestCommonAncestorChild2) == aParent1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2
) == aParent1)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(GetParentNodeForComparison<aKind
>::Get( closestCommonAncestorChild2) == aParent1))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aParent1"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4195); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aParent1"
")"); do { MOZ_CrashSequence(__null, 4195); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4196 if (aKind != TreeKind::DOM && ChildNodeIsInShadowDOMHostedByParent<aKind>(
4197 aParent1, closestCommonAncestorChild2)) {
4198 // Comparing a shadow host with its shadow root.
4199 // We consider:
4200 // [aParent1, 0] < closestCommonAncestorChild2 < [aParent1, 1]
4201 return aOffset1 > 0 ? Some(1) : Some(-1);
4202 }
4203
4204 // FIXME: bug 1946003 and bug 1946008.
4205 if (MOZ_UNLIKELY(closestCommonAncestorChild2->IsDocumentFragment())(__builtin_expect(!!(closestCommonAncestorChild2->IsDocumentFragment
()), 0))
) {
4206 // XXX Keep the odd traditional behavior for now.
4207 return Some(1);
4208 }
4209 // If the common ancestor is a shadow host, closestCommonAncestorChild2 must
4210 // be a child node of the host and we shouldn't handle the flattened tree.
4211 // Therefore, we can compare closestCommonAncestorChild2 and the child at
4212 // aBoundary1 can be compared within TreeKind::DOM tree.
4213 // NOTE: When aKind is TreeKind::FlatForSelection,
4214 // GetParentNodeForComparison returns the shadow host as the parent node
4215 // of a child node even if it's not assigned to any <slot>. Therefore, even
4216 // when we should return Nothing, we may return Some value for now.
4217 // Therefore, we need to relax this assertion for TreeKind::FlatForSelection
4218 // until fixing bug 2014622. And it's okay to compare the child nodes not a
4219 // part of flattened tree as in the DOM since anyway we return wrong value.
4220 MOZ_ASSERT_IF(do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor
->GetShadowRoot<aKind>()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(closestCommonAncestorChild2
->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild2->
GetParentNode() == closestCommonAncestor))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4223); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4223); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4221 aKind != TreeKind::FlatForSelection &&do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor
->GetShadowRoot<aKind>()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(closestCommonAncestorChild2
->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild2->
GetParentNode() == closestCommonAncestor))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4223); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4223); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4222 closestCommonAncestor->GetShadowRoot<aKind>(),do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor
->GetShadowRoot<aKind>()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(closestCommonAncestorChild2
->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild2->
GetParentNode() == closestCommonAncestor))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4223); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4223); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4223 closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor)do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor
->GetShadowRoot<aKind>()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(closestCommonAncestorChild2
->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild2->
GetParentNode() == closestCommonAncestor))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4223); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4223); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4224 const Maybe<int32_t> comp = nsContentUtils::CompareChildOffsetAndChildNode<
4225 TreeKindToCompareChildren<aKind>()>(*closestCommonAncestor, aOffset1,
4226 *closestCommonAncestorChild2,
4227 aIndexCache);
4228 if (NS_WARN_IF(comp.isNothing())NS_warn_if_impl(comp.isNothing(), "comp.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4228)
) {
4229 NS_ASSERTION(do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "nsContentUtils::CompareChildOffsetAndChildNode() must return Some "
"here. It should've already checked before we call it.", "comp.isSome()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4232); MOZ_PretendNoReturn
(); } } while (0)
4230 comp.isSome(),do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "nsContentUtils::CompareChildOffsetAndChildNode() must return Some "
"here. It should've already checked before we call it.", "comp.isSome()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4232); MOZ_PretendNoReturn
(); } } while (0)
4231 "nsContentUtils::CompareChildOffsetAndChildNode() must return Some "do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "nsContentUtils::CompareChildOffsetAndChildNode() must return Some "
"here. It should've already checked before we call it.", "comp.isSome()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4232); MOZ_PretendNoReturn
(); } } while (0)
4232 "here. It should've already checked before we call it.")do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "nsContentUtils::CompareChildOffsetAndChildNode() must return Some "
"here. It should've already checked before we call it.", "comp.isSome()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4232); MOZ_PretendNoReturn
(); } } while (0)
;
4233 // XXX Keep the odd traditional behavior for now.
4234 return Some(1);
4235 }
4236 // If the child of the closest common ancestor is at aOffset1 of aParent1,
4237 // it means that aOffset2 of aParent2 refers a descendant of the child.
4238 // So, aOffset2 of aParent2 refers a descendant of aOffset1 of aParent1.
4239 if (!*comp) {
4240 return Some(-1);
4241 }
4242 return comp;
4243 }
4244
4245 // aParent2 is the common ancestor.
4246 MOZ_ASSERT(closestCommonAncestorChild1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(closestCommonAncestorChild1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4246); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1" ")"); do { MOZ_CrashSequence
(__null, 4246); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4247 MOZ_ASSERT(GetParentNodeForComparison<aKind>::Get(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1
) == aParent2)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(GetParentNodeForComparison<aKind
>::Get( closestCommonAncestorChild1) == aParent2))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aParent2"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4248); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aParent2"
")"); do { MOZ_CrashSequence(__null, 4248); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4248 closestCommonAncestorChild1) == aParent2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1
) == aParent2)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(GetParentNodeForComparison<aKind
>::Get( closestCommonAncestorChild1) == aParent2))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aParent2"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4248); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aParent2"
")"); do { MOZ_CrashSequence(__null, 4248); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4249 if (aKind != TreeKind::DOM && ChildNodeIsInShadowDOMHostedByParent<aKind>(
4250 aParent2, closestCommonAncestorChild1)) {
4251 // Comparing a shadow host with its shadow root.
4252 // We consider: [aParent2, 0] < closestCommonAncestorChild1 < [aParent2, 1]
4253 return aOffset2 > 0 ? Some(-1) : Some(1);
4254 }
4255
4256 // FIXME: bug 1946003 and bug 1946008.
4257 if (MOZ_UNLIKELY(closestCommonAncestorChild1->IsDocumentFragment())(__builtin_expect(!!(closestCommonAncestorChild1->IsDocumentFragment
()), 0))
) {
4258 // XXX Keep the odd traditional behavior for now.
4259 return Some(-1);
4260 }
4261 // If the common ancestor is a shadow host, closestCommonAncestorChild1 must
4262 // be a child node of the host and we shouldn't handle the flattened tree.
4263 // Therefore, we can compare closestCommonAncestorChild1 and the child at
4264 // aBoundary2 can be compared within TreeKind::DOM tree.
4265 // NOTE: When aKind is TreeKind::FlatForSelection,
4266 // GetParentNodeForComparison returns the shadow host as the parent node
4267 // of a child node even if it's not assigned to any <slot>. Therefore, even
4268 // when we should return Nothing, we may return Some value for now.
4269 // Therefore, we need to relax this assertion for TreeKind::FlatForSelection
4270 // until fixing bug 2014622. And it's okay to compare the child nodes not a
4271 // part of flattened tree as in the DOM since anyway we return wrong value.
4272 MOZ_ASSERT_IF(do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor
->GetShadowRoot<aKind>()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(closestCommonAncestorChild1
->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1->
GetParentNode() == closestCommonAncestor))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4275); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4275); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4273 aKind != TreeKind::FlatForSelection &&do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor
->GetShadowRoot<aKind>()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(closestCommonAncestorChild1
->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1->
GetParentNode() == closestCommonAncestor))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4275); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4275); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4274 closestCommonAncestor->GetShadowRoot<aKind>(),do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor
->GetShadowRoot<aKind>()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(closestCommonAncestorChild1
->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1->
GetParentNode() == closestCommonAncestor))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4275); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4275); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4275 closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor)do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor
->GetShadowRoot<aKind>()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(closestCommonAncestorChild1
->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1->
GetParentNode() == closestCommonAncestor))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4275); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4275); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4276 const Maybe<int32_t> comp = nsContentUtils::CompareChildNodeAndChildOffset<
4277 TreeKindToCompareChildren<aKind>()>(*closestCommonAncestor,
4278 *closestCommonAncestorChild1,
4279 aOffset2, aIndexCache);
4280 if (NS_WARN_IF(comp.isNothing())NS_warn_if_impl(comp.isNothing(), "comp.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4280)
) {
4281 NS_ASSERTION(comp.isSome(),do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "nsContentUtils::CompareChildNodeAndChildOffset() must return "
"Some here. It should've already checked before we call it."
, "comp.isSome()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4283); MOZ_PretendNoReturn(); } } while (0)
4282 "nsContentUtils::CompareChildNodeAndChildOffset() must return "do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "nsContentUtils::CompareChildNodeAndChildOffset() must return "
"Some here. It should've already checked before we call it."
, "comp.isSome()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4283); MOZ_PretendNoReturn(); } } while (0)
4283 "Some here. It should've already checked before we call it.")do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "nsContentUtils::CompareChildNodeAndChildOffset() must return "
"Some here. It should've already checked before we call it."
, "comp.isSome()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4283); MOZ_PretendNoReturn(); } } while (0)
;
4284 // XXX Keep the odd traditional behavior for now.
4285 return Some(-1);
4286 }
4287 // If the child of the closet common ancestor is at aOffset2 of aParent2, it
4288 // means that aOffset1 of aParent1 refers a descendant of the child.
4289 // So, aOffset1 of aParent1 refers a descendant of aOffset2 of aParent2.
4290 if (!*comp) {
4291 return Some(1);
4292 }
4293 return comp;
4294}
4295
4296/* static */
4297BrowserParent* nsContentUtils::GetCommonBrowserParentAncestor(
4298 BrowserParent* aBrowserParent1, BrowserParent* aBrowserParent2) {
4299 MOZ_ASSERT(aBrowserParent1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBrowserParent1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aBrowserParent1))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aBrowserParent1"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4299); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aBrowserParent1" ")"); do { MOZ_CrashSequence
(__null, 4299); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4300 MOZ_ASSERT(aBrowserParent2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBrowserParent2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aBrowserParent2))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aBrowserParent2"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4300); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aBrowserParent2" ")"); do { MOZ_CrashSequence
(__null, 4300); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4301 return CommonAncestors<GetParentBrowserParent>(*aBrowserParent1,
4302 *aBrowserParent2)
4303 .GetClosestCommonAncestor();
4304}
4305
4306/* static */
4307Element* nsContentUtils::GetTargetElement(Document* aDocument,
4308 const nsAString& aAnchorName) {
4309 MOZ_ASSERT(aDocument)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDocument))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aDocument", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { MOZ_CrashSequence(__null, 4309); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4310
4311 if (aAnchorName.IsEmpty()) {
4312 return nullptr;
4313 }
4314 // 1. If there is an element in the document tree that has an ID equal to
4315 // fragment, then return the first such element in tree order.
4316 if (Element* el = aDocument->GetElementById(aAnchorName)) {
4317 return el;
4318 }
4319
4320 // 2. If there is an a element in the document tree that has a name
4321 // attribute whose value is equal to fragment, then return the first such
4322 // element in tree order.
4323 //
4324 // FIXME(emilio): Why the different code-paths for HTML and non-HTML docs?
4325 if (aDocument->IsHTMLDocument()) {
4326 RefPtr<NodeList> list = aDocument->GetElementsByName(aAnchorName);
4327 // Loop through the named nodes looking for the first anchor
4328 uint32_t length = list->Length();
4329 for (uint32_t i = 0; i < length; i++) {
4330 nsIContent* node = list->Item(i);
4331 if (node->IsHTMLElement(nsGkAtoms::a)) {
4332 return node->AsElement();
4333 }
4334 }
4335 } else {
4336 constexpr auto nameSpace = u"http://www.w3.org/1999/xhtml"_ns;
4337 // Get the list of anchor elements
4338 RefPtr<NodeList> list =
4339 aDocument->GetElementsByTagNameNS(nameSpace, u"a"_ns);
4340 // Loop through the anchors looking for the first one with the given name.
4341 for (uint32_t i = 0; true; i++) {
4342 nsIContent* node = list->Item(i);
4343 if (!node) { // End of list
4344 break;
4345 }
4346
4347 // Compare the name attribute
4348 if (node->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
4349 aAnchorName, eCaseMatters)) {
4350 return node->AsElement();
4351 }
4352 }
4353 }
4354
4355 // 3. Return null.
4356 return nullptr;
4357}
4358
4359/* static */
4360template <TreeKind aKind, typename PT1, typename RT1, typename PT2,
4361 typename RT2>
4362Maybe<int32_t> nsContentUtils::ComparePoints(
4363 const RangeBoundaryBase<PT1, RT1>& aBoundary1,
4364 const RangeBoundaryBase<PT2, RT2>& aBoundary2,
4365 NodeIndexCache* aIndexCache /* = nullptr */,
4366 const nsINode* aAncestorLimiter /* = nullptr */) {
4367 if (!aBoundary1.IsSet() || !aBoundary2.IsSet()) {
4368 return Nothing{};
4369 }
4370 MOZ_ASSERT(aBoundary1.GetTreeKind() == aBoundary2.GetTreeKind())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aBoundary1.GetTreeKind() == aBoundary2.GetTreeKind()
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aBoundary1.GetTreeKind() == aBoundary2.GetTreeKind()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aBoundary1.GetTreeKind() == aBoundary2.GetTreeKind()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBoundary1.GetTreeKind() == aBoundary2.GetTreeKind()"
")"); do { MOZ_CrashSequence(__null, 4370); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4371
4372 const auto kValidOrInvalidOffsets1 =
4373 RangeBoundaryBase<PT1, RT1>::OffsetFilter::kValidOrInvalidOffsets;
4374 const auto kValidOrInvalidOffsets2 =
4375 RangeBoundaryBase<PT2, RT2>::OffsetFilter::kValidOrInvalidOffsets;
4376
4377 // RangeBoundaryBase instances may be initialized only with a child node or an
4378 // offset in the container. If both instances have computed offset, we can
4379 // use ComparePointsWithIndices() which works with offsets.
4380 if (aBoundary1.HasOffset() && aBoundary2.HasOffset()) {
4381 return ComparePointsWithIndices<aKind>(
4382 aBoundary1.GetContainer(), *aBoundary1.Offset(kValidOrInvalidOffsets1),
4383 aBoundary2.GetContainer(), *aBoundary2.Offset(kValidOrInvalidOffsets2),
4384 aIndexCache, aAncestorLimiter);
4385 }
4386
4387 // Otherwise, i.e., at least one RangeBoundaryBase stores the child node.
4388 // In the most cases, RangeBoundaryBase has it, so, the worst scenario here
4389 // is, one of the boundaries comes from a StaticRange or is initialized with
4390 // offset and RangeBoundarySetBy::Offset. However, for making it faster in
4391 // the most cases, we should compare the child nodes without offsets if
4392 // possible.
4393
4394 // If we're comparing children in the same container, we don't need to compute
4395 // common ancestors. So, we can skip it and just compare the children.
4396 if (aBoundary1.GetContainer() == aBoundary2.GetContainer()) {
4397 MOZ_ASSERT_IF(aAncestorLimiter,do { if (aAncestorLimiter) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(IsInclusiveDescendantForComparison
<aKind>( *aBoundary1.GetContainer(), *aAncestorLimiter)
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsInclusiveDescendantForComparison<aKind>( *aBoundary1
.GetContainer(), *aAncestorLimiter)))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("IsInclusiveDescendantForComparison<aKind>( *aBoundary1.GetContainer(), *aAncestorLimiter)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4399); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInclusiveDescendantForComparison<aKind>( *aBoundary1.GetContainer(), *aAncestorLimiter)"
")"); do { MOZ_CrashSequence(__null, 4399); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4398 IsInclusiveDescendantForComparison<aKind>(do { if (aAncestorLimiter) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(IsInclusiveDescendantForComparison
<aKind>( *aBoundary1.GetContainer(), *aAncestorLimiter)
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsInclusiveDescendantForComparison<aKind>( *aBoundary1
.GetContainer(), *aAncestorLimiter)))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("IsInclusiveDescendantForComparison<aKind>( *aBoundary1.GetContainer(), *aAncestorLimiter)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4399); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInclusiveDescendantForComparison<aKind>( *aBoundary1.GetContainer(), *aAncestorLimiter)"
")"); do { MOZ_CrashSequence(__null, 4399); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4399 *aBoundary1.GetContainer(), *aAncestorLimiter))do { if (aAncestorLimiter) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(IsInclusiveDescendantForComparison
<aKind>( *aBoundary1.GetContainer(), *aAncestorLimiter)
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsInclusiveDescendantForComparison<aKind>( *aBoundary1
.GetContainer(), *aAncestorLimiter)))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("IsInclusiveDescendantForComparison<aKind>( *aBoundary1.GetContainer(), *aAncestorLimiter)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4399); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInclusiveDescendantForComparison<aKind>( *aBoundary1.GetContainer(), *aAncestorLimiter)"
")"); do { MOZ_CrashSequence(__null, 4399); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4400
4401 const nsIContent* const child1 = aBoundary1.GetChildAtOffset();
4402 MOZ_ASSERT_IF(child1, !child1->IsShadowRoot())do { if (child1) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(!child1->IsShadowRoot())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!child1->IsShadowRoot()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!child1->IsShadowRoot()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4402); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!child1->IsShadowRoot()" ")"); do { MOZ_CrashSequence
(__null, 4402); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
4403 const nsIContent* const child2 = aBoundary2.GetChildAtOffset();
4404 MOZ_ASSERT_IF(child2, !child2->IsShadowRoot())do { if (child2) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(!child2->IsShadowRoot())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!child2->IsShadowRoot()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!child2->IsShadowRoot()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4404); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!child2->IsShadowRoot()" ")"); do { MOZ_CrashSequence
(__null, 4404); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
4405 // But aBoundary1 and aBoundary2 may be not updated for the latest DOM.
4406 // In such case, we need to return Nothing.
4407 if (NS_WARN_IF(child1 && GetParentNodeForComparison<aKind>::Get(child1) !=NS_warn_if_impl(child1 && GetParentNodeForComparison<
aKind>::Get(child1) != aBoundary1.GetContainer(), "child1 && GetParentNodeForComparison<aKind>::Get(child1) != aBoundary1.GetContainer()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4408)
4408 aBoundary1.GetContainer())NS_warn_if_impl(child1 && GetParentNodeForComparison<
aKind>::Get(child1) != aBoundary1.GetContainer(), "child1 && GetParentNodeForComparison<aKind>::Get(child1) != aBoundary1.GetContainer()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4408)
||
4409 NS_WARN_IF(child2 && GetParentNodeForComparison<aKind>::Get(child2) !=NS_warn_if_impl(child2 && GetParentNodeForComparison<
aKind>::Get(child2) != aBoundary2.GetContainer(), "child2 && GetParentNodeForComparison<aKind>::Get(child2) != aBoundary2.GetContainer()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4410)
4410 aBoundary2.GetContainer())NS_warn_if_impl(child2 && GetParentNodeForComparison<
aKind>::Get(child2) != aBoundary2.GetContainer(), "child2 && GetParentNodeForComparison<aKind>::Get(child2) != aBoundary2.GetContainer()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4410)
) [[unlikely]] {
4411 return Nothing{};
4412 }
4413 return CompareClosestCommonAncestorChildren<
4414 TreeKindToCompareChildren<aKind>()>(*aBoundary1.GetContainer(), child1,
4415 child2, aIndexCache);
4416 }
4417
4418 // Otherwise, we need to compare the common ancestor children which is the
4419 // most distant different inclusive ancestors of the containers. So, the
4420 // following implementation is similar to ComparePointsWithIndices(), but we
4421 // don't have offset, so, we cannot use offset when we compare the boundaries
4422 // whose one is a descendant of the other.
4423 const CommonAncestors<GetParentNodeForComparison<aKind>> commonAncestors(
4424 *aBoundary1.GetContainer(), *aBoundary2.GetContainer(), aAncestorLimiter);
4425
4426 const nsINode* const closestCommonAncestor =
4427 commonAncestors.GetClosestCommonAncestor();
4428 if (MOZ_UNLIKELY(!closestCommonAncestor)(__builtin_expect(!!(!closestCommonAncestor), 0))) {
4429 return Nothing();
4430 }
4431 MOZ_ASSERT(commonAncestors.GetClosestCommonAncestor())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(commonAncestors.GetClosestCommonAncestor())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(commonAncestors.GetClosestCommonAncestor()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("commonAncestors.GetClosestCommonAncestor()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4431); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "commonAncestors.GetClosestCommonAncestor()"
")"); do { MOZ_CrashSequence(__null, 4431); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4432
4433 const nsIContent* closestCommonAncestorChild1 = nsIContent::FromNodeOrNull(
4434 commonAncestors.GetClosestCommonAncestorChild1());
4435 const nsIContent* closestCommonAncestorChild2 = nsIContent::FromNodeOrNull(
4436 commonAncestors.GetClosestCommonAncestorChild2());
4437 commonAncestors
4438 .template WarnIfClosestCommonAncestorChildrenAreNotInChildList<aKind>();
4439 MOZ_ASSERT(closestCommonAncestorChild1 != closestCommonAncestorChild2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(closestCommonAncestorChild1 != closestCommonAncestorChild2
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(closestCommonAncestorChild1 != closestCommonAncestorChild2
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"closestCommonAncestorChild1 != closestCommonAncestorChild2",
"/root/firefox-clang/dom/base/nsContentUtils.cpp", 4439); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1 != closestCommonAncestorChild2"
")"); do { MOZ_CrashSequence(__null, 4439); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4440 MOZ_ASSERT_IF(!closestCommonAncestorChild1,do { if (!closestCommonAncestorChild1) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(!commonAncestors
.GetClosestCommonAncestorChild1())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!commonAncestors.GetClosestCommonAncestorChild1
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!commonAncestors.GetClosestCommonAncestorChild1()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4441); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 4441); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4441 !commonAncestors.GetClosestCommonAncestorChild1())do { if (!closestCommonAncestorChild1) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(!commonAncestors
.GetClosestCommonAncestorChild1())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!commonAncestors.GetClosestCommonAncestorChild1
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!commonAncestors.GetClosestCommonAncestorChild1()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4441); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 4441); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4442 MOZ_ASSERT_IF(!closestCommonAncestorChild2,do { if (!closestCommonAncestorChild2) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(!commonAncestors
.GetClosestCommonAncestorChild2())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!commonAncestors.GetClosestCommonAncestorChild2
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!commonAncestors.GetClosestCommonAncestorChild2()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4443); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 4443); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4443 !commonAncestors.GetClosestCommonAncestorChild2())do { if (!closestCommonAncestorChild2) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(!commonAncestors
.GetClosestCommonAncestorChild2())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!commonAncestors.GetClosestCommonAncestorChild2
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!commonAncestors.GetClosestCommonAncestorChild2()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4443); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 4443); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4444 if (closestCommonAncestorChild1 && closestCommonAncestorChild2) {
4445 return CompareClosestCommonAncestorChildren<
4446 TreeKindToCompareChildren<aKind>()>(
4447 *closestCommonAncestor, closestCommonAncestorChild1,
4448 closestCommonAncestorChild2, aIndexCache);
4449 }
4450
4451 if (closestCommonAncestorChild2) {
4452 MOZ_ASSERT(GetParentNodeForComparison<aKind>::Get(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2
) == aBoundary1.GetContainer())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison<
aKind>::Get( closestCommonAncestorChild2) == aBoundary1.GetContainer
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aBoundary1.GetContainer()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4453); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aBoundary1.GetContainer()"
")"); do { MOZ_CrashSequence(__null, 4453); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4453 closestCommonAncestorChild2) == aBoundary1.GetContainer())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2
) == aBoundary1.GetContainer())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison<
aKind>::Get( closestCommonAncestorChild2) == aBoundary1.GetContainer
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aBoundary1.GetContainer()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4453); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aBoundary1.GetContainer()"
")"); do { MOZ_CrashSequence(__null, 4453); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4454 // FIXME: bug 1946003 and bug 1946008.
4455 if (MOZ_UNLIKELY(closestCommonAncestorChild2->IsDocumentFragment())(__builtin_expect(!!(closestCommonAncestorChild2->IsDocumentFragment
()), 0))
) {
4456 // XXX Keep the odd traditional behavior for now.
4457 return Some(1);
4458 }
4459 // If the common ancestor is a shadow host, closestCommonAncestorChild2 must
4460 // be a child node of the host and we shouldn't handle the flattened tree.
4461 // Therefore, we can compare closestCommonAncestorChild2 and the child at
4462 // aBoundary1 can be compared within TreeKind::DOM tree.
4463 // NOTE: When aKind is TreeKind::FlatForSelection,
4464 // GetParentNodeForComparison returns the shadow host as the parent node
4465 // of a child node even if it's not assigned to any <slot>. Therefore, even
4466 // when we should return Nothing, we may return Some value for now.
4467 // Therefore, we need to relax this assertion for TreeKind::FlatForSelection
4468 // until fixing bug 2014622. And it's okay to compare the child nodes not a
4469 // part of flattened tree as in the DOM since anyway we return wrong value.
4470 MOZ_ASSERT_IF(do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor
->GetShadowRoot<aKind>()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(closestCommonAncestorChild2
->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild2->
GetParentNode() == closestCommonAncestor))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4473); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4473); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4471 aKind != TreeKind::FlatForSelection &&do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor
->GetShadowRoot<aKind>()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(closestCommonAncestorChild2
->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild2->
GetParentNode() == closestCommonAncestor))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4473); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4473); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4472 closestCommonAncestor->GetShadowRoot<aKind>(),do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor
->GetShadowRoot<aKind>()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(closestCommonAncestorChild2
->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild2->
GetParentNode() == closestCommonAncestor))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4473); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4473); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4473 closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor)do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor
->GetShadowRoot<aKind>()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(closestCommonAncestorChild2
->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild2->
GetParentNode() == closestCommonAncestor))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4473); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4473); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4474 const Maybe<int32_t> comp = nsContentUtils::CompareChildNodes<
4475 TreeKindToCompareChildren<TreeKindToCompareChildren<aKind>()>()>(
4476 *closestCommonAncestor, aBoundary1.GetChildAtOffset(),
4477 closestCommonAncestorChild2, aIndexCache);
4478 NS_ASSERTION(comp.isSome(),do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "nsContentUtils::CompareChildNodes() must return Some here. "
"It should've already checked before we call it.", "comp.isSome()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4480); MOZ_PretendNoReturn
(); } } while (0)
4479 "nsContentUtils::CompareChildNodes() must return Some here. "do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "nsContentUtils::CompareChildNodes() must return Some here. "
"It should've already checked before we call it.", "comp.isSome()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4480); MOZ_PretendNoReturn
(); } } while (0)
4480 "It should've already checked before we call it.")do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "nsContentUtils::CompareChildNodes() must return Some here. "
"It should've already checked before we call it.", "comp.isSome()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4480); MOZ_PretendNoReturn
(); } } while (0)
;
4481 if (NS_WARN_IF(comp.isNothing())NS_warn_if_impl(comp.isNothing(), "comp.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4481)
) {
4482 // XXX Keep the odd traditional behavior for now.
4483 return Some(1);
4484 }
4485 // If the child of the closest common ancestor is at aBoundary1, it means
4486 // that aBoundary2 refers a descendant of the child. So, aBoundary2 refers a
4487 // descendant of aBoundary1.
4488 if (!*comp) {
4489 MOZ_ASSERT_IF(do { if (aKind != TreeKind::FlatForSelection) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren
<aKind>()>( closestCommonAncestorChild2) == *aBoundary1
.Offset(kValidOrInvalidOffsets1)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4494); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4494); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4490 aKind != TreeKind::FlatForSelection,do { if (aKind != TreeKind::FlatForSelection) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren
<aKind>()>( closestCommonAncestorChild2) == *aBoundary1
.Offset(kValidOrInvalidOffsets1)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4494); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4494); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4491 *closestCommonAncestordo { if (aKind != TreeKind::FlatForSelection) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren
<aKind>()>( closestCommonAncestorChild2) == *aBoundary1
.Offset(kValidOrInvalidOffsets1)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4494); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4494); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4492 ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>(do { if (aKind != TreeKind::FlatForSelection) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren
<aKind>()>( closestCommonAncestorChild2) == *aBoundary1
.Offset(kValidOrInvalidOffsets1)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4494); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4494); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4493 closestCommonAncestorChild2) ==do { if (aKind != TreeKind::FlatForSelection) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren
<aKind>()>( closestCommonAncestorChild2) == *aBoundary1
.Offset(kValidOrInvalidOffsets1)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4494); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4494); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4494 *aBoundary1.Offset(kValidOrInvalidOffsets1))do { if (aKind != TreeKind::FlatForSelection) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren
<aKind>()>( closestCommonAncestorChild2) == *aBoundary1
.Offset(kValidOrInvalidOffsets1)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4494); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4494); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4495 return Some(-1);
4496 }
4497 // ComputeIndexInParentNode() is the index in the regular child list, which
4498 // native anonymous content is not part of. CompareChildNodes already
4499 // ordered NAC via GetIndexInParent, so skip the regular-index sanity checks
4500 // for it.
4501 const DebugOnly<bool> child2IsNAC =
4502 closestCommonAncestorChild2->IsRootOfNativeAnonymousSubtree();
4503 MOZ_ASSERT_IF(do { if (!child2IsNAC && *comp < 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*aBoundary1.Offset
(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf
<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild2)))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4508); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
")"); do { MOZ_CrashSequence(__null, 4508); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4504 !child2IsNAC && *comp < 0 && aKind != TreeKind::FlatForSelection,do { if (!child2IsNAC && *comp < 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*aBoundary1.Offset
(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf
<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild2)))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4508); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
")"); do { MOZ_CrashSequence(__null, 4508); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4505 *aBoundary1.Offset(kValidOrInvalidOffsets1) <do { if (!child2IsNAC && *comp < 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*aBoundary1.Offset
(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf
<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild2)))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4508); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
")"); do { MOZ_CrashSequence(__null, 4508); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4506 *closestCommonAncestordo { if (!child2IsNAC && *comp < 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*aBoundary1.Offset
(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf
<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild2)))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4508); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
")"); do { MOZ_CrashSequence(__null, 4508); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4507 ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>(do { if (!child2IsNAC && *comp < 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*aBoundary1.Offset
(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf
<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild2)))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4508); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
")"); do { MOZ_CrashSequence(__null, 4508); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4508 closestCommonAncestorChild2))do { if (!child2IsNAC && *comp < 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*aBoundary1.Offset
(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf
<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild2)))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4508); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
")"); do { MOZ_CrashSequence(__null, 4508); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4509 MOZ_ASSERT_IF(do { if (!child2IsNAC && *comp > 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild2) < *aBoundary1.Offset(
kValidOrInvalidOffsets1))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor ->
ComputeIndexOf<TreeKindToCompareChildren<aKind>()>
( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4514); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4514); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4510 !child2IsNAC && *comp > 0 && aKind != TreeKind::FlatForSelection,do { if (!child2IsNAC && *comp > 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild2) < *aBoundary1.Offset(
kValidOrInvalidOffsets1))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor ->
ComputeIndexOf<TreeKindToCompareChildren<aKind>()>
( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4514); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4514); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4511 *closestCommonAncestordo { if (!child2IsNAC && *comp > 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild2) < *aBoundary1.Offset(
kValidOrInvalidOffsets1))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor ->
ComputeIndexOf<TreeKindToCompareChildren<aKind>()>
( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4514); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4514); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4512 ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>(do { if (!child2IsNAC && *comp > 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild2) < *aBoundary1.Offset(
kValidOrInvalidOffsets1))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor ->
ComputeIndexOf<TreeKindToCompareChildren<aKind>()>
( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4514); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4514); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4513 closestCommonAncestorChild2) <do { if (!child2IsNAC && *comp > 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild2) < *aBoundary1.Offset(
kValidOrInvalidOffsets1))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor ->
ComputeIndexOf<TreeKindToCompareChildren<aKind>()>
( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4514); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4514); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4514 *aBoundary1.Offset(kValidOrInvalidOffsets1))do { if (!child2IsNAC && *comp > 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild2) < *aBoundary1.Offset(
kValidOrInvalidOffsets1))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor ->
ComputeIndexOf<TreeKindToCompareChildren<aKind>()>
( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4514); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4514); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4515 return comp;
4516 }
4517
4518 MOZ_ASSERT(closestCommonAncestorChild1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(closestCommonAncestorChild1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4518); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1" ")"); do { MOZ_CrashSequence
(__null, 4518); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4519 MOZ_ASSERT(GetParentNodeForComparison<aKind>::Get(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1
) == aBoundary2.GetContainer())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison<
aKind>::Get( closestCommonAncestorChild1) == aBoundary2.GetContainer
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aBoundary2.GetContainer()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4520); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aBoundary2.GetContainer()"
")"); do { MOZ_CrashSequence(__null, 4520); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4520 closestCommonAncestorChild1) == aBoundary2.GetContainer())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1
) == aBoundary2.GetContainer())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(GetParentNodeForComparison<
aKind>::Get( closestCommonAncestorChild1) == aBoundary2.GetContainer
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aBoundary2.GetContainer()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4520); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aBoundary2.GetContainer()"
")"); do { MOZ_CrashSequence(__null, 4520); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4521 // FIXME: bug 1946003 and bug 1946008.
4522 if (MOZ_UNLIKELY(closestCommonAncestorChild1->IsDocumentFragment())(__builtin_expect(!!(closestCommonAncestorChild1->IsDocumentFragment
()), 0))
) {
4523 // XXX Keep the odd traditional behavior for now.
4524 return Some(-1);
4525 }
4526 // If the common ancestor is a shadow host, closestCommonAncestorChild1 must
4527 // be a child node of the host and we shouldn't handle the flattened tree.
4528 // Therefore, we can compare closestCommonAncestorChild1 and the child at
4529 // aBoundary2 can be compared within TreeKind::DOM tree.
4530 // NOTE: When aKind is TreeKind::FlatForSelection,
4531 // GetParentNodeForComparison returns the shadow host as the parent node
4532 // of a child node even if it's not assigned to any <slot>. Therefore, even
4533 // when we should return Nothing, we may return Some value for now.
4534 // Therefore, we need to relax this assertion for TreeKind::FlatForSelection
4535 // until fixing bug 2014622. And it's okay to compare the child nodes not a
4536 // part of flattened tree as in the DOM since anyway we return wrong value.
4537 MOZ_ASSERT_IF(do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor
->GetShadowRoot<aKind>()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(closestCommonAncestorChild1
->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1->
GetParentNode() == closestCommonAncestor))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4540); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4540); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4538 aKind != TreeKind::FlatForSelection &&do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor
->GetShadowRoot<aKind>()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(closestCommonAncestorChild1
->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1->
GetParentNode() == closestCommonAncestor))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4540); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4540); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4539 closestCommonAncestor->GetShadowRoot<aKind>(),do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor
->GetShadowRoot<aKind>()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(closestCommonAncestorChild1
->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1->
GetParentNode() == closestCommonAncestor))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4540); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4540); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4540 closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor)do { if (aKind != TreeKind::FlatForSelection && closestCommonAncestor
->GetShadowRoot<aKind>()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(closestCommonAncestorChild1
->GetParentNode() == closestCommonAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(closestCommonAncestorChild1->
GetParentNode() == closestCommonAncestor))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4540); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4540); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4541 const Maybe<int32_t> comp =
4542 nsContentUtils::CompareChildNodes<TreeKindToCompareChildren<aKind>()>(
4543 *closestCommonAncestor, closestCommonAncestorChild1,
4544 aBoundary2.GetChildAtOffset(), aIndexCache);
4545 NS_ASSERTION(comp.isSome(),do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "nsContentUtils::CompareChildNodes() must return Some here. "
"It should've already checked before we call it.", "comp.isSome()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4547); MOZ_PretendNoReturn
(); } } while (0)
4546 "nsContentUtils::CompareChildNodes() must return Some here. "do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "nsContentUtils::CompareChildNodes() must return Some here. "
"It should've already checked before we call it.", "comp.isSome()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4547); MOZ_PretendNoReturn
(); } } while (0)
4547 "It should've already checked before we call it.")do { if (!(comp.isSome())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "nsContentUtils::CompareChildNodes() must return Some here. "
"It should've already checked before we call it.", "comp.isSome()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4547); MOZ_PretendNoReturn
(); } } while (0)
;
4548 if (NS_WARN_IF(comp.isNothing())NS_warn_if_impl(comp.isNothing(), "comp.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4548)
) {
4549 // XXX Keep the odd traditional behavior for now.
4550 return Some(-1);
4551 }
4552 // If the child of the closet common ancestor is at aBoundary2, it means that
4553 // aBoundary1 refers a descendant of the child. So, aBoundary1 refers a
4554 // descendant of aBoundary2.
4555 if (!*comp) {
4556 MOZ_ASSERT_IF(aKind != TreeKind::FlatForSelection,do { if (aKind != TreeKind::FlatForSelection) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren
<aKind>()>( closestCommonAncestorChild1) == *aBoundary2
.Offset(kValidOrInvalidOffsets2)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4560); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4560); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4557 *closestCommonAncestordo { if (aKind != TreeKind::FlatForSelection) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren
<aKind>()>( closestCommonAncestorChild1) == *aBoundary2
.Offset(kValidOrInvalidOffsets2)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4560); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4560); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4558 ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>(do { if (aKind != TreeKind::FlatForSelection) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren
<aKind>()>( closestCommonAncestorChild1) == *aBoundary2
.Offset(kValidOrInvalidOffsets2)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4560); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4560); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4559 closestCommonAncestorChild1) ==do { if (aKind != TreeKind::FlatForSelection) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren
<aKind>()>( closestCommonAncestorChild1) == *aBoundary2
.Offset(kValidOrInvalidOffsets2)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4560); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4560); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4560 *aBoundary2.Offset(kValidOrInvalidOffsets2))do { if (aKind != TreeKind::FlatForSelection) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren
<aKind>()>( closestCommonAncestorChild1) == *aBoundary2
.Offset(kValidOrInvalidOffsets2)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4560); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4560); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4561 return Some(1);
4562 }
4563 // ComputeIndexInParentNode() is the index in the regular child list, which
4564 // native anonymous content is not part of. CompareChildNodes already ordered
4565 // NAC via GetIndexInParent, so skip the regular-index sanity checks for it.
4566 const DebugOnly<bool> child1IsNAC =
4567 closestCommonAncestorChild1->IsRootOfNativeAnonymousSubtree();
4568 MOZ_ASSERT_IF(do { if (!child1IsNAC && *comp < 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild1) < *aBoundary2.Offset(
kValidOrInvalidOffsets2))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor ->
ComputeIndexOf<TreeKindToCompareChildren<aKind>()>
( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4573); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4573); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4569 !child1IsNAC && *comp < 0 && aKind != TreeKind::FlatForSelection,do { if (!child1IsNAC && *comp < 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild1) < *aBoundary2.Offset(
kValidOrInvalidOffsets2))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor ->
ComputeIndexOf<TreeKindToCompareChildren<aKind>()>
( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4573); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4573); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4570 *closestCommonAncestordo { if (!child1IsNAC && *comp < 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild1) < *aBoundary2.Offset(
kValidOrInvalidOffsets2))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor ->
ComputeIndexOf<TreeKindToCompareChildren<aKind>()>
( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4573); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4573); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4571 ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>(do { if (!child1IsNAC && *comp < 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild1) < *aBoundary2.Offset(
kValidOrInvalidOffsets2))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor ->
ComputeIndexOf<TreeKindToCompareChildren<aKind>()>
( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4573); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4573); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4572 closestCommonAncestorChild1) <do { if (!child1IsNAC && *comp < 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild1) < *aBoundary2.Offset(
kValidOrInvalidOffsets2))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor ->
ComputeIndexOf<TreeKindToCompareChildren<aKind>()>
( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4573); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4573); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4573 *aBoundary2.Offset(kValidOrInvalidOffsets2))do { if (!child1IsNAC && *comp < 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild1) < *aBoundary2.Offset(
kValidOrInvalidOffsets2))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(*closestCommonAncestor ->
ComputeIndexOf<TreeKindToCompareChildren<aKind>()>
( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4573); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4573); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4574 MOZ_ASSERT_IF(do { if (!child1IsNAC && *comp > 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*aBoundary2.Offset
(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf
<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild1)))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4579); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
")"); do { MOZ_CrashSequence(__null, 4579); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4575 !child1IsNAC && *comp > 0 && aKind != TreeKind::FlatForSelection,do { if (!child1IsNAC && *comp > 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*aBoundary2.Offset
(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf
<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild1)))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4579); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
")"); do { MOZ_CrashSequence(__null, 4579); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4576 *aBoundary2.Offset(kValidOrInvalidOffsets2) <do { if (!child1IsNAC && *comp > 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*aBoundary2.Offset
(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf
<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild1)))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4579); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
")"); do { MOZ_CrashSequence(__null, 4579); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4577 *closestCommonAncestordo { if (!child1IsNAC && *comp > 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*aBoundary2.Offset
(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf
<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild1)))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4579); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
")"); do { MOZ_CrashSequence(__null, 4579); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4578 ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>(do { if (!child1IsNAC && *comp > 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*aBoundary2.Offset
(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf
<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild1)))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4579); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
")"); do { MOZ_CrashSequence(__null, 4579); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4579 closestCommonAncestorChild1))do { if (!child1IsNAC && *comp > 0 && aKind
!= TreeKind::FlatForSelection) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(*aBoundary2.Offset
(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf
<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor
->ComputeIndexOf<TreeKindToCompareChildren<aKind>
()>( closestCommonAncestorChild1)))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4579); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
")"); do { MOZ_CrashSequence(__null, 4579); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4580 return comp;
4581}
4582
4583inline bool IsCharInSet(const char* aSet, const char16_t aChar) {
4584 char16_t ch;
4585 while ((ch = *aSet)) {
4586 if (aChar == char16_t(ch)) {
4587 return true;
4588 }
4589 ++aSet;
4590 }
4591 return false;
4592}
4593
4594/**
4595 * This method strips leading/trailing chars, in given set, from string.
4596 */
4597
4598// static
4599const nsDependentSubstring nsContentUtils::TrimCharsInSet(
4600 const char* aSet, const nsAString& aValue) {
4601 nsAString::const_iterator valueCurrent, valueEnd;
4602
4603 aValue.BeginReading(valueCurrent);
4604 aValue.EndReading(valueEnd);
4605
4606 // Skip characters in the beginning
4607 while (valueCurrent != valueEnd) {
4608 if (!IsCharInSet(aSet, *valueCurrent)) {
4609 break;
4610 }
4611 ++valueCurrent;
4612 }
4613
4614 if (valueCurrent != valueEnd) {
4615 for (;;) {
4616 --valueEnd;
4617 if (!IsCharInSet(aSet, *valueEnd)) {
4618 break;
4619 }
4620 }
4621 ++valueEnd; // Step beyond the last character we want in the value.
4622 }
4623
4624 // valueEnd should point to the char after the last to copy
4625 return Substring(valueCurrent, valueEnd);
4626}
4627
4628/**
4629 * This method strips leading and trailing whitespace from a string.
4630 */
4631
4632// static
4633template <bool IsWhitespace(char16_t)>
4634const nsDependentSubstring nsContentUtils::TrimWhitespace(const nsAString& aStr,
4635 bool aTrimTrailing) {
4636 nsAString::const_iterator start, end;
4637
4638 aStr.BeginReading(start);
4639 aStr.EndReading(end);
4640
4641 // Skip whitespace characters in the beginning
4642 while (start != end && IsWhitespace(*start)) {
4643 ++start;
4644 }
4645
4646 if (aTrimTrailing) {
4647 // Skip whitespace characters in the end.
4648 while (end != start) {
4649 --end;
4650
4651 if (!IsWhitespace(*end)) {
4652 // Step back to the last non-whitespace character.
4653 ++end;
4654
4655 break;
4656 }
4657 }
4658 }
4659
4660 // Return a substring for the string w/o leading and/or trailing
4661 // whitespace
4662
4663 return Substring(start, end);
4664}
4665
4666// Declaring the templates we are going to use avoid linking issues without
4667// inlining the method. Considering there is not so much spaces checking
4668// methods we can consider this to be better than inlining.
4669template const nsDependentSubstring
4670nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(const nsAString&, bool);
4671template const nsDependentSubstring nsContentUtils::TrimWhitespace<
4672 nsContentUtils::IsHTMLWhitespace>(const nsAString&, bool);
4673template const nsDependentSubstring nsContentUtils::TrimWhitespace<
4674 nsContentUtils::IsHTMLWhitespaceOrNBSP>(const nsAString&, bool);
4675
4676static inline void KeyAppendSep(nsACString& aKey) {
4677 if (!aKey.IsEmpty()) {
4678 aKey.Append('>');
4679 }
4680}
4681
4682static inline void KeyAppendString(const nsAString& aString, nsACString& aKey) {
4683 KeyAppendSep(aKey);
4684
4685 // Could escape separator here if collisions happen. > is not a legal char
4686 // for a name or type attribute, so we should be safe avoiding that extra
4687 // work.
4688
4689 AppendUTF16toUTF8(aString, aKey);
4690}
4691
4692static inline void KeyAppendString(const nsACString& aString,
4693 nsACString& aKey) {
4694 KeyAppendSep(aKey);
4695
4696 // Could escape separator here if collisions happen. > is not a legal char
4697 // for a name or type attribute, so we should be safe avoiding that extra
4698 // work.
4699
4700 aKey.Append(aString);
4701}
4702
4703static inline void KeyAppendInt(int32_t aInt, nsACString& aKey) {
4704 KeyAppendSep(aKey);
4705
4706 aKey.AppendInt(aInt);
4707}
4708
4709static inline bool IsAutocompleteOff(const nsIContent* aContent) {
4710 return aContent->IsElement() &&
4711 aContent->AsElement()->AttrValueIs(kNameSpaceID_None,
4712 nsGkAtoms::autocomplete, u"off"_ns,
4713 eIgnoreCase);
4714}
4715
4716/*static*/
4717void nsContentUtils::GenerateStateKey(nsIContent* aContent, Document* aDocument,
4718 nsACString& aKey) {
4719 MOZ_ASSERT(aContent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aContent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aContent", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { MOZ_CrashSequence(__null, 4719); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4720
4721 aKey.Truncate();
4722
4723 uint32_t partID = aDocument ? aDocument->GetPartID() : 0;
4724
4725 // Don't capture state for anonymous content
4726 if (aContent->IsInNativeAnonymousSubtree()) {
4727 return;
4728 }
4729
4730 if (IsAutocompleteOff(aContent)) {
4731 return;
4732 }
4733
4734 RefPtr<Document> doc = aContent->GetUncomposedDoc();
4735
4736 KeyAppendInt(partID, aKey); // first append a partID
4737 bool generatedUniqueKey = false;
4738
4739 if (doc && doc->IsHTMLOrXHTML()) {
4740 nsHTMLDocument* htmlDoc = doc->AsHTMLDocument();
4741
4742 // If we have a form control and can calculate form information, use that
4743 // as the key - it is more reliable than just recording position in the
4744 // DOM.
4745 // XXXbz Is it, really? We have bugs on this, I think...
4746 // Important to have a unique key, and tag/type/name may not be.
4747 //
4748 // The format of the key depends on whether the control has a form,
4749 // and whether the element was parser inserted:
4750 //
4751 // [Has Form, Parser Inserted]:
4752 // fp>type>FormNum>IndOfControlInForm>FormName>name
4753 //
4754 // [No Form, Parser Inserted]:
4755 // dp>type>ControlNum>name
4756 //
4757 // [Has Form, Not Parser Inserted]:
4758 // fn>type>IndOfFormInDoc>IndOfControlInForm>FormName>name
4759 //
4760 // [No Form, Not Parser Inserted]:
4761 // dn>type>IndOfControlInDoc>name
4762 //
4763 // XXX We don't need to use index if name is there
4764 // XXXbz We don't? Why not? I don't follow.
4765 //
4766 if (const auto* control = nsIFormControl::FromNode(aContent)) {
4767 // Get the control number if this was a parser inserted element from the
4768 // network.
4769 int32_t controlNumber =
4770 control->GetParserInsertedControlNumberForStateKey();
4771 bool parserInserted = controlNumber != -1;
4772
4773 RefPtr<ContentList> htmlForms;
4774 RefPtr<ContentList> htmlFormControls;
4775 if (!parserInserted) {
4776 // Getting these lists is expensive, as we need to keep them up to date
4777 // as the document loads, so we avoid it if we don't need them.
4778 htmlDoc->GetFormsAndFormControls(getter_AddRefs(htmlForms),
4779 getter_AddRefs(htmlFormControls));
4780 }
4781
4782 // Append the control type
4783 KeyAppendInt(int32_t(control->ControlType()), aKey);
4784
4785 // If in a form, add form name / index of form / index in form
4786 HTMLFormElement* formElement = control->GetFormInternal();
4787 if (formElement) {
4788 if (IsAutocompleteOff(formElement)) {
4789 aKey.Truncate();
4790 return;
4791 }
4792
4793 // Append the form number, if this is a parser inserted control, or
4794 // the index of the form in the document otherwise.
4795 bool appendedForm = false;
4796 if (parserInserted) {
4797 MOZ_ASSERT(formElement->GetFormNumberForStateKey() != -1,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(formElement->GetFormNumberForStateKey() != -1)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(formElement->GetFormNumberForStateKey() != -1))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("formElement->GetFormNumberForStateKey() != -1"
" (" "when generating a state key for a parser inserted form "
"control we should have a parser inserted <form> element"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4799
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "formElement->GetFormNumberForStateKey() != -1"
") (" "when generating a state key for a parser inserted form "
"control we should have a parser inserted <form> element"
")"); do { MOZ_CrashSequence(__null, 4799); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4798 "when generating a state key for a parser inserted form "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(formElement->GetFormNumberForStateKey() != -1)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(formElement->GetFormNumberForStateKey() != -1))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("formElement->GetFormNumberForStateKey() != -1"
" (" "when generating a state key for a parser inserted form "
"control we should have a parser inserted <form> element"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4799
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "formElement->GetFormNumberForStateKey() != -1"
") (" "when generating a state key for a parser inserted form "
"control we should have a parser inserted <form> element"
")"); do { MOZ_CrashSequence(__null, 4799); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4799 "control we should have a parser inserted <form> element")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(formElement->GetFormNumberForStateKey() != -1)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(formElement->GetFormNumberForStateKey() != -1))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("formElement->GetFormNumberForStateKey() != -1"
" (" "when generating a state key for a parser inserted form "
"control we should have a parser inserted <form> element"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4799
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "formElement->GetFormNumberForStateKey() != -1"
") (" "when generating a state key for a parser inserted form "
"control we should have a parser inserted <form> element"
")"); do { MOZ_CrashSequence(__null, 4799); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4800 KeyAppendString("fp"_ns, aKey);
4801 KeyAppendInt(formElement->GetFormNumberForStateKey(), aKey);
4802 appendedForm = true;
4803 } else {
4804 KeyAppendString("fn"_ns, aKey);
4805 int32_t index = htmlForms->IndexOf(formElement);
4806 if (index <= -1) {
4807 //
4808 // XXX HACK this uses some state that was dumped into the document
4809 // specifically to fix bug 138892. What we are trying to do is
4810 // *guess* which form this control's state is found in, with the
4811 // highly likely guess that the highest form parsed so far is the
4812 // one. This code should not be on trunk, only branch.
4813 //
4814 index = htmlDoc->GetNumFormsSynchronous() - 1;
4815 }
4816 if (index > -1) {
4817 KeyAppendInt(index, aKey);
4818 appendedForm = true;
4819 }
4820 }
4821
4822 if (appendedForm) {
4823 // Append the index of the control in the form
4824 int32_t index = formElement->IndexOfContent(aContent);
4825
4826 if (index > -1) {
4827 KeyAppendInt(index, aKey);
4828 generatedUniqueKey = true;
4829 }
4830 }
4831
4832 // Append the form name
4833 nsAutoString formName;
4834 formElement->GetAttr(nsGkAtoms::name, formName);
4835 KeyAppendString(formName, aKey);
4836 } else {
4837 // Not in a form. Append the control number, if this is a parser
4838 // inserted control, or the index of the control in the document
4839 // otherwise.
4840 if (parserInserted) {
4841 KeyAppendString("dp"_ns, aKey);
4842 KeyAppendInt(control->GetParserInsertedControlNumberForStateKey(),
4843 aKey);
4844 generatedUniqueKey = true;
4845 } else {
4846 KeyAppendString("dn"_ns, aKey);
4847 int32_t index = htmlFormControls->IndexOf(aContent);
4848 if (index > -1) {
4849 KeyAppendInt(index, aKey);
4850 generatedUniqueKey = true;
4851 }
4852 }
4853
4854 // Append the control name
4855 nsAutoString name;
4856 aContent->AsElement()->GetAttr(nsGkAtoms::name, name);
4857 KeyAppendString(name, aKey);
4858 }
4859 }
4860 }
4861
4862 if (!generatedUniqueKey) {
4863 // Either we didn't have a form control or we aren't in an HTML document so
4864 // we can't figure out form info. Append the tag name if it's an element
4865 // to avoid restoring state for one type of element on another type.
4866 if (aContent->IsElement()) {
4867 KeyAppendString(nsDependentAtomString(aContent->NodeInfo()->NameAtom()),
4868 aKey);
4869 } else {
4870 // Append a character that is not "d" or "f" to disambiguate from
4871 // the case when we were a form control in an HTML document.
4872 KeyAppendString("o"_ns, aKey);
4873 }
4874
4875 // Now start at aContent and append the indices of it and all its ancestors
4876 // in their containers. That should at least pin down its position in the
4877 // DOM...
4878 nsINode* parent = aContent->GetParentNode();
4879 nsINode* content = aContent;
4880 while (parent) {
4881 if (content->IsShadowRoot()) {
4882 KeyAppendString("s"_ns, aKey);
4883 } else {
4884 KeyAppendInt(parent->ComputeIndexOf_Deprecated(content), aKey);
4885 }
4886 content = parent;
4887 parent = content->GetParentOrShadowHostNode();
4888 }
4889 }
4890}
4891
4892// static
4893nsIPrincipal* nsContentUtils::SubjectPrincipal(JSContext* aCx) {
4894 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4894); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 4894); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4895
4896 // As opposed to SubjectPrincipal(), we do in fact assume that
4897 // we're in a realm here; anyone who calls this function in
4898 // situations where that's not the case is doing it wrong.
4899 JS::Realm* realm = js::GetContextRealm(aCx);
4900 MOZ_ASSERT(realm)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(realm)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(realm))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("realm", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4900); AnnotateMozCrashReason("MOZ_ASSERT" "(" "realm" ")")
; do { MOZ_CrashSequence(__null, 4900); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4901
4902 JSPrincipals* principals = JS::GetRealmPrincipals(realm);
4903 return nsJSPrincipals::get(principals);
4904}
4905
4906// static
4907nsIPrincipal* nsContentUtils::SubjectPrincipal() {
4908 MOZ_ASSERT(IsInitialized())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsInitialized())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInitialized()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("IsInitialized()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4908); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInitialized()" ")"); do { MOZ_CrashSequence
(__null, 4908); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4909 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4909); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 4909); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4910 JSContext* cx = GetCurrentJSContext();
4911 if (!cx) {
4912 MOZ_CRASH(do { do { } while (false); MOZ_ReportCrash("" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4914); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden" ")"); do { MOZ_CrashSequence(__null, 4914); __attribute__
((nomerge)) ::abort(); } while (false); } while (false)
4913 "Accessing the Subject Principal without an AutoJSAPI on the stack is "do { do { } while (false); MOZ_ReportCrash("" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4914); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden" ")"); do { MOZ_CrashSequence(__null, 4914); __attribute__
((nomerge)) ::abort(); } while (false); } while (false)
4914 "forbidden")do { do { } while (false); MOZ_ReportCrash("" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4914); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden" ")"); do { MOZ_CrashSequence(__null, 4914); __attribute__
((nomerge)) ::abort(); } while (false); } while (false)
;
4915 }
4916
4917 JS::Realm* realm = js::GetContextRealm(cx);
4918
4919 // When an AutoJSAPI is instantiated, we are in a null realm until the
4920 // first JSAutoRealm, which is kind of a purgatory as far as permissions
4921 // go. It would be nice to just hard-abort if somebody does a security check
4922 // in this purgatory zone, but that would be too fragile, since it could be
4923 // triggered by random IsCallerChrome() checks 20-levels deep.
4924 //
4925 // So we want to return _something_ here - and definitely not the System
4926 // Principal, since that would make an AutoJSAPI a very dangerous thing to
4927 // instantiate.
4928 //
4929 // The natural thing to return is a null principal. Ideally, we'd return a
4930 // different null principal each time, to avoid any unexpected interactions
4931 // when the principal accidentally gets inherited somewhere. But
4932 // SubjectPrincipal doesn't return strong references, so there's no way to
4933 // sanely manage the lifetime of multiple null principals.
4934 //
4935 // So we use a singleton null principal. To avoid it being accidentally
4936 // inherited and becoming a "real" subject or object principal, we do a
4937 // release-mode assert during realm creation against using this principal on
4938 // an actual global.
4939 if (!realm) {
4940 return sNullSubjectPrincipal;
4941 }
4942
4943 return SubjectPrincipal(cx);
4944}
4945
4946// static
4947nsIPrincipal* nsContentUtils::ObjectPrincipal(JSObject* aObj) {
4948#ifdef DEBUG1
4949 JS::AssertObjectBelongsToCurrentThread(aObj);
4950#endif
4951
4952 MOZ_DIAGNOSTIC_ASSERT(!js::IsCrossCompartmentWrapper(aObj))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!js::IsCrossCompartmentWrapper(aObj))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!js::IsCrossCompartmentWrapper
(aObj)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!js::IsCrossCompartmentWrapper(aObj)", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4952); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!js::IsCrossCompartmentWrapper(aObj)"
")"); do { MOZ_CrashSequence(__null, 4952); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4953
4954 JS::Realm* realm = js::GetNonCCWObjectRealm(aObj);
4955 JSPrincipals* principals = JS::GetRealmPrincipals(realm);
4956 return nsJSPrincipals::get(principals);
4957}
4958
4959// static
4960nsresult nsContentUtils::NewURIWithDocumentCharset(nsIURI** aResult,
4961 const nsAString& aSpec,
4962 Document* aDocument,
4963 nsIURI* aBaseURI) {
4964 if (aDocument) {
4965 return NS_NewURI(aResult, aSpec, aDocument->GetDocumentCharacterSet(),
4966 aBaseURI);
4967 }
4968 return NS_NewURI(aResult, aSpec, nullptr, aBaseURI);
4969}
4970
4971// static
4972bool nsContentUtils::ContainsChar(nsAtom* aAtom, char aChar) {
4973 const uint32_t len = aAtom->GetLength();
4974 if (!len) {
4975 return false;
4976 }
4977 const char16_t* name = aAtom->GetUTF16String();
4978 uint32_t i = 0;
4979 while (i < len) {
4980 if (name[i] == aChar) {
4981 return true;
4982 }
4983 i++;
4984 }
4985 return false;
4986}
4987
4988// static
4989bool nsContentUtils::IsNameWithDash(nsAtom* aName) {
4990 // A valid custom element name is a sequence of characters name which
4991 // must match the PotentialCustomElementName production:
4992 // PotentialCustomElementName ::= [a-z] (PCENChar)* '-' (PCENChar)*
4993 const char16_t* name = aName->GetUTF16String();
4994 uint32_t len = aName->GetLength();
4995 bool hasDash = false;
4996
4997 // A string name is a valid custom element name if all of the following are
4998 // true:
4999
5000 // name's 0th code point is an ASCII lower alpha;
5001 if (!len || name[0] < 'a' || name[0] > 'z') {
5002 return false;
5003 }
5004
5005 uint32_t i = 1;
5006 while (i < len) {
5007 // name does not contain any ASCII upper alphas
5008 if (name[i] >= 'A' && name[i] <= 'Z') {
5009 return false;
5010 }
5011
5012 // name is a valid element local name;
5013 //
5014 // // https://dom.spec.whatwg.org/#valid-element-local-name
5015 // Step 2.1.
5016 // If name contains ASCII whitespace, U+0000 NULL, U+002F (/), or U+003E
5017 // (>), then return false.
5018 //
5019 // ASCII whitespace is U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, or
5020 // U+0020 SPACE.
5021 if (name[i] == 0x0000 || // null
5022 name[i] == 0x0009 || // tab
5023 name[i] == 0x000A || // newline
5024 name[i] == 0x000C || // form feed
5025 name[i] == 0x000D || // carriage return
5026 name[i] == 0x0020 || // space
5027 name[i] == 0x002F || // /
5028 name[i] == 0x003E) { // >
5029 return false;
5030 }
5031
5032 if (name[i] == '-') {
5033 hasDash = true;
5034 }
5035
5036 i++;
5037 }
5038 return hasDash;
5039}
5040
5041// static
5042bool nsContentUtils::IsCustomElementName(nsAtom* aName, uint32_t aNameSpaceID) {
5043 // Allow non-dashed names in XUL for XBL to Custom Element migrations.
5044 if (aNameSpaceID == kNameSpaceID_XUL8) {
5045 return true;
5046 }
5047
5048 bool hasDash = IsNameWithDash(aName);
5049 if (!hasDash) {
5050 return false;
5051 }
5052
5053 // The custom element name must not be one of the following values:
5054 // annotation-xml
5055 // color-profile
5056 // font-face
5057 // font-face-src
5058 // font-face-uri
5059 // font-face-format
5060 // font-face-name
5061 // missing-glyph
5062 return aName != nsGkAtoms::annotation_xml &&
5063 aName != nsGkAtoms::color_profile && aName != nsGkAtoms::font_face &&
5064 aName != nsGkAtoms::font_face_src &&
5065 aName != nsGkAtoms::font_face_uri &&
5066 aName != nsGkAtoms::font_face_format &&
5067 aName != nsGkAtoms::font_face_name && aName != nsGkAtoms::missingGlyph;
5068}
5069
5070bool nsContentUtils::IsValidShadowHostName(nsAtom* aName,
5071 uint32_t aNameSpaceID) {
5072 return IsCustomElementName(aName, aNameSpaceID) ||
5073 aName == nsGkAtoms::article || aName == nsGkAtoms::aside ||
5074 aName == nsGkAtoms::blockquote || aName == nsGkAtoms::body ||
5075 aName == nsGkAtoms::div || aName == nsGkAtoms::footer ||
5076 aName == nsGkAtoms::h1 || aName == nsGkAtoms::h2 ||
5077 aName == nsGkAtoms::h3 || aName == nsGkAtoms::h4 ||
5078 aName == nsGkAtoms::h5 || aName == nsGkAtoms::h6 ||
5079 aName == nsGkAtoms::header || aName == nsGkAtoms::main ||
5080 aName == nsGkAtoms::nav || aName == nsGkAtoms::p ||
5081 aName == nsGkAtoms::section || aName == nsGkAtoms::span;
5082}
5083
5084// static
5085nsresult nsContentUtils::CheckQName(const nsAString& aQualifiedName,
5086 bool aNamespaceAware,
5087 const char16_t** aColon) {
5088 const char* colon = nullptr;
5089 const char16_t* begin = aQualifiedName.BeginReading();
5090 const char16_t* end = aQualifiedName.EndReading();
5091
5092 int result = MOZ_XMLCheckQName(reinterpret_cast<const char*>(begin),
5093 reinterpret_cast<const char*>(end),
5094 aNamespaceAware, &colon);
5095
5096 if (!result) {
5097 if (aColon) {
5098 *aColon = reinterpret_cast<const char16_t*>(colon);
5099 }
5100
5101 return NS_OK;
5102 }
5103
5104 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5105}
5106
5107static inline bool IsValidRestrictedContinuation(char16_t c) {
5108 return mozilla::IsAsciiAlpha(c) || mozilla::IsAsciiDigit(c) || c == '-' ||
5109 c == '.' || c == ':' || c == '_' || c >= 0x80;
5110}
5111
5112// static
5113// https://dom.spec.whatwg.org/#valid-element-local-name
5114// Two paths:
5115// 1. Starts with [A-Za-z]: continuation can be any char except
5116// null/whitespace/>/'/'
5117// 2. Starts with [:_>=0x80]: continuation must be [A-Za-z0-9-.:_>=0x80]
5118bool nsContentUtils::IsValidElementLocalName(const nsAString& aName) {
5119 if (aName.IsEmpty()) {
5120 return false;
5121 }
5122
5123 const char16_t* ptr = aName.BeginReading();
5124 const char16_t* end = aName.EndReading();
5125 char16_t first = *ptr;
5126
5127 if (mozilla::IsAsciiAlpha(first)) {
5128 // Path 1: ASCII alpha start - any continuation except forbidden chars.
5129 for (++ptr; ptr < end; ++ptr) {
5130 char16_t c = *ptr;
5131 if (c == 0 || IsHTMLWhitespace(c) || c == '/' || c == '>') {
5132 return false;
5133 }
5134 }
5135 return true;
5136 }
5137
5138 if (first == ':' || first == '_' || first >= 0x80) {
5139 // Path 2: Colon, underscore, or non-ASCII start - restricted continuation.
5140 for (++ptr; ptr < end; ++ptr) {
5141 if (!IsValidRestrictedContinuation(*ptr)) {
5142 return false;
5143 }
5144 }
5145 return true;
5146 }
5147
5148 // Starting with anything else (e.g., digits, other ASCII) is invalid.
5149 return false;
5150}
5151
5152// static
5153// https://dom.spec.whatwg.org/#valid-attribute-local-name
5154bool nsContentUtils::IsValidAttributeLocalName(const nsAString& aName) {
5155 if (aName.IsEmpty()) {
5156 return false;
5157 }
5158 for (const char16_t* ptr = aName.BeginReading(); ptr < aName.EndReading();
5159 ptr++) {
5160 char16_t c = *ptr;
5161 if (c == 0 || IsHTMLWhitespace(c) || c == '>' || c == '/' || c == '=') {
5162 return false;
5163 }
5164 }
5165 return true;
5166}
5167
5168// static
5169// https://dom.spec.whatwg.org/#valid-namespace-prefix
5170bool nsContentUtils::IsValidNamespacePrefix(const nsAString& aPrefix) {
5171 // Empty prefix is valid (means no prefix).
5172 if (aPrefix.IsEmpty()) {
5173 return true;
5174 }
5175 for (const char16_t* ptr = aPrefix.BeginReading(); ptr < aPrefix.EndReading();
5176 ptr++) {
5177 char16_t c = *ptr;
5178 if (c == 0 || IsHTMLWhitespace(c) || c == '/' || c == '>') {
5179 return false;
5180 }
5181 }
5182 return true;
5183}
5184
5185// static
5186// https://dom.spec.whatwg.org/#valid-doctype-name
5187bool nsContentUtils::IsValidDoctypeName(const nsAString& aName) {
5188 // Empty doctype name is valid per spec (it just can't contain bad chars).
5189 for (const char16_t* ptr = aName.BeginReading(); ptr < aName.EndReading();
5190 ptr++) {
5191 char16_t c = *ptr;
5192 if (c == 0 || IsHTMLWhitespace(c) || c == '>') {
5193 return false;
5194 }
5195 }
5196 return true;
5197}
5198
5199// static
5200// https://dom.spec.whatwg.org/#validate-and-extract
5201// This implements only the validation and parsing portion of the algorithm.
5202// Namespace resolution (steps involving namespace lookups) is handled by
5203// callers.
5204nsresult nsContentUtils::ParseQualifiedNameRelaxed(
5205 const nsAString& aQualifiedName, uint16_t aNodeType,
5206 const char16_t** aColon, const char16_t** aLocalNameEnd) {
5207 if (aColon) {
5208 *aColon = nullptr;
5209 }
5210 if (aLocalNameEnd) {
5211 *aLocalNameEnd = nullptr;
5212 }
5213
5214 if (aQualifiedName.IsEmpty()) {
5215 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5216 }
5217
5218 const char16_t* begin = aQualifiedName.BeginReading();
5219 const char16_t* end = aQualifiedName.EndReading();
5220 const char16_t* firstColon = nullptr;
5221
5222 for (const char16_t* ptr = begin; ptr < end; ptr++) {
5223 if (*ptr == ':') {
5224 firstColon = ptr;
5225 break;
5226 }
5227 }
5228
5229 if (firstColon) {
5230 nsDependentSubstring prefix(begin, firstColon);
5231
5232 if (prefix.IsEmpty()) {
5233 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5234 }
5235
5236 if (!IsValidNamespacePrefix(prefix)) {
5237 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5238 }
5239
5240 // Local name is everything after the first colon.
5241 nsDependentSubstring localName(firstColon + 1, end);
5242
5243 // Local name must not be empty.
5244 if (localName.IsEmpty()) {
5245 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5246 }
5247
5248 // Validate local name based on node type.
5249 if (aNodeType == nsINode::ATTRIBUTE_NODE) {
5250 if (!IsValidAttributeLocalName(localName)) {
5251 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5252 }
5253 } else {
5254 if (!IsValidElementLocalName(localName)) {
5255 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5256 }
5257 }
5258
5259 if (aColon) {
5260 *aColon = firstColon;
5261 }
5262 if (aLocalNameEnd) {
5263 *aLocalNameEnd = end;
5264 }
5265 } else {
5266 // No colon, the whole string is the local name.
5267 if (aNodeType == nsINode::ATTRIBUTE_NODE) {
5268 if (!IsValidAttributeLocalName(aQualifiedName)) {
5269 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5270 }
5271 } else {
5272 if (!IsValidElementLocalName(aQualifiedName)) {
5273 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5274 }
5275 }
5276 }
5277
5278 return NS_OK;
5279}
5280
5281// static
5282nsresult nsContentUtils::SplitQName(const nsIContent* aNamespaceResolver,
5283 const nsString& aQName, int32_t* aNamespace,
5284 nsAtom** aLocalName) {
5285 const char16_t* colon;
5286 nsresult rv = nsContentUtils::CheckQName(aQName, true, &colon);
5287 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5287); return rv; } } while (false)
;
5288
5289 if (colon) {
5290 const char16_t* end;
5291 aQName.EndReading(end);
5292 nsAutoString nameSpace;
5293 rv = aNamespaceResolver->LookupNamespaceURIInternal(
5294 Substring(aQName.get(), colon), nameSpace);
5295 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5295); return rv; } } while (false)
;
5296
5297 *aNamespace = nsNameSpaceManager::GetInstance()->GetNameSpaceID(
5298 nameSpace, nsContentUtils::IsChromeDoc(aNamespaceResolver->OwnerDoc()));
5299 if (*aNamespace == kNameSpaceID_Unknown-1) return NS_ERROR_FAILURE;
5300
5301 *aLocalName = NS_AtomizeMainThread(Substring(colon + 1, end)).take();
5302 } else {
5303 *aNamespace = kNameSpaceID_None;
5304 *aLocalName = NS_AtomizeMainThread(aQName).take();
5305 }
5306 NS_ENSURE_TRUE(aLocalName, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(aLocalName)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aLocalName" ") failed",
nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5306
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
5307 return NS_OK;
5308}
5309
5310// static
5311nsresult nsContentUtils::GetNodeInfoFromQName(
5312 const nsAString& aNamespaceURI, const nsAString& aQualifiedName,
5313 nsNodeInfoManager* aNodeInfoManager, uint16_t aNodeType,
5314 mozilla::dom::NodeInfo** aNodeInfo) {
5315 const nsString& qName = PromiseFlatStringTPromiseFlatString<char16_t>(aQualifiedName);
5316 const char16_t* colon;
5317 const char16_t* localNameEnd;
5318 nsresult rv = nsContentUtils::ParseQualifiedNameRelaxed(
5319 qName, aNodeType, &colon, &localNameEnd);
5320 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5320); return rv; } } while (false)
;
5321
5322 int32_t nsID;
5323 nsNameSpaceManager::GetInstance()->RegisterNameSpace(aNamespaceURI, nsID);
5324 if (colon) {
5325 RefPtr<nsAtom> prefix = NS_AtomizeMainThread(Substring(qName.get(), colon));
5326
5327 rv = aNodeInfoManager->GetNodeInfo(Substring(colon + 1, localNameEnd),
5328 prefix, nsID, aNodeType, aNodeInfo);
5329 } else {
5330 rv = aNodeInfoManager->GetNodeInfo(aQualifiedName, nullptr, nsID, aNodeType,
5331 aNodeInfo);
5332 }
5333 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5333); return rv; } } while (false)
;
5334
5335 return nsContentUtils::IsValidNodeName((*aNodeInfo)->NameAtom(),
5336 (*aNodeInfo)->GetPrefixAtom(),
5337 (*aNodeInfo)->NamespaceID())
5338 ? NS_OK
5339 : NS_ERROR_DOM_NAMESPACE_ERR;
5340}
5341
5342// static
5343void nsContentUtils::SplitExpatName(const char16_t* aExpatName,
5344 nsAtom** aPrefix, nsAtom** aLocalName,
5345 int32_t* aNameSpaceID) {
5346 /**
5347 * Expat can send the following:
5348 * localName
5349 * namespaceURI<separator>localName
5350 * namespaceURI<separator>localName<separator>prefix
5351 *
5352 * and we use 0xFFFF for the <separator>.
5353 *
5354 */
5355
5356 const char16_t* uriEnd = nullptr;
5357 const char16_t* nameEnd = nullptr;
5358 const char16_t* pos;
5359 for (pos = aExpatName; *pos; ++pos) {
5360 if (*pos == 0xFFFF) {
5361 if (uriEnd) {
5362 nameEnd = pos;
5363 } else {
5364 uriEnd = pos;
5365 }
5366 }
5367 }
5368
5369 const char16_t* nameStart;
5370 if (uriEnd) {
5371 nsNameSpaceManager::GetInstance()->RegisterNameSpace(
5372 nsDependentSubstring(aExpatName, uriEnd), *aNameSpaceID);
5373
5374 nameStart = (uriEnd + 1);
5375 if (nameEnd) {
5376 const char16_t* prefixStart = nameEnd + 1;
5377 *aPrefix = NS_AtomizeMainThread(Substring(prefixStart, pos)).take();
5378 } else {
5379 nameEnd = pos;
5380 *aPrefix = nullptr;
5381 }
5382 } else {
5383 *aNameSpaceID = kNameSpaceID_None;
5384 nameStart = aExpatName;
5385 nameEnd = pos;
5386 *aPrefix = nullptr;
5387 }
5388 *aLocalName = NS_AtomizeMainThread(Substring(nameStart, nameEnd)).take();
5389}
5390
5391// static
5392PresShell* nsContentUtils::GetPresShellForContent(const nsIContent* aContent) {
5393 Document* doc = aContent->GetComposedDoc();
5394 if (!doc) {
5395 return nullptr;
5396 }
5397 return doc->GetPresShell();
5398}
5399
5400// static
5401nsPresContext* nsContentUtils::GetContextForContent(
5402 const nsIContent* aContent) {
5403 PresShell* presShell = GetPresShellForContent(aContent);
5404 if (!presShell) {
5405 return nullptr;
5406 }
5407 return presShell->GetPresContext();
5408}
5409
5410// static
5411bool nsContentUtils::IsInPrivateBrowsing(nsILoadGroup* aLoadGroup) {
5412 if (!aLoadGroup) {
5413 return false;
5414 }
5415 // See duplicated code in Document::Reset/ResetToURI
5416 bool isPrivate = false;
5417 nsCOMPtr<nsIInterfaceRequestor> callbacks;
5418 aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
5419 if (callbacks) {
5420 nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
5421 isPrivate = loadContext && loadContext->UsePrivateBrowsing();
5422 }
5423 return isPrivate;
5424}
5425
5426// FIXME(emilio): This is (effectively) almost but not quite the same as
5427// Document::ShouldLoadImages(), which one is right?
5428bool nsContentUtils::DocumentInactiveForImageLoads(Document* aDocument) {
5429 if (!aDocument) {
5430 return false;
5431 }
5432 if (IsChromeDoc(aDocument) || aDocument->IsResourceDoc() ||
5433 aDocument->IsStaticDocument()) {
5434 return false;
5435 }
5436 nsCOMPtr<nsPIDOMWindowInner> win =
5437 do_QueryInterface(aDocument->GetScopeObject());
5438 return !win || !win->GetDocShell();
5439}
5440
5441imgLoader* nsContentUtils::GetImgLoaderForDocument(Document* aDoc) {
5442 NS_ENSURE_TRUE(!DocumentInactiveForImageLoads(aDoc), nullptr)do { if ((__builtin_expect(!!(!(!DocumentInactiveForImageLoads
(aDoc))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!DocumentInactiveForImageLoads(aDoc)" ") failed", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5442); return nullptr; } } while (false)
;
5443
5444 if (!aDoc) {
5445 return imgLoader::NormalLoader();
5446 }
5447 const bool isPrivate = aDoc->IsInPrivateBrowsing();
5448 return isPrivate ? imgLoader::PrivateBrowsingLoader()
5449 : imgLoader::NormalLoader();
5450}
5451
5452// static
5453imgLoader* nsContentUtils::GetImgLoaderForChannel(nsIChannel* aChannel,
5454 Document* aContext) {
5455 NS_ENSURE_TRUE(!DocumentInactiveForImageLoads(aContext), nullptr)do { if ((__builtin_expect(!!(!(!DocumentInactiveForImageLoads
(aContext))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!DocumentInactiveForImageLoads(aContext)" ") failed", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5455); return
nullptr; } } while (false)
;
5456
5457 if (!aChannel) {
5458 return imgLoader::NormalLoader();
5459 }
5460 return NS_UsePrivateBrowsing(aChannel) ? imgLoader::PrivateBrowsingLoader()
5461 : imgLoader::NormalLoader();
5462}
5463
5464// static
5465int32_t nsContentUtils::CORSModeToLoadImageFlags(mozilla::CORSMode aMode) {
5466 switch (aMode) {
5467 case CORS_ANONYMOUS:
5468 return imgILoader::LOAD_CORS_ANONYMOUS;
5469 case CORS_USE_CREDENTIALS:
5470 return imgILoader::LOAD_CORS_USE_CREDENTIALS;
5471 default:
5472 return 0;
5473 }
5474}
5475
5476// static
5477nsresult nsContentUtils::LoadImage(
5478 nsIURI* aURI, nsINode* aContext, Document* aLoadingDocument,
5479 nsIPrincipal* aLoadingPrincipal, uint64_t aRequestContextID,
5480 nsIReferrerInfo* aReferrerInfo, imgINotificationObserver* aObserver,
5481 int32_t aLoadFlags, const nsAString& initiatorType,
5482 imgRequestProxy** aRequest, nsContentPolicyType aContentPolicyType,
5483 bool aUseUrgentStartForChannel, bool aLinkPreload,
5484 uint64_t aEarlyHintPreloaderId,
5485 mozilla::dom::FetchPriority aFetchPriority) {
5486 MOZ_ASSERT(aURI, "Must have a URI")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURI)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURI" " (" "Must have a URI" ")"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5486); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aURI" ") (" "Must have a URI" ")"); do { MOZ_CrashSequence
(__null, 5486); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5487 MOZ_ASSERT(aContext, "Must have a context")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aContext))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aContext" " (" "Must have a context"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5487
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContext" ") (" "Must have a context"
")"); do { MOZ_CrashSequence(__null, 5487); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5488 MOZ_ASSERT(aLoadingDocument, "Must have a document")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadingDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadingDocument))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aLoadingDocument"
" (" "Must have a document" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5488); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingDocument"
") (" "Must have a document" ")"); do { MOZ_CrashSequence(__null
, 5488); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
5489 MOZ_ASSERT(aLoadingPrincipal, "Must have a principal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadingPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadingPrincipal))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aLoadingPrincipal"
" (" "Must have a principal" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5489); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Must have a principal" ")"); do { MOZ_CrashSequence(__null
, 5489); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
5490 MOZ_ASSERT(aRequest, "Null out param")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequest)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequest))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aRequest" " (" "Null out param"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5490
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest" ") (" "Null out param"
")"); do { MOZ_CrashSequence(__null, 5490); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5491
5492 imgLoader* imgLoader = GetImgLoaderForDocument(aLoadingDocument);
5493 if (!imgLoader) {
5494 // nothing we can do here
5495 return NS_ERROR_FAILURE;
5496 }
5497
5498 nsCOMPtr<nsILoadGroup> loadGroup = aLoadingDocument->GetDocumentLoadGroup();
5499
5500 nsIURI* documentURI = aLoadingDocument->GetDocumentURI();
5501
5502 NS_ASSERTION(loadGroup || aLoadingDocument->IsSVGGlyphsDocument(),do { if (!(loadGroup || aLoadingDocument->IsSVGGlyphsDocument
())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Could not get loadgroup; onload may fire too early"
, "loadGroup || aLoadingDocument->IsSVGGlyphsDocument()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5503); MOZ_PretendNoReturn(); } } while (0)
5503 "Could not get loadgroup; onload may fire too early")do { if (!(loadGroup || aLoadingDocument->IsSVGGlyphsDocument
())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Could not get loadgroup; onload may fire too early"
, "loadGroup || aLoadingDocument->IsSVGGlyphsDocument()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5503); MOZ_PretendNoReturn(); } } while (0)
;
5504
5505 // XXXbz using "documentURI" for the initialDocumentURI is not quite
5506 // right, but the best we can do here...
5507 return imgLoader->LoadImage(aURI, /* uri to load */
5508 documentURI, /* initialDocumentURI */
5509 aReferrerInfo, /* referrerInfo */
5510 aLoadingPrincipal, /* loading principal */
5511 aRequestContextID, /* request context ID */
5512 loadGroup, /* loadgroup */
5513 aObserver, /* imgINotificationObserver */
5514 aContext, /* loading context */
5515 aLoadingDocument, /* uniquification key */
5516 aLoadFlags, /* load flags */
5517 nullptr, /* cache key */
5518 aContentPolicyType, /* content policy type */
5519 initiatorType, /* the load initiator */
5520 aUseUrgentStartForChannel, /* urgent-start flag */
5521 aLinkPreload, /* <link preload> initiator */
5522 aEarlyHintPreloaderId, aFetchPriority, aRequest);
5523}
5524
5525// static
5526already_AddRefed<imgIContainer> nsContentUtils::GetImageFromContent(
5527 nsIImageLoadingContent* aContent, imgIRequest** aRequest) {
5528 if (aRequest) {
5529 *aRequest = nullptr;
5530 }
5531
5532 NS_ENSURE_TRUE(aContent, nullptr)do { if ((__builtin_expect(!!(!(aContent)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aContent" ") failed", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5532); return
nullptr; } } while (false)
;
5533
5534 nsCOMPtr<imgIRequest> imgRequest;
5535 aContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
5536 getter_AddRefs(imgRequest));
5537 if (!imgRequest) {
5538 return nullptr;
5539 }
5540
5541 nsCOMPtr<imgIContainer> imgContainer;
5542 imgRequest->GetImage(getter_AddRefs(imgContainer));
5543
5544 if (!imgContainer) {
5545 return nullptr;
5546 }
5547
5548 if (aRequest) {
5549 // If the consumer wants the request, verify it has actually loaded
5550 // successfully.
5551 uint32_t imgStatus;
5552 imgRequest->GetImageStatus(&imgStatus);
5553 if (imgStatus & imgIRequest::STATUS_FRAME_COMPLETE &&
5554 !(imgStatus & imgIRequest::STATUS_ERROR)) {
5555 imgRequest.swap(*aRequest);
5556 }
5557 }
5558
5559 return imgContainer.forget();
5560}
5561
5562static bool IsLinkWithURI(const nsIContent& aContent) {
5563 const auto* element = Element::FromNode(aContent);
5564 if (!element || !element->IsLink()) {
5565 return false;
5566 }
5567 nsCOMPtr<nsIURI> absURI = element->GetHrefURI();
5568 return !!absURI;
5569}
5570
5571static bool HasImageRequest(nsIContent& aContent) {
5572 nsCOMPtr<nsIImageLoadingContent> imageContent(do_QueryInterface(&aContent));
5573 if (!imageContent) {
5574 return false;
5575 }
5576
5577 nsCOMPtr<imgIRequest> imgRequest;
5578 imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
5579 getter_AddRefs(imgRequest));
5580
5581 // XXXbz It may be draggable even if the request resulted in an error. Why?
5582 // Not sure; that's what the old nsContentAreaDragDrop/nsFrame code did.
5583 return !!imgRequest;
5584}
5585
5586static Maybe<bool> DraggableOverride(const nsIContent& aContent) {
5587 if (auto* el = nsGenericHTMLElement::FromNode(aContent)) {
5588 if (el->Draggable()) {
5589 return Some(true);
5590 }
5591
5592 if (el->AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable,
5593 nsGkAtoms::_false, eIgnoreCase)) {
5594 return Some(false);
5595 }
5596 }
5597 if (aContent.IsSVGElement()) {
5598 return Some(false);
5599 }
5600 return Nothing();
5601}
5602
5603// static
5604bool nsContentUtils::ContentIsDraggable(nsIContent* aContent) {
5605 MOZ_ASSERT(aContent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aContent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aContent", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5605); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { MOZ_CrashSequence(__null, 5605); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5606
5607 if (auto draggable = DraggableOverride(*aContent)) {
5608 return *draggable;
5609 }
5610
5611 // special handling for content area image and link dragging
5612 return HasImageRequest(*aContent) || IsLinkWithURI(*aContent);
5613}
5614
5615// static
5616bool nsContentUtils::IsDraggableImage(nsIContent* aContent) {
5617 MOZ_ASSERT(aContent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aContent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aContent", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5617); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { MOZ_CrashSequence(__null, 5617); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5618 return HasImageRequest(*aContent) &&
5619 DraggableOverride(*aContent).valueOr(true);
5620}
5621
5622// static
5623bool nsContentUtils::IsDraggableLink(const nsIContent* aContent) {
5624 MOZ_ASSERT(aContent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aContent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aContent))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aContent", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5624); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { MOZ_CrashSequence(__null, 5624); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5625 return IsLinkWithURI(*aContent) && DraggableOverride(*aContent).valueOr(true);
5626}
5627
5628// static
5629nsresult nsContentUtils::QNameChanged(mozilla::dom::NodeInfo* aNodeInfo,
5630 nsAtom* aName,
5631 mozilla::dom::NodeInfo** aResult) {
5632 nsNodeInfoManager* niMgr = aNodeInfo->NodeInfoManager();
5633
5634 *aResult = niMgr
5635 ->GetNodeInfo(aName, nullptr, aNodeInfo->NamespaceID(),
5636 aNodeInfo->NodeType(), aNodeInfo->GetExtraName())
5637 .take();
5638 return NS_OK;
5639}
5640
5641static bool TestSitePerm(nsIPrincipal* aPrincipal, const nsACString& aType,
5642 uint32_t aPerm, bool aExactHostMatch) {
5643 if (!aPrincipal) {
5644 // We always deny (i.e. don't allow) the permission if we don't have a
5645 // principal.
5646 return aPerm != nsIPermissionManager::ALLOW_ACTION;
5647 }
5648
5649 nsCOMPtr<nsIPermissionManager> permMgr =
5650 components::PermissionManager::Service();
5651 NS_ENSURE_TRUE(permMgr, false)do { if ((__builtin_expect(!!(!(permMgr)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "permMgr" ") failed", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5651); return
false; } } while (false)
;
5652
5653 uint32_t perm;
5654 nsresult rv;
5655 if (aExactHostMatch) {
5656 rv = permMgr->TestExactPermissionFromPrincipal(aPrincipal, aType, &perm);
5657 } else {
5658 rv = permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &perm);
5659 }
5660 NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5660); return false; } } while (false)
;
5661
5662 return perm == aPerm;
5663}
5664
5665bool nsContentUtils::IsSitePermAllow(nsIPrincipal* aPrincipal,
5666 const nsACString& aType) {
5667 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION,
5668 false);
5669}
5670
5671bool nsContentUtils::IsSitePermDeny(nsIPrincipal* aPrincipal,
5672 const nsACString& aType) {
5673 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION,
5674 false);
5675}
5676
5677bool nsContentUtils::IsExactSitePermAllow(nsIPrincipal* aPrincipal,
5678 const nsACString& aType) {
5679 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION,
5680 true);
5681}
5682
5683bool nsContentUtils::IsExactSitePermDeny(nsIPrincipal* aPrincipal,
5684 const nsACString& aType) {
5685 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION,
5686 true);
5687}
5688
5689bool nsContentUtils::HasSitePerm(nsIPrincipal* aPrincipal,
5690 const nsACString& aType) {
5691 if (!aPrincipal) {
5692 return false;
5693 }
5694
5695 nsCOMPtr<nsIPermissionManager> permMgr =
5696 components::PermissionManager::Service();
5697 NS_ENSURE_TRUE(permMgr, false)do { if ((__builtin_expect(!!(!(permMgr)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "permMgr" ") failed", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5697); return
false; } } while (false)
;
5698
5699 uint32_t perm;
5700 nsresult rv = permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &perm);
5701 NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5701); return false; } } while (false)
;
5702
5703 return perm != nsIPermissionManager::UNKNOWN_ACTION;
5704}
5705
5706static const char* gEventNames[] = {"event"};
5707static const char* gSVGEventNames[] = {"evt"};
5708// for b/w compat, the first name to onerror is still 'event', even though it
5709// is actually the error message
5710static const char* gOnErrorNames[] = {"event", "source", "lineno", "colno",
5711 "error"};
5712
5713// static
5714void nsContentUtils::GetEventArgNames(int32_t aNameSpaceID, nsAtom* aEventName,
5715 bool aIsForWindow, uint32_t* aArgCount,
5716 const char*** aArgArray) {
5717#define SET_EVENT_ARG_NAMES(names)*aArgCount = sizeof(names) / sizeof(names[0]); *aArgArray = names
;
\
5718 *aArgCount = sizeof(names) / sizeof(names[0]); \
5719 *aArgArray = names;
5720
5721 // JSEventHandler is what does the arg magic for onerror, and it does
5722 // not seem to take the namespace into account. So we let onerror in all
5723 // namespaces get the 3 arg names.
5724 if (aEventName == nsGkAtoms::onerror && aIsForWindow) {
5725 SET_EVENT_ARG_NAMES(gOnErrorNames)*aArgCount = sizeof(gOnErrorNames) / sizeof(gOnErrorNames[0])
; *aArgArray = gOnErrorNames;
;
5726 } else if (aNameSpaceID == kNameSpaceID_SVG9) {
5727 SET_EVENT_ARG_NAMES(gSVGEventNames)*aArgCount = sizeof(gSVGEventNames) / sizeof(gSVGEventNames[0
]); *aArgArray = gSVGEventNames;
;
5728 } else {
5729 SET_EVENT_ARG_NAMES(gEventNames)*aArgCount = sizeof(gEventNames) / sizeof(gEventNames[0]); *aArgArray
= gEventNames;
;
5730 }
5731}
5732
5733// Note: The list of content bundles in nsStringBundle.cpp should be updated
5734// whenever entries are added or removed from this list.
5735static const char* gPropertiesFiles[kPropertiesFileCount] = {
5736 // Must line up with the enum values in |PropertiesFile| enum.
5737 "chrome://global/locale/css.properties",
5738 "chrome://global/locale/xul.properties",
5739 "chrome://global/locale/layout_errors.properties",
5740 "chrome://global/locale/layout/HtmlForm.properties",
5741 "chrome://global/locale/printing.properties",
5742 "chrome://global/locale/dom/dom.properties",
5743 "chrome://global/locale/layout/htmlparser.properties",
5744 "chrome://global/locale/svg/svg.properties",
5745 "chrome://branding/locale/brand.properties",
5746 "chrome://global/locale/commonDialogs.properties",
5747 "chrome://global/locale/mathml/mathml.properties",
5748 "chrome://global/locale/security/security.properties",
5749 "chrome://necko/locale/necko.properties",
5750 "resource://gre/res/locale/layout/HtmlForm.properties",
5751 "resource://gre/res/locale/dom/dom.properties",
5752 "resource://gre/res/locale/necko/necko.properties",
5753};
5754
5755/* static */
5756nsresult nsContentUtils::EnsureStringBundle(PropertiesFile aFile) {
5757 MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Should not create bundles off main thread." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5758); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "NS_IsMainThread()"
") (" "Should not create bundles off main thread." ")"); do {
MOZ_CrashSequence(__null, 5758); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5758 "Should not create bundles off main thread.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Should not create bundles off main thread." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5758); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "NS_IsMainThread()"
") (" "Should not create bundles off main thread." ")"); do {
MOZ_CrashSequence(__null, 5758); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5759 if (!sStringBundles[size_t(aFile)]) {
5760 if (!sStringBundleService) {
5761 nsresult rv =
5762 CallGetService(NS_STRINGBUNDLE_CONTRACTID"@mozilla.org/intl/stringbundle;1", &sStringBundleService);
5763 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5763); return rv; } } while (false)
;
5764 }
5765 RefPtr<nsIStringBundle> bundle;
5766 MOZ_TRY(sStringBundleService->CreateBundle(gPropertiesFiles[size_t(aFile)],__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(sStringBundleService->CreateBundle(gPropertiesFiles[size_t
(aFile)], getter_AddRefs(bundle))); if ((__builtin_expect(!!(
mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
5767 getter_AddRefs(bundle)))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(sStringBundleService->CreateBundle(gPropertiesFiles[size_t
(aFile)], getter_AddRefs(bundle))); if ((__builtin_expect(!!(
mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
5768 sStringBundles[size_t(aFile)] = bundle.forget();
5769 }
5770 return NS_OK;
5771}
5772
5773/* static */
5774void nsContentUtils::AsyncPrecreateStringBundles() {
5775 // We only ever want to pre-create bundles in the parent process.
5776 //
5777 // All nsContentUtils bundles are shared between the parent and child
5778 // precesses, and the shared memory regions that back them *must* be created
5779 // in the parent, and then sent to all children.
5780 //
5781 // If we attempt to create a bundle in the child before its memory region is
5782 // available, we need to create a temporary non-shared bundle, and later
5783 // replace that with the shared memory copy. So attempting to pre-load in the
5784 // child is wasteful and unnecessary.
5785 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5785); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "XRE_IsParentProcess()" ")"); do { MOZ_CrashSequence
(__null, 5785); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5786
5787 for (size_t bundleIndex = 0; bundleIndex < kPropertiesFileCount;
5788 ++bundleIndex) {
5789 nsresult rv = NS_DispatchToCurrentThreadQueue(
5790 NS_NewRunnableFunction("AsyncPrecreateStringBundles",
5791 [bundleIndex]() {
5792 PropertiesFile file =
5793 static_cast<PropertiesFile>(bundleIndex);
5794 EnsureStringBundle(file);
5795 nsIStringBundle* bundle =
5796 sStringBundles[size_t(file)];
5797 bundle->AsyncPreload();
5798 }),
5799 EventQueuePriority::Idle);
5800 (void)NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5800)
;
5801 }
5802}
5803
5804static PropertiesFile GetMaybeSpoofedPropertiesFile(PropertiesFile aFile,
5805 const char* aKey,
5806 const Document* aDocument) {
5807 // When we spoof English, use en-US properties in strings that are accessible
5808 // by content.
5809 bool spoofLocale = nsContentUtils::ShouldResistFingerprinting(
5810 aDocument, RFPTarget::JSLocale);
5811 if (spoofLocale) {
5812 switch (aFile) {
5813 case PropertiesFile::FORMS_PROPERTIES:
5814 return PropertiesFile::FORMS_PROPERTIES_en_US;
5815 case PropertiesFile::DOM_PROPERTIES:
5816 return PropertiesFile::DOM_PROPERTIES_en_US;
5817 default:
5818 break;
5819 }
5820 }
5821 return aFile;
5822}
5823
5824/* static */
5825nsresult nsContentUtils::GetMaybeLocalizedString(PropertiesFile aFile,
5826 const char* aKey,
5827 const Document* aDocument,
5828 nsAString& aResult) {
5829 return GetLocalizedString(
5830 GetMaybeSpoofedPropertiesFile(aFile, aKey, aDocument), aKey, aResult);
5831}
5832
5833/* static */
5834nsresult nsContentUtils::GetLocalizedString(PropertiesFile aFile,
5835 const char* aKey,
5836 nsAString& aResult) {
5837 return FormatLocalizedString(aFile, aKey, {}, aResult);
5838}
5839
5840/* static */
5841nsresult nsContentUtils::FormatMaybeLocalizedString(
5842 PropertiesFile aFile, const char* aKey, Document* aDocument,
5843 const nsTArray<nsString>& aParams, nsAString& aResult) {
5844 return FormatLocalizedString(
5845 GetMaybeSpoofedPropertiesFile(aFile, aKey, aDocument), aKey, aParams,
5846 aResult);
5847}
5848
5849class FormatLocalizedStringRunnable final : public WorkerMainThreadRunnable {
5850 public:
5851 FormatLocalizedStringRunnable(WorkerPrivate* aWorkerPrivate,
5852 PropertiesFile aFile, const char* aKey,
5853 const nsTArray<nsString>& aParams,
5854 nsAString& aLocalizedString)
5855 : WorkerMainThreadRunnable(aWorkerPrivate,
5856 "FormatLocalizedStringRunnable"_ns),
5857 mFile(aFile),
5858 mKey(aKey),
5859 mParams(aParams),
5860 mLocalizedString(aLocalizedString) {
5861 MOZ_ASSERT(aWorkerPrivate)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aWorkerPrivate)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aWorkerPrivate))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aWorkerPrivate"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 5861); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aWorkerPrivate" ")"); do { MOZ_CrashSequence
(__null, 5861); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5862 aWorkerPrivate->AssertIsOnWorkerThread();
5863 }
5864
5865 bool MainThreadRun() override {
5866 AssertIsOnMainThread();
5867
5868 mResult = nsContentUtils::FormatLocalizedString(mFile, mKey, mParams,
5869 mLocalizedString);
5870 (void)NS_WARN_IF(NS_FAILED(mResult))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(mResult
)), 0))), "NS_FAILED(mResult)", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5870)
;
5871 return true;
5872 }
5873
5874 nsresult GetResult() const { return mResult; }
5875
5876 private:
5877 const PropertiesFile mFile;
5878 const char* mKey;
5879 const nsTArray<nsString>& mParams;
5880 nsresult mResult = NS_ERROR_FAILURE;
5881 nsAString& mLocalizedString;
5882};
5883
5884/* static */
5885nsresult nsContentUtils::FormatLocalizedString(
5886 PropertiesFile aFile, const char* aKey, const nsTArray<nsString>& aParams,
5887 nsAString& aResult) {
5888 if (!NS_IsMainThread()) {
5889 // nsIStringBundle is thread-safe but its creation is not, and in particular
5890 // we don't create and store nsIStringBundle objects in a thread-safe way.
5891 //
5892 // TODO(emilio): Maybe if we already have the right bundle created we could
5893 // just call into it, but we should make sure that Shutdown() doesn't get
5894 // called on the main thread when that happens which is a bit tricky to
5895 // prove?
5896 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
5897 if (NS_WARN_IF(!workerPrivate)NS_warn_if_impl(!workerPrivate, "!workerPrivate", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5897)
) {
5898 return NS_ERROR_UNEXPECTED;
5899 }
5900
5901 auto runnable = MakeRefPtr<FormatLocalizedStringRunnable>(
5902 workerPrivate, aFile, aKey, aParams, aResult);
5903
5904 runnable->Dispatch(workerPrivate, Canceling, IgnoreErrors());
5905 return runnable->GetResult();
5906 }
5907
5908 MOZ_TRY(EnsureStringBundle(aFile))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(EnsureStringBundle(aFile)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
;
5909 nsIStringBundle* bundle = sStringBundles[size_t(aFile)];
5910 if (aParams.IsEmpty()) {
5911 return bundle->GetStringFromName(aKey, aResult);
5912 }
5913 return bundle->FormatStringFromName(aKey, aParams, aResult);
5914}
5915
5916/* static */
5917void nsContentUtils::LogSimpleConsoleError(const nsAString& aErrorText,
5918 const nsACString& aCategory,
5919 bool aFromPrivateWindow,
5920 bool aFromChromeContext,
5921 uint32_t aErrorFlags) {
5922 nsCOMPtr<nsIScriptError> scriptError =
5923 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1");
5924 if (scriptError) {
5925 nsCOMPtr<nsIConsoleService> console =
5926 do_GetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1");
5927 if (console && NS_SUCCEEDED(scriptError->Init(((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init
( aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow
, aFromChromeContext))), 1)))
5928 aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory,((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init
( aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow
, aFromChromeContext))), 1)))
5929 aFromPrivateWindow, aFromChromeContext))((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init
( aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow
, aFromChromeContext))), 1)))
) {
5930 console->LogMessage(scriptError);
5931 }
5932 }
5933}
5934
5935/* static */
5936nsresult nsContentUtils::ReportToConsole(
5937 uint32_t aErrorFlags, const nsACString& aCategory,
5938 const Document* aDocument, PropertiesFile aFile, const char* aMessageName,
5939 const nsTArray<nsString>& aParams, const SourceLocation& aLoc) {
5940 nsresult rv;
5941 nsAutoString errorText;
5942 if (!aParams.IsEmpty()) {
5943 rv = FormatLocalizedString(aFile, aMessageName, aParams, errorText);
5944 } else {
5945 rv = GetLocalizedString(aFile, aMessageName, errorText);
5946 }
5947 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5947); return rv; } } while (false)
;
5948 return ReportToConsoleNonLocalized(errorText, aErrorFlags, aCategory,
5949 aDocument, aLoc);
5950}
5951
5952/* static */
5953void nsContentUtils::ReportEmptyGetElementByIdArg(const Document* aDoc) {
5954 ReportToConsole(nsIScriptError::warningFlag, "DOM"_ns, aDoc,
5955 PropertiesFile::DOM_PROPERTIES, "EmptyGetElementByIdParam");
5956}
5957
5958/* static */
5959nsresult nsContentUtils::ReportToConsoleNonLocalized(
5960 const nsAString& aErrorText, uint32_t aErrorFlags,
5961 const nsACString& aCategory, const Document* aDocument,
5962 const SourceLocation& aLoc) {
5963 uint64_t innerWindowID = aDocument ? aDocument->InnerWindowID() : 0;
5964 if (aLoc || !aDocument || !aDocument->GetDocumentURI()) {
5965 return ReportToConsoleByWindowID(aErrorText, aErrorFlags, aCategory,
5966 innerWindowID, aLoc);
5967 }
5968 return ReportToConsoleByWindowID(aErrorText, aErrorFlags, aCategory,
5969 innerWindowID,
5970 SourceLocation(aDocument->GetDocumentURI()));
5971}
5972
5973/* static */
5974nsresult nsContentUtils::ReportToConsoleByWindowID(
5975 const nsAString& aErrorText, uint32_t aErrorFlags,
5976 const nsACString& aCategory, uint64_t aInnerWindowID,
5977 const SourceLocation& aLocation) {
5978 nsresult rv;
5979 if (!sConsoleService) { // only need to bother null-checking here
5980 rv = CallGetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1", &sConsoleService);
5981 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5981); return rv; } } while (false)
;
5982 }
5983
5984 nsCOMPtr<nsIScriptError> errorObject =
5985 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1", &rv);
5986 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5986); return rv; } } while (false)
;
5987
5988 if (aLocation.mResource.is<nsCOMPtr<nsIURI>>()) {
5989 nsIURI* uri = aLocation.mResource.as<nsCOMPtr<nsIURI>>();
5990 rv = errorObject->InitWithSourceURI(aErrorText, uri, aLocation.mLine,
5991 aLocation.mColumn, aErrorFlags,
5992 aCategory, aInnerWindowID);
5993 } else {
5994 rv = errorObject->InitWithWindowID(
5995 aErrorText, aLocation.mResource.as<nsCString>(), aLocation.mLine,
5996 aLocation.mColumn, aErrorFlags, aCategory, aInnerWindowID);
5997 }
5998 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5998); return rv; } } while (false)
;
5999
6000 return sConsoleService->LogMessage(errorObject);
6001}
6002
6003namespace {
6004
6005#define DEPRECATED_OPERATION(_op) #_op,
6006static const char* kDeprecatedOperations[] = {
6007#include "nsDeprecatedOperationList.inc"
6008 nullptr};
6009#undef DEPRECATED_OPERATION
6010
6011} // anonymous namespace
6012
6013/* static */
6014void nsContentUtils::ReportDeprecation(
6015 nsIGlobalObject* aGlobal, const Document* aDoc, nsIURI* aURI,
6016 DeprecatedOperations aOperation,
6017 const mozilla::JSCallingLocation& aLocation,
6018 const nsTArray<nsString>& aParams) {
6019 MOZ_ASSERT(aGlobal)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aGlobal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aGlobal))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aGlobal", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6019); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aGlobal" ")"
); do { MOZ_CrashSequence(__null, 6019); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6020 MOZ_ASSERT(aURI)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURI)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURI", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6020); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")");
do { MOZ_CrashSequence(__null, 6020); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6021
6022 nsAutoCString url;
6023 ReportingUtils::StripURL(aURI, url);
6024
6025 const char* operation =
6026 kDeprecatedOperations[static_cast<size_t>(aOperation)];
6027 nsAutoString type;
6028 type.AppendASCII(operation);
6029
6030 nsAutoCString key;
6031 key.AssignLiteral(operation, strlen(operation));
6032 key.AppendLiteral("Warning");
6033
6034 // XXX do we really want the localized string for deprecation report?
6035 nsAutoString msg;
6036 nsresult rv = FormatLocalizedString(
6037 GetMaybeSpoofedPropertiesFile(PropertiesFile::DOM_PROPERTIES, key.get(),
6038 aDoc),
6039 key.get(), aParams, msg);
6040 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6040)
) {
6041 return;
6042 }
6043
6044 Nullable<uint32_t> lineNumber;
6045 Nullable<uint32_t> columnNumber;
6046 nsAutoCString sourceFile;
6047 if (aLocation) {
6048 lineNumber.SetValue(aLocation.mLine);
6049 columnNumber.SetValue(aLocation.mColumn);
6050 ReportingUtils::StripLocationFileName(aLocation, sourceFile);
6051 }
6052
6053 RefPtr<DeprecationReportBody> body =
6054 new DeprecationReportBody(aGlobal, type, nullptr /* date */, msg,
6055 sourceFile, lineNumber, columnNumber);
6056
6057 ReportingUtils::Report(aGlobal, nsGkAtoms::deprecation, "default"_ns, url,
6058 body);
6059}
6060
6061void nsContentUtils::LogMessageToConsole(const char* aMsg) {
6062 if (!sConsoleService) { // only need to bother null-checking here
6063 CallGetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1", &sConsoleService);
6064 if (!sConsoleService) {
6065 return;
6066 }
6067 }
6068 sConsoleService->LogStringMessage(NS_ConvertUTF8toUTF16(aMsg).get());
6069}
6070
6071bool nsContentUtils::IsChromeDoc(const Document* aDocument) {
6072 return aDocument && aDocument->NodePrincipal() == sSystemPrincipal;
6073}
6074
6075bool nsContentUtils::IsAddonDoc(const Document* aDocument) {
6076 return aDocument &&
6077 aDocument->NodePrincipal()->GetIsAddonOrExpandedAddonPrincipal();
6078}
6079
6080bool nsContentUtils::IsChildOfSameType(Document* aDoc) {
6081 if (BrowsingContext* bc = aDoc->GetBrowsingContext()) {
6082 return bc->GetParent();
6083 }
6084 return false;
6085}
6086
6087static bool IsJSONType(const nsACString& aContentType) {
6088 return aContentType.EqualsLiteral(TEXT_JSON"text/json") ||
6089 aContentType.EqualsLiteral(APPLICATION_JSON"application/json");
6090}
6091
6092static bool IsNonPlainTextType(const nsACString& aContentType) {
6093 // MIME type suffixes which should not be plain text.
6094 static constexpr std::string_view kNonPlainTextTypes[] = {
6095 "html",
6096 "xml",
6097 "xsl",
6098 "calendar",
6099 "x-calendar",
6100 "x-vcalendar",
6101 "vcalendar",
6102 "vcard",
6103 "x-vcard",
6104 "directory",
6105 "ldif",
6106 "qif",
6107 "x-qif",
6108 "x-csv",
6109 "x-vcf",
6110 "rtf",
6111 "comma-separated-values",
6112 "csv",
6113 "tab-separated-values",
6114 "tsv",
6115 "ofx",
6116 "vnd.sun.j2me.app-descriptor",
6117 "x-ms-iqy",
6118 "x-ms-odc",
6119 "x-ms-rqy",
6120 "x-ms-contact"};
6121
6122 // Trim off the "text/" prefix for comparison.
6123 MOZ_ASSERT(StringBeginsWith(aContentType, "text/"_ns))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(StringBeginsWith(aContentType, "text/"_ns))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(StringBeginsWith(aContentType, "text/"_ns)))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("StringBeginsWith(aContentType, \"text/\"_ns)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6123); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "StringBeginsWith(aContentType, \"text/\"_ns)"
")"); do { MOZ_CrashSequence(__null, 6123); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6124 std::string_view suffix = aContentType;
6125 suffix.remove_prefix(5);
6126
6127 for (std::string_view type : kNonPlainTextTypes) {
6128 if (type == suffix) {
6129 return true;
6130 }
6131 }
6132 return false;
6133}
6134
6135bool nsContentUtils::IsPlainTextType(const nsACString& aContentType) {
6136 // All `text/*`, any JSON type and any JavaScript type are considered "plain
6137 // text" types for the purposes of how to render them as a document.
6138 return (StringBeginsWith(aContentType, "text/"_ns) &&
6139 !IsNonPlainTextType(aContentType)) ||
6140 IsJSONType(aContentType) || IsJavascriptMIMEType(aContentType);
6141}
6142
6143bool nsContentUtils::IsUtf8OnlyPlainTextType(const nsACString& aContentType) {
6144 // NOTE: This must be a subset of the list in IsPlainTextType().
6145 return IsJSONType(aContentType) ||
6146 aContentType.EqualsLiteral(TEXT_CACHE_MANIFEST"text/cache-manifest") ||
6147 aContentType.EqualsLiteral(TEXT_VTT"text/vtt");
6148}
6149
6150bool nsContentUtils::IsInChromeDocshell(const Document* aDocument) {
6151 return aDocument && aDocument->IsInChromeDocShell();
6152}
6153
6154// static
6155nsIContentPolicy* nsContentUtils::GetContentPolicy() {
6156 if (!sTriedToGetContentPolicy) {
6157 CallGetService(NS_CONTENTPOLICY_CONTRACTID"@mozilla.org/layout/content-policy;1", &sContentPolicyService);
6158 // It's OK to not have a content policy service
6159 sTriedToGetContentPolicy = true;
6160 }
6161
6162 return sContentPolicyService;
6163}
6164
6165// static
6166bool nsContentUtils::IsEventAttributeName(nsAtom* aName, int32_t aType) {
6167 const char16_t* name = aName->GetUTF16String();
6168 if (name[0] != 'o' || name[1] != 'n') {
6169 return false;
6170 }
6171
6172 EventNameMapping mapping;
6173 return (sAtomEventTable->Get(aName, &mapping) && mapping.mType & aType);
6174}
6175
6176// static
6177EventMessage nsContentUtils::GetEventMessage(nsAtom* aName) {
6178 MOZ_ASSERT(NS_IsMainThread(), "sAtomEventTable is not threadsafe")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "sAtomEventTable is not threadsafe" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6178); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "sAtomEventTable is not threadsafe" ")"); do { MOZ_CrashSequence
(__null, 6178); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6179 if (aName) {
6180 EventNameMapping mapping;
6181 if (sAtomEventTable->Get(aName, &mapping)) {
6182 return mapping.mMessage;
6183 }
6184 }
6185
6186 return eUnidentifiedEvent;
6187}
6188
6189// static
6190void nsContentUtils::ForEachEventAttributeName(
6191 int32_t aType, const FunctionRef<void(nsAtom*)> aFunc) {
6192 for (auto iter = sAtomEventTable->ConstIter(); !iter.Done(); iter.Next()) {
6193 if (iter.Data().mType & aType) {
6194 aFunc(iter.Key());
6195 }
6196 }
6197}
6198
6199// static
6200mozilla::EventClassID nsContentUtils::GetEventClassID(const nsAString& aName) {
6201 EventNameMapping mapping;
6202 if (sStringEventTable->Get(aName, &mapping)) return mapping.mEventClassID;
6203
6204 return eBasicEventClass;
6205}
6206
6207nsAtom* nsContentUtils::GetEventMessageAndAtom(
6208 const nsAString& aName, mozilla::EventClassID aEventClassID,
6209 EventMessage* aEventMessage) {
6210 MOZ_ASSERT(NS_IsMainThread(), "Our hashtables are not threadsafe")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Our hashtables are not threadsafe" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6210); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Our hashtables are not threadsafe" ")"); do { MOZ_CrashSequence
(__null, 6210); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6211 EventNameMapping mapping;
6212 if (sStringEventTable->Get(aName, &mapping)) {
6213 *aEventMessage = mapping.mEventClassID == aEventClassID
6214 ? mapping.mMessage
6215 : eUnidentifiedEvent;
6216 return mapping.mAtom;
6217 }
6218
6219 // If we have cached lots of user defined event names, clear some of them.
6220 if (sUserDefinedEvents->Length() > 127) {
6221 while (sUserDefinedEvents->Length() > 64) {
6222 nsAtom* first = sUserDefinedEvents->ElementAt(0);
6223 sStringEventTable->Remove(Substring(nsDependentAtomString(first), 2));
6224 sUserDefinedEvents->RemoveElementAt(0);
6225 }
6226 }
6227
6228 *aEventMessage = eUnidentifiedEvent;
6229 RefPtr<nsAtom> atom = NS_AtomizeMainThread(u"on"_ns + aName);
6230 sUserDefinedEvents->AppendElement(atom);
6231 mapping.mAtom = atom;
6232 mapping.mMessage = eUnidentifiedEvent;
6233 mapping.mType = EventNameType_None;
6234 mapping.mEventClassID = eBasicEventClass;
6235 sStringEventTable->InsertOrUpdate(aName, mapping);
6236 return mapping.mAtom;
6237}
6238
6239// static
6240EventMessage nsContentUtils::GetEventMessageAndAtomForListener(
6241 const nsAString& aName, nsAtom** aOnName) {
6242 MOZ_ASSERT(NS_IsMainThread(), "Our hashtables are not threadsafe")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Our hashtables are not threadsafe" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6242); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Our hashtables are not threadsafe" ")"); do { MOZ_CrashSequence
(__null, 6242); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6243
6244 // Check sStringEventTable for a matching entry. This will only fail for
6245 // user-defined event types.
6246 EventNameMapping mapping;
6247 if (sStringEventTable->Get(aName, &mapping)) {
6248 RefPtr<nsAtom> atom = mapping.mAtom;
6249 atom.forget(aOnName);
6250 return mapping.mMessage;
6251 }
6252
6253 // sStringEventTable did not contain an entry for this event type string.
6254 // Call GetEventMessageAndAtom, which will create an event type atom and
6255 // cache it in sStringEventTable for future calls.
6256 EventMessage msg = eUnidentifiedEvent;
6257 RefPtr<nsAtom> atom = GetEventMessageAndAtom(aName, eBasicEventClass, &msg);
6258 atom.forget(aOnName);
6259 return msg;
6260}
6261
6262static already_AddRefed<Event> GetEventWithTarget(
6263 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
6264 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
6265 Trusted aTrusted, ErrorResult& aErrorResult) {
6266 RefPtr<Event> event =
6267 aDoc->CreateEvent(u"Events"_ns, CallerType::System, aErrorResult);
6268 if (aErrorResult.Failed()) {
6269 return nullptr;
6270 }
6271
6272 event->InitEvent(aEventName, aCanBubble, aCancelable, aComposed);
6273 event->SetTrusted(aTrusted == Trusted::eYes);
6274
6275 event->SetTarget(aTarget);
6276
6277 return event.forget();
6278}
6279
6280// static
6281nsIContent* nsContentUtils::GetEventTargetContent(
6282 nsIContent* aExplicitEventTargetContent, const WidgetEvent* aEvent) {
6283 if (!aExplicitEventTargetContent ||
6284 aExplicitEventTargetContent->IsElement() || !aEvent ||
6285 !IsForbiddenDispatchingToNonElementContent(aEvent->mMessage)) {
6286 return aExplicitEventTargetContent;
6287 }
6288 Element* const ancestorElement =
6289 aExplicitEventTargetContent->GetInclusiveFlattenedTreeAncestorElement();
6290 return ancestorElement ? ancestorElement : aExplicitEventTargetContent;
6291}
6292
6293// static
6294nsresult nsContentUtils::DispatchTrustedEvent(
6295 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
6296 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
6297 bool* aDefaultAction, SystemGroupOnly aSystemGroupOnly) {
6298 MOZ_ASSERT(!aEventName.EqualsLiteral("input") &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aEventName.EqualsLiteral("input") && !aEventName
.EqualsLiteral("beforeinput"))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aEventName.EqualsLiteral("input"
) && !aEventName.EqualsLiteral("beforeinput")))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
" (" "Use DispatchInputEvent() instead" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6300); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
") (" "Use DispatchInputEvent() instead" ")"); do { MOZ_CrashSequence
(__null, 6300); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6299 !aEventName.EqualsLiteral("beforeinput"),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aEventName.EqualsLiteral("input") && !aEventName
.EqualsLiteral("beforeinput"))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aEventName.EqualsLiteral("input"
) && !aEventName.EqualsLiteral("beforeinput")))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
" (" "Use DispatchInputEvent() instead" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6300); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
") (" "Use DispatchInputEvent() instead" ")"); do { MOZ_CrashSequence
(__null, 6300); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6300 "Use DispatchInputEvent() instead")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aEventName.EqualsLiteral("input") && !aEventName
.EqualsLiteral("beforeinput"))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aEventName.EqualsLiteral("input"
) && !aEventName.EqualsLiteral("beforeinput")))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
" (" "Use DispatchInputEvent() instead" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6300); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
") (" "Use DispatchInputEvent() instead" ")"); do { MOZ_CrashSequence
(__null, 6300); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6301 return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
6302 aComposed, Trusted::eYes, aDefaultAction,
6303 ChromeOnlyDispatch::eNo, aSystemGroupOnly);
6304}
6305
6306// static
6307nsresult nsContentUtils::DispatchUntrustedEvent(
6308 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
6309 CanBubble aCanBubble, Cancelable aCancelable, bool* aDefaultAction) {
6310 return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
6311 Composed::eDefault, Trusted::eNo, aDefaultAction);
6312}
6313
6314// static
6315nsresult nsContentUtils::DispatchEvent(
6316 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
6317 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
6318 Trusted aTrusted, bool* aDefaultAction,
6319 ChromeOnlyDispatch aOnlyChromeDispatch, SystemGroupOnly aSystemGroupOnly) {
6320 if (!aDoc || !aTarget) {
6321 return NS_ERROR_INVALID_ARG;
6322 }
6323
6324 ErrorResult err;
6325 RefPtr<Event> event =
6326 GetEventWithTarget(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
6327 aComposed, aTrusted, err);
6328 if (err.Failed()) {
6329 return err.StealNSResult();
6330 }
6331 event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch =
6332 aOnlyChromeDispatch == ChromeOnlyDispatch::eYes;
6333 event->WidgetEventPtr()->mFlags.mOnlySystemGroupDispatch =
6334 aSystemGroupOnly == SystemGroupOnly::eYes;
6335
6336 // For the performance reason, aDoc may be set to a raw pointer because it's
6337 // used only before dispatching the event. Therefore, we should not use aDoc
6338 // anymore.
6339 aDoc = nullptr;
6340 bool doDefault = aTarget->DispatchEvent(*event, CallerType::System, err);
6341 if (aDefaultAction) {
6342 *aDefaultAction = doDefault;
6343 }
6344 return err.StealNSResult();
6345}
6346
6347// static
6348nsresult nsContentUtils::DispatchEvent(
6349 EventTarget* aTarget, WidgetEvent& aEvent, EventMessage aEventMessage,
6350 CanBubble aCanBubble, Cancelable aCancelable, Trusted aTrusted,
6351 bool* aDefaultAction, ChromeOnlyDispatch aOnlyChromeDispatch) {
6352 MOZ_ASSERT_IF(aOnlyChromeDispatch == ChromeOnlyDispatch::eYes,do { if (aOnlyChromeDispatch == ChromeOnlyDispatch::eYes) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(aTrusted == Trusted::eYes)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aTrusted == Trusted::eYes)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aTrusted == Trusted::eYes"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6353); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aTrusted == Trusted::eYes" ")"); do { MOZ_CrashSequence
(__null, 6353); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
6353 aTrusted == Trusted::eYes)do { if (aOnlyChromeDispatch == ChromeOnlyDispatch::eYes) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(aTrusted == Trusted::eYes)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aTrusted == Trusted::eYes)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("aTrusted == Trusted::eYes"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6353); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aTrusted == Trusted::eYes" ")"); do { MOZ_CrashSequence
(__null, 6353); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
6354
6355 aEvent.mSpecifiedEventType = GetEventTypeFromMessage(aEventMessage);
6356 aEvent.SetDefaultComposed();
6357 aEvent.SetDefaultComposedInNativeAnonymousContent();
6358
6359 aEvent.mFlags.mBubbles = aCanBubble == CanBubble::eYes;
6360 aEvent.mFlags.mCancelable = aCancelable == Cancelable::eYes;
6361 aEvent.mFlags.mOnlyChromeDispatch =
6362 aOnlyChromeDispatch == ChromeOnlyDispatch::eYes;
6363
6364 aEvent.mTarget = aTarget;
6365
6366 nsEventStatus status = nsEventStatus_eIgnore;
6367 nsresult rv = EventDispatcher::DispatchDOMEvent(aTarget, &aEvent, nullptr,
6368 nullptr, &status);
6369 if (aDefaultAction) {
6370 *aDefaultAction = (status != nsEventStatus_eConsumeNoDefault);
6371 }
6372 return rv;
6373}
6374
6375// static
6376nsresult nsContentUtils::DispatchInputEvent(Element* aEventTarget) {
6377 return DispatchInputEvent(aEventTarget, mozilla::eEditorInput,
6378 mozilla::EditorInputType::eUnknown, nullptr,
6379 InputEventOptions());
6380}
6381
6382// static
6383nsresult nsContentUtils::DispatchInputEvent(
6384 Element* aEventTargetElement, EventMessage aEventMessage,
6385 EditorInputType aEditorInputType, EditorBase* aEditorBase,
6386 InputEventOptions&& aOptions, nsEventStatus* aEventStatus /* = nullptr */) {
6387 MOZ_ASSERT(aEventMessage == eEditorInput ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6388); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput"
")"); do { MOZ_CrashSequence(__null, 6388); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6388 aEventMessage == eEditorBeforeInput)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6388); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput"
")"); do { MOZ_CrashSequence(__null, 6388); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6389
6390 if (NS_WARN_IF(!aEventTargetElement)NS_warn_if_impl(!aEventTargetElement, "!aEventTargetElement",
"/root/firefox-clang/dom/base/nsContentUtils.cpp", 6390)
) {
6391 return NS_ERROR_INVALID_ARG;
6392 }
6393
6394 // If this is called from editor, the instance should be set to aEditorBase.
6395 // Otherwise, we need to look for an editor for aEventTargetElement.
6396 // However, we don't need to do it for HTMLEditor since nobody shouldn't
6397 // dispatch "beforeinput" nor "input" event for HTMLEditor except HTMLEditor
6398 // itself.
6399 bool useInputEvent = false;
6400 if (aEditorBase) {
6401 useInputEvent = true;
6402 } else if (const HTMLTextAreaElement* const textAreaElement =
6403 HTMLTextAreaElement::FromNode(aEventTargetElement)) {
6404 aEditorBase = textAreaElement->GetExtantTextEditor();
6405 useInputEvent = true;
6406 } else if (const HTMLInputElement* const inputElement =
6407 HTMLInputElement::FromNode(aEventTargetElement)) {
6408 if (inputElement->IsInputEventTarget()) {
6409 aEditorBase = inputElement->GetExtantTextEditor();
6410 useInputEvent = true;
6411 }
6412 }
6413#ifdef DEBUG1
6414 else {
6415 MOZ_ASSERT(!aEventTargetElement->IsTextControlElement(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aEventTargetElement->IsTextControlElement())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aEventTargetElement->IsTextControlElement()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!aEventTargetElement->IsTextControlElement()"
" (" "The event target may have editor, but we've not known it yet."
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6416
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventTargetElement->IsTextControlElement()"
") (" "The event target may have editor, but we've not known it yet."
")"); do { MOZ_CrashSequence(__null, 6416); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6416 "The event target may have editor, but we've not known it yet.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aEventTargetElement->IsTextControlElement())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aEventTargetElement->IsTextControlElement()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!aEventTargetElement->IsTextControlElement()"
" (" "The event target may have editor, but we've not known it yet."
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6416
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventTargetElement->IsTextControlElement()"
") (" "The event target may have editor, but we've not known it yet."
")"); do { MOZ_CrashSequence(__null, 6416); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6417 }
6418#endif // #ifdef DEBUG
6419
6420 if (!useInputEvent) {
6421 MOZ_ASSERT(aEventMessage == eEditorInput)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEventMessage == eEditorInput)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aEventMessage == eEditorInput
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aEventMessage == eEditorInput", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6421); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEventMessage == eEditorInput"
")"); do { MOZ_CrashSequence(__null, 6421); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6422 MOZ_ASSERT(aEditorInputType == EditorInputType::eUnknown)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEditorInputType == EditorInputType::eUnknown)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aEditorInputType == EditorInputType::eUnknown))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("aEditorInputType == EditorInputType::eUnknown"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6422); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eUnknown"
")"); do { MOZ_CrashSequence(__null, 6422); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6423 MOZ_ASSERT(!aOptions.mNeverCancelable)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aOptions.mNeverCancelable)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aOptions.mNeverCancelable))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aOptions.mNeverCancelable"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6423); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable" ")"); do { MOZ_CrashSequence
(__null, 6423); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6424 // Dispatch "input" event with Event instance.
6425 WidgetEvent widgetEvent(true, eUnidentifiedEvent);
6426 widgetEvent.mSpecifiedEventType = nsGkAtoms::oninput;
6427 widgetEvent.mFlags.mCancelable = false;
6428 widgetEvent.mFlags.mComposed = true;
6429 MOZ_LOG(gInputEventLog, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gInputEventLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s, safe?=%s, aEditorBase=%p, aEventTargetElement=%s"
, ToChar(widgetEvent.mMessage), YesOrNo(nsContentUtils::IsSafeToRunScript
()), aEditorBase, ToString(RefPtr{aEventTargetElement}).c_str
()); } } while (0)
6430 ("Dispatching %s, safe?=%s, aEditorBase=%p, aEventTargetElement=%s",do { const ::mozilla::LogModule* moz_real_module = gInputEventLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s, safe?=%s, aEditorBase=%p, aEventTargetElement=%s"
, ToChar(widgetEvent.mMessage), YesOrNo(nsContentUtils::IsSafeToRunScript
()), aEditorBase, ToString(RefPtr{aEventTargetElement}).c_str
()); } } while (0)
6431 ToChar(widgetEvent.mMessage),do { const ::mozilla::LogModule* moz_real_module = gInputEventLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s, safe?=%s, aEditorBase=%p, aEventTargetElement=%s"
, ToChar(widgetEvent.mMessage), YesOrNo(nsContentUtils::IsSafeToRunScript
()), aEditorBase, ToString(RefPtr{aEventTargetElement}).c_str
()); } } while (0)
6432 YesOrNo(nsContentUtils::IsSafeToRunScript()), aEditorBase,do { const ::mozilla::LogModule* moz_real_module = gInputEventLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s, safe?=%s, aEditorBase=%p, aEventTargetElement=%s"
, ToChar(widgetEvent.mMessage), YesOrNo(nsContentUtils::IsSafeToRunScript
()), aEditorBase, ToString(RefPtr{aEventTargetElement}).c_str
()); } } while (0)
6433 ToString(RefPtr{aEventTargetElement}).c_str()))do { const ::mozilla::LogModule* moz_real_module = gInputEventLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s, safe?=%s, aEditorBase=%p, aEventTargetElement=%s"
, ToChar(widgetEvent.mMessage), YesOrNo(nsContentUtils::IsSafeToRunScript
()), aEditorBase, ToString(RefPtr{aEventTargetElement}).c_str
()); } } while (0)
;
6434 return AsyncEventDispatcher::RunDOMEventWhenSafe(*aEventTargetElement,
6435 widgetEvent, aEventStatus);
6436 }
6437
6438 MOZ_ASSERT_IF(aEventMessage != eEditorBeforeInput,do { if (aEventMessage != eEditorBeforeInput) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!aOptions
.mNeverCancelable)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aOptions.mNeverCancelable))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aOptions.mNeverCancelable"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6439); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable" ")"); do { MOZ_CrashSequence
(__null, 6439); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
6439 !aOptions.mNeverCancelable)do { if (aEventMessage != eEditorBeforeInput) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!aOptions
.mNeverCancelable)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aOptions.mNeverCancelable))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aOptions.mNeverCancelable"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6439); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable" ")"); do { MOZ_CrashSequence
(__null, 6439); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
6440 MOZ_ASSERT_IF(do { if (aEventMessage == eEditorBeforeInput && aOptions
.mNeverCancelable) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(aEditorInputType == EditorInputType::eInsertReplacementText
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aEditorInputType == EditorInputType::eInsertReplacementText
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aEditorInputType == EditorInputType::eInsertReplacementText"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6442); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText"
")"); do { MOZ_CrashSequence(__null, 6442); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
6441 aEventMessage == eEditorBeforeInput && aOptions.mNeverCancelable,do { if (aEventMessage == eEditorBeforeInput && aOptions
.mNeverCancelable) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(aEditorInputType == EditorInputType::eInsertReplacementText
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aEditorInputType == EditorInputType::eInsertReplacementText
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aEditorInputType == EditorInputType::eInsertReplacementText"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6442); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText"
")"); do { MOZ_CrashSequence(__null, 6442); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
6442 aEditorInputType == EditorInputType::eInsertReplacementText)do { if (aEventMessage == eEditorBeforeInput && aOptions
.mNeverCancelable) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(aEditorInputType == EditorInputType::eInsertReplacementText
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aEditorInputType == EditorInputType::eInsertReplacementText
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aEditorInputType == EditorInputType::eInsertReplacementText"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6442); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText"
")"); do { MOZ_CrashSequence(__null, 6442); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6443
6444 nsCOMPtr<nsIWidget> widget;
6445 if (aEditorBase) {
6446 widget = aEditorBase->GetWidget();
6447 if (NS_WARN_IF(!widget)NS_warn_if_impl(!widget, "!widget", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6447)
) {
6448 return NS_ERROR_FAILURE;
6449 }
6450 } else {
6451 Document* document = aEventTargetElement->OwnerDoc();
6452 if (NS_WARN_IF(!document)NS_warn_if_impl(!document, "!document", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6452)
) {
6453 return NS_ERROR_FAILURE;
6454 }
6455 // If we're running xpcshell tests, we fail to get presShell here.
6456 // Even in such case, we need to dispatch "input" event without widget.
6457 PresShell* presShell = document->GetPresShell();
6458 if (presShell) {
6459 nsPresContext* presContext = presShell->GetPresContext();
6460 if (NS_WARN_IF(!presContext)NS_warn_if_impl(!presContext, "!presContext", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6460)
) {
6461 return NS_ERROR_FAILURE;
6462 }
6463 widget = presContext->GetRootWidget();
6464 if (NS_WARN_IF(!widget)NS_warn_if_impl(!widget, "!widget", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6464)
) {
6465 return NS_ERROR_FAILURE;
6466 }
6467 }
6468 }
6469
6470 // Dispatch "input" event with InputEvent instance.
6471 InternalEditorInputEvent inputEvent(true, aEventMessage, widget);
6472
6473 inputEvent.mFlags.mCancelable =
6474 !aOptions.mNeverCancelable && aEventMessage == eEditorBeforeInput &&
6475 IsCancelableBeforeInputEvent(aEditorInputType);
6476 MOZ_ASSERT(!inputEvent.mFlags.mCancelable || aEventStatus)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!inputEvent.mFlags.mCancelable || aEventStatus)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!inputEvent.mFlags.mCancelable || aEventStatus))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!inputEvent.mFlags.mCancelable || aEventStatus"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6476); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!inputEvent.mFlags.mCancelable || aEventStatus"
")"); do { MOZ_CrashSequence(__null, 6476); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6477
6478 // If there is an editor, set isComposing to true when it has composition.
6479 // Note that EditorBase::IsIMEComposing() may return false even when we
6480 // need to set it to true.
6481 // Otherwise, i.e., editor hasn't been created for the element yet,
6482 // we should set isComposing to false since the element can never has
6483 // composition without editor.
6484 inputEvent.mIsComposing = aEditorBase && aEditorBase->GetComposition();
6485
6486 if (!aEditorBase || aEditorBase->IsTextEditor()) {
6487 if (IsDataAvailableOnTextEditor(aEditorInputType)) {
6488 inputEvent.mData = std::move(aOptions.mData);
6489 MOZ_ASSERT(!inputEvent.mData.IsVoid(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!inputEvent.mData.IsVoid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!inputEvent.mData.IsVoid()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!inputEvent.mData.IsVoid()"
" (" "inputEvent.mData shouldn't be void" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6490); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { MOZ_CrashSequence
(__null, 6490); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6490 "inputEvent.mData shouldn't be void")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!inputEvent.mData.IsVoid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!inputEvent.mData.IsVoid()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!inputEvent.mData.IsVoid()"
" (" "inputEvent.mData shouldn't be void" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6490); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { MOZ_CrashSequence
(__null, 6490); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6491 }
6492#ifdef DEBUG1
6493 else {
6494 MOZ_ASSERT(inputEvent.mData.IsVoid(), "inputEvent.mData should be void")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(inputEvent.mData.IsVoid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(inputEvent.mData.IsVoid())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("inputEvent.mData.IsVoid()"
" (" "inputEvent.mData should be void" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6494); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mData.IsVoid()"
") (" "inputEvent.mData should be void" ")"); do { MOZ_CrashSequence
(__null, 6494); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6495 }
6496#endif // #ifdef DEBUG
6497 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aOptions.mTargetRanges.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aOptions.mTargetRanges.IsEmpty
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aOptions.mTargetRanges.IsEmpty()" " (" "Target ranges for <input> and <textarea> should always be empty"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6499
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges for <input> and <textarea> should always be empty"
")"); do { MOZ_CrashSequence(__null, 6499); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6498 aOptions.mTargetRanges.IsEmpty(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aOptions.mTargetRanges.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aOptions.mTargetRanges.IsEmpty
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aOptions.mTargetRanges.IsEmpty()" " (" "Target ranges for <input> and <textarea> should always be empty"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6499
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges for <input> and <textarea> should always be empty"
")"); do { MOZ_CrashSequence(__null, 6499); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6499 "Target ranges for <input> and <textarea> should always be empty")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aOptions.mTargetRanges.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aOptions.mTargetRanges.IsEmpty
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aOptions.mTargetRanges.IsEmpty()" " (" "Target ranges for <input> and <textarea> should always be empty"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6499
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges for <input> and <textarea> should always be empty"
")"); do { MOZ_CrashSequence(__null, 6499); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6500 } else {
6501 MOZ_ASSERT(aEditorBase->IsHTMLEditor())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aEditorBase->IsHTMLEditor())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aEditorBase->IsHTMLEditor
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aEditorBase->IsHTMLEditor()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6501); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorBase->IsHTMLEditor()"
")"); do { MOZ_CrashSequence(__null, 6501); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6502 if (IsDataAvailableOnHTMLEditor(aEditorInputType)) {
6503 inputEvent.mData = std::move(aOptions.mData);
6504 MOZ_ASSERT(!inputEvent.mData.IsVoid(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!inputEvent.mData.IsVoid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!inputEvent.mData.IsVoid()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!inputEvent.mData.IsVoid()"
" (" "inputEvent.mData shouldn't be void" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6505); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { MOZ_CrashSequence
(__null, 6505); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6505 "inputEvent.mData shouldn't be void")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!inputEvent.mData.IsVoid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!inputEvent.mData.IsVoid()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!inputEvent.mData.IsVoid()"
" (" "inputEvent.mData shouldn't be void" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6505); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { MOZ_CrashSequence
(__null, 6505); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6506 } else {
6507 MOZ_ASSERT(inputEvent.mData.IsVoid(), "inputEvent.mData should be void")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(inputEvent.mData.IsVoid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(inputEvent.mData.IsVoid())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("inputEvent.mData.IsVoid()"
" (" "inputEvent.mData should be void" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6507); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mData.IsVoid()"
") (" "inputEvent.mData should be void" ")"); do { MOZ_CrashSequence
(__null, 6507); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6508 if (IsDataTransferAvailableOnHTMLEditor(aEditorInputType)) {
6509 inputEvent.mDataTransfer = std::move(aOptions.mDataTransfer);
6510 MOZ_ASSERT(inputEvent.mDataTransfer,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(inputEvent.mDataTransfer)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(inputEvent.mDataTransfer))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("inputEvent.mDataTransfer"
" (" "inputEvent.mDataTransfer shouldn't be nullptr" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6511); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer shouldn't be nullptr" ")"); do
{ MOZ_CrashSequence(__null, 6511); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6511 "inputEvent.mDataTransfer shouldn't be nullptr")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(inputEvent.mDataTransfer)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(inputEvent.mDataTransfer))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("inputEvent.mDataTransfer"
" (" "inputEvent.mDataTransfer shouldn't be nullptr" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6511); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer shouldn't be nullptr" ")"); do
{ MOZ_CrashSequence(__null, 6511); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6512 MOZ_ASSERT(inputEvent.mDataTransfer->IsReadOnly(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(inputEvent.mDataTransfer->IsReadOnly())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(inputEvent.mDataTransfer->IsReadOnly()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("inputEvent.mDataTransfer->IsReadOnly()"
" (" "inputEvent.mDataTransfer should be read only" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6513); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer->IsReadOnly()"
") (" "inputEvent.mDataTransfer should be read only" ")"); do
{ MOZ_CrashSequence(__null, 6513); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6513 "inputEvent.mDataTransfer should be read only")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(inputEvent.mDataTransfer->IsReadOnly())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(inputEvent.mDataTransfer->IsReadOnly()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("inputEvent.mDataTransfer->IsReadOnly()"
" (" "inputEvent.mDataTransfer should be read only" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6513); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer->IsReadOnly()"
") (" "inputEvent.mDataTransfer should be read only" ")"); do
{ MOZ_CrashSequence(__null, 6513); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6514 }
6515#ifdef DEBUG1
6516 else {
6517 MOZ_ASSERT(!inputEvent.mDataTransfer,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!inputEvent.mDataTransfer)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!inputEvent.mDataTransfer)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!inputEvent.mDataTransfer"
" (" "inputEvent.mDataTransfer should be nullptr" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6518); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer should be nullptr" ")"); do {
MOZ_CrashSequence(__null, 6518); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6518 "inputEvent.mDataTransfer should be nullptr")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!inputEvent.mDataTransfer)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!inputEvent.mDataTransfer)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!inputEvent.mDataTransfer"
" (" "inputEvent.mDataTransfer should be nullptr" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6518); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer should be nullptr" ")"); do {
MOZ_CrashSequence(__null, 6518); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6519 }
6520#endif // #ifdef DEBUG
6521 }
6522 if (aEventMessage == eEditorBeforeInput &&
6523 MayHaveTargetRangesOnHTMLEditor(aEditorInputType)) {
6524 inputEvent.mTargetRanges = std::move(aOptions.mTargetRanges);
6525 }
6526#ifdef DEBUG1
6527 else {
6528 MOZ_ASSERT(aOptions.mTargetRanges.IsEmpty(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aOptions.mTargetRanges.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aOptions.mTargetRanges.IsEmpty
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aOptions.mTargetRanges.IsEmpty()" " (" "Target ranges shouldn't be set for the dispatching event"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6529
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges shouldn't be set for the dispatching event"
")"); do { MOZ_CrashSequence(__null, 6529); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6529 "Target ranges shouldn't be set for the dispatching event")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aOptions.mTargetRanges.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aOptions.mTargetRanges.IsEmpty
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aOptions.mTargetRanges.IsEmpty()" " (" "Target ranges shouldn't be set for the dispatching event"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6529
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges shouldn't be set for the dispatching event"
")"); do { MOZ_CrashSequence(__null, 6529); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6530 }
6531#endif // #ifdef DEBUG
6532 }
6533
6534 inputEvent.mInputType = aEditorInputType;
6535
6536 // If we cannot dispatch an event right now, we cannot make it cancelable.
6537 if (!nsContentUtils::IsSafeToRunScript()) {
6538 NS_ASSERTION(do { if (!(!inputEvent.mFlags.mCancelable)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Cancelable beforeinput event dispatcher should run when it's safe"
, "!inputEvent.mFlags.mCancelable", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6540); MOZ_PretendNoReturn(); } } while (0)
6539 !inputEvent.mFlags.mCancelable,do { if (!(!inputEvent.mFlags.mCancelable)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Cancelable beforeinput event dispatcher should run when it's safe"
, "!inputEvent.mFlags.mCancelable", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6540); MOZ_PretendNoReturn(); } } while (0)
6540 "Cancelable beforeinput event dispatcher should run when it's safe")do { if (!(!inputEvent.mFlags.mCancelable)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Cancelable beforeinput event dispatcher should run when it's safe"
, "!inputEvent.mFlags.mCancelable", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6540); MOZ_PretendNoReturn(); } } while (0)
;
6541 inputEvent.mFlags.mCancelable = false;
6542 }
6543 MOZ_LOG(gInputEventLog, LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = gInputEventLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s, safe?=%s, inputType=%s, aEditorBase=%p, "
"aEventTargetElement=%s", ToChar(inputEvent.mMessage), YesOrNo
(nsContentUtils::IsSafeToRunScript()), ToString(inputEvent.mInputType
).c_str(), aEditorBase, ToString(RefPtr{aEventTargetElement})
.c_str()); } } while (0)
6544 ("Dispatching %s, safe?=%s, inputType=%s, aEditorBase=%p, "do { const ::mozilla::LogModule* moz_real_module = gInputEventLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s, safe?=%s, inputType=%s, aEditorBase=%p, "
"aEventTargetElement=%s", ToChar(inputEvent.mMessage), YesOrNo
(nsContentUtils::IsSafeToRunScript()), ToString(inputEvent.mInputType
).c_str(), aEditorBase, ToString(RefPtr{aEventTargetElement})
.c_str()); } } while (0)
6545 "aEventTargetElement=%s",do { const ::mozilla::LogModule* moz_real_module = gInputEventLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s, safe?=%s, inputType=%s, aEditorBase=%p, "
"aEventTargetElement=%s", ToChar(inputEvent.mMessage), YesOrNo
(nsContentUtils::IsSafeToRunScript()), ToString(inputEvent.mInputType
).c_str(), aEditorBase, ToString(RefPtr{aEventTargetElement})
.c_str()); } } while (0)
6546 ToChar(inputEvent.mMessage),do { const ::mozilla::LogModule* moz_real_module = gInputEventLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s, safe?=%s, inputType=%s, aEditorBase=%p, "
"aEventTargetElement=%s", ToChar(inputEvent.mMessage), YesOrNo
(nsContentUtils::IsSafeToRunScript()), ToString(inputEvent.mInputType
).c_str(), aEditorBase, ToString(RefPtr{aEventTargetElement})
.c_str()); } } while (0)
6547 YesOrNo(nsContentUtils::IsSafeToRunScript()),do { const ::mozilla::LogModule* moz_real_module = gInputEventLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s, safe?=%s, inputType=%s, aEditorBase=%p, "
"aEventTargetElement=%s", ToChar(inputEvent.mMessage), YesOrNo
(nsContentUtils::IsSafeToRunScript()), ToString(inputEvent.mInputType
).c_str(), aEditorBase, ToString(RefPtr{aEventTargetElement})
.c_str()); } } while (0)
6548 ToString(inputEvent.mInputType).c_str(), aEditorBase,do { const ::mozilla::LogModule* moz_real_module = gInputEventLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s, safe?=%s, inputType=%s, aEditorBase=%p, "
"aEventTargetElement=%s", ToChar(inputEvent.mMessage), YesOrNo
(nsContentUtils::IsSafeToRunScript()), ToString(inputEvent.mInputType
).c_str(), aEditorBase, ToString(RefPtr{aEventTargetElement})
.c_str()); } } while (0)
6549 ToString(RefPtr{aEventTargetElement}).c_str()))do { const ::mozilla::LogModule* moz_real_module = gInputEventLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Info)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Info, "Dispatching %s, safe?=%s, inputType=%s, aEditorBase=%p, "
"aEventTargetElement=%s", ToChar(inputEvent.mMessage), YesOrNo
(nsContentUtils::IsSafeToRunScript()), ToString(inputEvent.mInputType
).c_str(), aEditorBase, ToString(RefPtr{aEventTargetElement})
.c_str()); } } while (0)
;
6550 return AsyncEventDispatcher::RunDOMEventWhenSafe(*aEventTargetElement,
6551 inputEvent, aEventStatus);
6552}
6553
6554nsresult nsContentUtils::DispatchChromeEvent(
6555 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
6556 CanBubble aCanBubble, Cancelable aCancelable, bool* aDefaultAction) {
6557 if (!aDoc || !aTarget) {
6558 return NS_ERROR_INVALID_ARG;
6559 }
6560
6561 if (!aDoc->GetWindow()) {
6562 return NS_ERROR_INVALID_ARG;
6563 }
6564
6565 EventTarget* piTarget = aDoc->GetWindow()->GetParentTarget();
6566 if (!piTarget) {
6567 return NS_ERROR_INVALID_ARG;
6568 }
6569
6570 ErrorResult err;
6571 RefPtr<Event> event =
6572 GetEventWithTarget(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
6573 Composed::eDefault, Trusted::eYes, err);
6574 if (err.Failed()) {
6575 return err.StealNSResult();
6576 }
6577
6578 bool defaultActionEnabled =
6579 piTarget->DispatchEvent(*event, CallerType::System, err);
6580 if (aDefaultAction) {
6581 *aDefaultAction = defaultActionEnabled;
6582 }
6583 return err.StealNSResult();
6584}
6585
6586void nsContentUtils::RequestFrameFocus(Element& aFrameElement, bool aCanRaise,
6587 CallerType aCallerType) {
6588 RefPtr<Element> target = &aFrameElement;
6589 bool defaultAction = true;
6590 if (aCanRaise) {
6591 RefPtr<Document> doc = target->OwnerDoc();
6592 DispatchEventOnlyToChrome(doc, target, u"framefocusrequested"_ns,
6593 CanBubble::eYes, Cancelable::eYes,
6594 &defaultAction);
6595 }
6596 if (!defaultAction) {
6597 return;
6598 }
6599
6600 RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager();
6601 if (!fm) {
6602 return;
6603 }
6604
6605 uint32_t flags = nsIFocusManager::FLAG_NOSCROLL;
6606 if (aCanRaise) {
6607 flags |= nsIFocusManager::FLAG_RAISE;
6608 }
6609
6610 if (aCallerType == CallerType::NonSystem) {
6611 flags |= nsIFocusManager::FLAG_NONSYSTEMCALLER;
6612 }
6613
6614 fm->SetFocus(target, flags);
6615}
6616
6617nsresult nsContentUtils::DispatchEventOnlyToChrome(
6618 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
6619 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
6620 bool* aDefaultAction) {
6621 return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
6622 aComposed, Trusted::eYes, aDefaultAction,
6623 ChromeOnlyDispatch::eYes);
6624}
6625
6626/* static */
6627Element* nsContentUtils::MatchElementId(nsIContent* aContent,
6628 const nsAtom* aId) {
6629 for (nsIContent* cur = aContent; cur; cur = cur->GetNextNode(aContent)) {
6630 if (aId == cur->GetID()) {
6631 return cur->AsElement();
6632 }
6633 }
6634
6635 return nullptr;
6636}
6637
6638/* static */
6639Element* nsContentUtils::MatchElementId(nsIContent* aContent,
6640 const nsAString& aId) {
6641 MOZ_ASSERT(!aId.IsEmpty(), "Will match random elements")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aId.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aId.IsEmpty()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!aId.IsEmpty()"
" (" "Will match random elements" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6641); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aId.IsEmpty()"
") (" "Will match random elements" ")"); do { MOZ_CrashSequence
(__null, 6641); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6642
6643 // ID attrs are generally stored as atoms, so just atomize this up front
6644 RefPtr<nsAtom> id(NS_Atomize(aId));
6645 if (!id) {
6646 // OOM, so just bail
6647 return nullptr;
6648 }
6649
6650 return MatchElementId(aContent, id);
6651}
6652
6653/* static */
6654void nsContentUtils::RegisterShutdownObserver(nsIObserver* aObserver) {
6655 nsCOMPtr<nsIObserverService> observerService =
6656 mozilla::services::GetObserverService();
6657 if (observerService) {
6658 observerService->AddObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown",
6659 false);
6660 }
6661}
6662
6663/* static */
6664void nsContentUtils::UnregisterShutdownObserver(nsIObserver* aObserver) {
6665 nsCOMPtr<nsIObserverService> observerService =
6666 mozilla::services::GetObserverService();
6667 if (observerService) {
6668 observerService->RemoveObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown");
6669 }
6670}
6671
6672/* static */
6673bool nsContentUtils::HasNonEmptyAttr(const nsIContent* aContent,
6674 int32_t aNameSpaceID, nsAtom* aName) {
6675 static AttrArray::AttrValuesArray strings[] = {nsGkAtoms::_empty, nullptr};
6676 return aContent->IsElement() &&
6677 aContent->AsElement()->FindAttrValueIn(aNameSpaceID, aName, strings,
6678 eCaseMatters) ==
6679 AttrArray::ATTR_VALUE_NO_MATCH;
6680}
6681
6682void nsContentUtils::NotifyDevToolsOfNodeRemoval(nsINode& aRemovingNode) {
6683 // Having an explicit check here since it's an easy mistake to fall into,
6684 // and there might be existing code with problems. We'd rather be safe
6685 // than fire a chrome only event in all corner cases. We also rely on it for
6686 // nsAutoScriptBlockerSuppressNodeRemoved.
6687 if (!IsSafeToRunScript()) {
6688 // This checks that IsSafeToRunScript is true since we don't want to fire
6689 // events when that is false. We can't rely on EventDispatcher to assert
6690 // this in this situation since most of the time DevTools is not observing
6691 // the mutations, in which case we won't even attempt to dispatch events.
6692 // However this also allows for two exceptions. First off, we don't assert
6693 // if the mutation happens to native anonymous content since we never fire
6694 // mutation events on such content anyway.
6695 // Second, we don't assert if sDOMNodeRemovedSuppressCount is true since
6696 // that is a know case when we'd normally fire a mutation event, but can't
6697 // make that safe and so we suppress it at this time. Ideally this should
6698 // go away eventually.
6699 if (!aRemovingNode.IsInNativeAnonymousSubtree() &&
6700 !sDOMNodeRemovedSuppressCount) {
6701 NS_ERROR(do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Want to fire \"devtoolschildremoved\" event, but it's not safe"
, "Error", "/root/firefox-clang/dom/base/nsContentUtils.cpp",
6702); MOZ_PretendNoReturn(); } while (0)
6702 "Want to fire \"devtoolschildremoved\" event, but it's not safe")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Want to fire \"devtoolschildremoved\" event, but it's not safe"
, "Error", "/root/firefox-clang/dom/base/nsContentUtils.cpp",
6702); MOZ_PretendNoReturn(); } while (0)
;
6703 WarnScriptWasIgnored(aRemovingNode.OwnerDoc());
6704 }
6705 return;
6706 }
6707
6708 if (MOZ_UNLIKELY(aRemovingNode.DevToolsShouldBeNotifiedOfThisRemoval())(__builtin_expect(!!(aRemovingNode.DevToolsShouldBeNotifiedOfThisRemoval
()), 0))
) {
6709 const RefPtr<Document> doc = aRemovingNode.OwnerDoc();
6710 DispatchChromeEvent(doc, &aRemovingNode, u"devtoolschildremoved"_ns,
6711 CanBubble::eNo, Cancelable::eNo);
6712 }
6713}
6714
6715void nsContentUtils::AddEntryToDOMArenaTable(nsINode* aNode,
6716 DOMArena* aDOMArena) {
6717 MOZ_ASSERT_IF(sDOMArenaHashtable, !sDOMArenaHashtable->Contains(aNode))do { if (sDOMArenaHashtable) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(!sDOMArenaHashtable->
Contains(aNode))>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(!sDOMArenaHashtable->Contains
(aNode)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!sDOMArenaHashtable->Contains(aNode)", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6717); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sDOMArenaHashtable->Contains(aNode)"
")"); do { MOZ_CrashSequence(__null, 6717); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6718 MOZ_ASSERT(!aNode->HasFlag(NODE_KEEPS_DOMARENA))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aNode->HasFlag(NODE_KEEPS_DOMARENA))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!aNode->HasFlag(NODE_KEEPS_DOMARENA)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!aNode->HasFlag(NODE_KEEPS_DOMARENA)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6718); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aNode->HasFlag(NODE_KEEPS_DOMARENA)" ")"
); do { MOZ_CrashSequence(__null, 6718); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6719 if (!sDOMArenaHashtable) {
6720 sDOMArenaHashtable =
6721 new nsRefPtrHashtable<nsPtrHashKey<const nsINode>, dom::DOMArena>();
6722 }
6723 aNode->SetFlags(NODE_KEEPS_DOMARENA);
6724 sDOMArenaHashtable->InsertOrUpdate(aNode, RefPtr<DOMArena>(aDOMArena));
6725}
6726
6727DOMArena* nsContentUtils::GetEntryFromDOMArenaTable(const nsINode* aNode) {
6728 if (!sDOMArenaHashtable) {
6729 return nullptr;
6730 }
6731 return sDOMArenaHashtable->MaybeGet(aNode).valueOr(nullptr);
6732}
6733
6734already_AddRefed<DOMArena> nsContentUtils::TakeEntryFromDOMArenaTable(
6735 const nsINode* aNode) {
6736 MOZ_ASSERT(sDOMArenaHashtable->Contains(aNode))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sDOMArenaHashtable->Contains(aNode))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(sDOMArenaHashtable->Contains(aNode)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("sDOMArenaHashtable->Contains(aNode)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 6736); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sDOMArenaHashtable->Contains(aNode)" ")"
); do { MOZ_CrashSequence(__null, 6736); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6737 RefPtr<DOMArena> arena;
6738 sDOMArenaHashtable->Remove(aNode, getter_AddRefs(arena));
6739 return arena.forget();
6740}
6741
6742/* static */
6743bool nsContentUtils::IsValidNodeName(nsAtom* aLocalName, nsAtom* aPrefix,
6744 int32_t aNamespaceID) {
6745 if (aNamespaceID == kNameSpaceID_Unknown-1) {
6746 return false;
6747 }
6748
6749 if (!aPrefix) {
6750 // If the prefix is null, then either the QName must be xmlns or the
6751 // namespace must not be XMLNS.
6752 return (aLocalName == nsGkAtoms::xmlns) ==
6753 (aNamespaceID == kNameSpaceID_XMLNS1);
6754 }
6755
6756 // If the prefix is non-null then the namespace must not be null.
6757 if (aNamespaceID == kNameSpaceID_None) {
6758 return false;
6759 }
6760
6761 // If the namespace is the XMLNS namespace then the prefix must be xmlns,
6762 // but the localname must not be xmlns.
6763 if (aNamespaceID == kNameSpaceID_XMLNS1) {
6764 return aPrefix == nsGkAtoms::xmlns && aLocalName != nsGkAtoms::xmlns;
6765 }
6766
6767 // If the namespace is not the XMLNS namespace then the prefix must not be
6768 // xmlns.
6769 // If the namespace is the XML namespace then the prefix can be anything.
6770 // If the namespace is not the XML namespace then the prefix must not be xml.
6771 return aPrefix != nsGkAtoms::xmlns &&
6772 (aNamespaceID == kNameSpaceID_XML2 || aPrefix != nsGkAtoms::xml);
6773}
6774
6775already_AddRefed<DocumentFragment> nsContentUtils::CreateContextualFragment(
6776 nsINode* aContextNode, const nsAString& aFragment,
6777 bool aPreventScriptExecution,
6778 Maybe<RefPtr<CustomElementRegistry>> aCustomElementRegistry,
6779 ErrorResult& aRv) {
6780 if (!aContextNode) {
6781 aRv.Throw(NS_ERROR_INVALID_ARG);
6782 return nullptr;
6783 }
6784
6785 // If we don't have a document here, we can't get the right security context
6786 // for compiling event handlers... so just bail out.
6787 RefPtr<Document> document = aContextNode->OwnerDoc();
6788 bool isHTML = document->IsHTMLDocument();
6789
6790 if (isHTML) {
6791 RefPtr<DocumentFragment> frag = new (document->NodeInfoManager())
6792 DocumentFragment(document->NodeInfoManager());
6793
6794 Element* element = aContextNode->GetAsElementOrParentElement();
6795 if (element && !element->IsHTMLElement(nsGkAtoms::html)) {
6796 aRv = ParseFragmentHTML(
6797 aFragment, frag, element->NodeInfo()->NameAtom(),
6798 element->GetNameSpaceID(),
6799 (document->GetCompatibilityMode() == eCompatibility_NavQuirks),
6800 aPreventScriptExecution, kParseFragmentPrivilegedDefaultSanitization,
6801 std::move(aCustomElementRegistry));
6802 } else {
6803 aRv = ParseFragmentHTML(
6804 aFragment, frag, nsGkAtoms::body, kNameSpaceID_XHTML3,
6805 (document->GetCompatibilityMode() == eCompatibility_NavQuirks),
6806 aPreventScriptExecution, kParseFragmentPrivilegedDefaultSanitization,
6807 std::move(aCustomElementRegistry));
6808 }
6809
6810 return frag.forget();
6811 }
6812
6813 AutoTArray<nsString, 32> tagStack;
6814 nsAutoString uriStr, nameStr;
6815 for (Element* element : aContextNode->InclusiveAncestorsOfType<Element>()) {
6816 nsString& tagName = *tagStack.AppendElement();
6817 // It mostly doesn't actually matter what tag name we use here: XML doesn't
6818 // have parsing that depends on the open tag stack, apart from namespace
6819 // declarations. So this whole tagStack bit is just there to get the right
6820 // namespace declarations to the XML parser. That said, the parser _is_
6821 // going to create elements with the tag names we provide here, so we need
6822 // to make sure they are not names that can trigger custom element
6823 // constructors. Just make up a name that is never going to be a valid
6824 // custom element name.
6825 //
6826 // The principled way to do this would probably be to add a new FromParser
6827 // value and make sure we use it when creating the context elements, then
6828 // make sure we teach all FromParser consumers (and in particular the custom
6829 // element code) about it as needed. But right now the XML parser never
6830 // actually uses FromParser values other than NOT_FROM_PARSER, and changing
6831 // that is pretty complicated.
6832 tagName.AssignLiteral("notacustomelement");
6833
6834 // see if we need to add xmlns declarations
6835 uint32_t count = element->GetAttrCount();
6836 bool setDefaultNamespace = false;
6837 if (count > 0) {
6838 uint32_t index;
6839
6840 for (index = 0; index < count; index++) {
6841 const BorrowedAttrInfo info = element->GetAttrInfoAt(index);
6842 const nsAttrName* name = info.mName;
6843 if (name->NamespaceEquals(kNameSpaceID_XMLNS1)) {
6844 info.mValue->ToString(uriStr);
6845
6846 tagName.AppendLiteral(" xmlns"); // space important
6847 if (name->GetPrefix()) {
6848 tagName.Append(char16_t(':'));
6849 name->LocalName()->ToString(nameStr);
6850 tagName.Append(nameStr);
6851 } else {
6852 setDefaultNamespace = true;
6853 }
6854 tagName.AppendLiteral(R"(=")");
6855 if (!nsXMLContentSerializer::
6856 AppendAndTranslateEntitiesInXMLAttributeValue(uriStr,
6857 tagName)) {
6858 aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
6859 return nullptr;
6860 }
6861 tagName.Append('"');
6862 }
6863 }
6864 }
6865
6866 if (!setDefaultNamespace) {
6867 mozilla::dom::NodeInfo* info = element->NodeInfo();
6868 if (!info->GetPrefixAtom() && info->NamespaceID() != kNameSpaceID_None) {
6869 // We have no namespace prefix, but have a namespace ID. Push
6870 // default namespace attr in, so that our kids will be in our
6871 // namespace.
6872 info->GetNamespaceURI(uriStr);
6873 tagName.AppendLiteral(R"( xmlns=")");
6874 if (!nsXMLContentSerializer::
6875 AppendAndTranslateEntitiesInXMLAttributeValue(uriStr,
6876 tagName)) {
6877 aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
6878 return nullptr;
6879 }
6880 tagName.Append('"');
6881 }
6882 }
6883 }
6884
6885 RefPtr<DocumentFragment> frag;
6886 aRv = ParseFragmentXML(aFragment, document, tagStack, aPreventScriptExecution,
6887 kParseFragmentPrivilegedDefaultSanitization,
6888 getter_AddRefs(frag));
6889 return frag.forget();
6890}
6891
6892/* static */
6893void nsContentUtils::DropFragmentParsers() {
6894 NS_IF_RELEASE(sHTMLFragmentParser)do { if (sHTMLFragmentParser) { (sHTMLFragmentParser)->Release
(); (sHTMLFragmentParser) = 0; } } while (0)
;
6895 NS_IF_RELEASE(sXMLFragmentParser)do { if (sXMLFragmentParser) { (sXMLFragmentParser)->Release
(); (sXMLFragmentParser) = 0; } } while (0)
;
6896 NS_IF_RELEASE(sXMLFragmentSink)do { if (sXMLFragmentSink) { (sXMLFragmentSink)->Release()
; (sXMLFragmentSink) = 0; } } while (0)
;
6897}
6898
6899/* static */
6900void nsContentUtils::XPCOMShutdown() { nsContentUtils::DropFragmentParsers(); }
6901
6902// https://wicg.github.io/sanitizer-api/#set-and-filter-html
6903static void SetAndFilterHTML(
6904 FragmentOrElement* aTarget, Element* aContext, const nsAString& aHTML,
6905 const OwningSanitizerOrSanitizerConfigOrSanitizerPresets& aSanitizerOptions,
6906 nsContentUtils::SanitizerMode aSanitizerMode, ErrorResult& aError) {
6907 const bool safe = aSanitizerMode == nsContentUtils::SanitizerMode::Safe;
6908 const RefPtr<Document> doc = aTarget->OwnerDoc();
6909
6910 // Step 1. If safe and contextElement’s local name is "script" and
6911 // contextElement’s namespace is the HTML namespace or the SVG namespace, then
6912 // return.
6913 if (safe && (aContext->IsHTMLElement(nsGkAtoms::script) ||
6914 aContext->IsSVGElement(nsGkAtoms::script))) {
6915 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "DOM"_ns, doc,
6916 PropertiesFile::DOM_PROPERTIES,
6917 "SetHTMLScript");
6918 return;
6919 }
6920
6921 // Step 2. Let sanitizer be the result of calling get a sanitizer instance
6922 // from options with options and safe.
6923 nsCOMPtr<nsPIDOMWindowInner> window =
6924 do_QueryInterface(aTarget->GetRelevantGlobal());
6925 if (!window) {
6926 aError.ThrowInvalidStateError("Missing owner global.");
6927 return;
6928 }
6929 RefPtr<Sanitizer> sanitizer =
6930 Sanitizer::GetInstance(window, aSanitizerOptions, safe, aError);
6931 if (aError.Failed()) {
6932 return;
6933 }
6934
6935 aTarget->NotifyDevToolsOfRemovalsOfChildren();
6936
6937 // Needed when innerHTML is used in combination with contenteditable
6938 mozAutoDocUpdate updateBatch(doc, true);
6939
6940 // Remove childnodes.
6941 nsAutoMutationBatch mb(aTarget, true, false);
6942 aTarget->RemoveAllChildren(true);
6943 mb.RemovalDone();
6944
6945 nsAutoScriptLoaderDisabler sld(doc);
6946
6947 // Step 3. Let newChildren be the result of the HTML fragment parsing
6948 // algorithm steps given contextElement, html, and true.
6949 // Step 4. Let fragment be a new DocumentFragment whose node document is
6950 // contextElement’s node document.
6951 // Step 5. For each node in newChildren, append node to fragment.
6952
6953 // We MUST NOT cause any requests during parsing, so we'll
6954 // create an inert Document and parse into a new DocumentFragment.
6955
6956 RefPtr<Document> inertDoc = nsContentUtils::CreateInertHTMLDocument(doc);
6957 if (!inertDoc) {
6958 aError = NS_ERROR_FAILURE;
6959 return;
6960 }
6961
6962 RefPtr<DocumentFragment> fragment = new (inertDoc->NodeInfoManager())
6963 DocumentFragment(inertDoc->NodeInfoManager());
6964
6965 nsAtom* contextLocalName = aContext->NodeInfo()->NameAtom();
6966 int32_t contextNameSpaceID = aContext->GetNameSpaceID();
6967 int32_t flags =
6968 safe ? nsContentUtils::kParseFragmentNoSanitization
6969 : nsContentUtils::kParseFragmentPrivilegedDefaultSanitization;
6970
6971 const bool sanitizeWhileParsing =
6972 StaticPrefs::dom_security_sanitizer_while_parsing();
6973
6974 aError = nsContentUtils::ParseFragmentHTML(
6975 aHTML, fragment, contextLocalName, contextNameSpaceID,
6976 /* aQuirks */ false, /* aPreventScriptExecution */ true, flags,
6977 mozilla::Nothing(), sanitizeWhileParsing ? sanitizer.get() : nullptr,
6978 aSanitizerMode);
6979 if (aError.Failed()) {
6980 return;
6981 }
6982
6983 // Suppress assertion about node removal mutation events that can't have
6984 // listeners anyway, because no one has had the chance to register
6985 // mutation listeners on the fragment that comes from the parser.
6986 nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
6987
6988 if (!sanitizeWhileParsing) {
6989 // Step 6. Run sanitize on fragment using sanitizer and safe.
6990 sanitizer->Sanitize(fragment, safe, aError);
6991 if (aError.Failed()) {
6992 return;
6993 }
6994 }
6995
6996 // Step 7. Replace all with fragment within target.
6997 aTarget->AppendChild(*fragment, aError);
6998 if (aError.Failed()) {
6999 return;
7000 }
7001
7002 mb.NodesAdded();
7003}
7004
7005/* static */
7006void nsContentUtils::SetHTML(FragmentOrElement* aTarget, Element* aContext,
7007 const nsAString& aHTML,
7008 const SetHTMLOptions& aOptions,
7009 ErrorResult& aError) {
7010 SetAndFilterHTML(aTarget, aContext, aHTML, aOptions.mSanitizer,
7011 SanitizerMode::Safe, aError);
7012}
7013
7014/* https://html.spec.whatwg.org/#unsafely-set-html */
7015/* https://html.spec.whatwg.org/#dom-shadowroot-sethtmlunsafe */
7016/* https://html.spec.whatwg.org/#dom-element-sethtmlunsafe */
7017/* static */
7018void nsContentUtils::SetHTMLUnsafe(
7019 FragmentOrElement* aTarget, Element* aContext,
7020 const TrustedHTMLOrString& aSource, const SetHTMLUnsafeOptions& aOptions,
7021 bool aIsShadowRoot, nsIPrincipal* aSubjectPrincipal, ErrorResult& aError) {
7022 // Element's setHTMLUnsafe() step 1 / ShadowRoot's setHTMLUnsafe() step 1.
7023 // "Let compliantHTML be the result of invoking the get trusted type compliant
7024 // string algorithm with TrustedHTML, this's relevant global object, html,
7025 // «Element setHTMLUnsafe» or «ShadowRoot setHTMLUnsafe», and «script»."
7026 constexpr nsLiteralString elementSink = u"Element setHTMLUnsafe"_ns;
7027 constexpr nsLiteralString shadowRootSink = u"ShadowRoot setHTMLUnsafe"_ns;
7028 // Bug 2072122: Trusted Types readiness experiment only, to be removed.
7029 aTarget->OwnerDoc()->RecordTrustedTypesHTMLSink(aSource.IsTrustedHTML());
7030 Maybe<nsAutoString> compliantStringHolder;
7031 const nsAString* compliantString =
7032 TrustedTypeUtils::GetTrustedTypesCompliantString(
7033 aSource, aIsShadowRoot ? shadowRootSink : elementSink,
7034 kTrustedTypesOnlySinkGroup, *aContext, aSubjectPrincipal,
7035 compliantStringHolder, aError);
7036 if (aError.Failed()) {
7037 return;
7038 }
7039
7040 // Fallback to the more optimized code below without a sanitizer.
7041 if (aOptions.mSanitizer.WasPassed()) {
7042 return SetAndFilterHTML(aTarget, aContext, *compliantString,
7043 aOptions.mSanitizer.Value(), SanitizerMode::Unsafe,
7044 aError);
7045 }
7046
7047 RefPtr<DocumentFragment> fragment;
7048 {
7049 MOZ_ASSERT(!sFragmentParsingActive,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sFragmentParsingActive)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!sFragmentParsingActive))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!sFragmentParsingActive"
" (" "Re-entrant fragment parsing attempted." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 7050); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sFragmentParsingActive"
") (" "Re-entrant fragment parsing attempted." ")"); do { MOZ_CrashSequence
(__null, 7050); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
7050 "Re-entrant fragment parsing attempted.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sFragmentParsingActive)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!sFragmentParsingActive))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!sFragmentParsingActive"
" (" "Re-entrant fragment parsing attempted." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 7050); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sFragmentParsingActive"
") (" "Re-entrant fragment parsing attempted." ")"); do { MOZ_CrashSequence
(__null, 7050); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7051 mozilla::AutoRestore<bool> guard(sFragmentParsingActive);
7052 sFragmentParsingActive = true;
7053 if (!sHTMLFragmentParser) {
7054 NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef(
)
;
7055 // Now sHTMLFragmentParser owns the object
7056 }
7057
7058 nsAtom* contextLocalName = aContext->NodeInfo()->NameAtom();
7059 int32_t contextNameSpaceID = aContext->GetNameSpaceID();
7060
7061 // https://html.spec.whatwg.org/#html-fragment-parsing-algorithm
7062 // 11. Let root be the result of creating an element given document,
7063 // 'html', the HTML namespace, null, null, false, and context's
7064 // custom element registry.
7065 Maybe<RefPtr<CustomElementRegistry>> customElementRegistry;
7066 if (StaticPrefs::dom_scoped_custom_element_registries_enabled()) {
7067 customElementRegistry.emplace(aContext->GetCustomElementRegistry());
7068 }
7069
7070 RefPtr<Document> doc = aTarget->OwnerDoc();
7071 fragment = doc->CreateDocumentFragment();
7072
7073 // XXX: Steps 1-3 are performed together by ParseFragment, which parses
7074 // directly into the DocumentFragment.
7075 nsresult rv = sHTMLFragmentParser->ParseFragment(
7076 *compliantString, fragment, contextLocalName, contextNameSpaceID,
7077 fragment->OwnerDoc()->GetCompatibilityMode() ==
7078 eCompatibility_NavQuirks,
7079 true, true, std::move(customElementRegistry));
7080 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7081 NS_WARNING("Failed to parse fragment for SetHTMLUnsafe")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to parse fragment for SetHTMLUnsafe"
, nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp",
7081)
;
7082 }
7083 }
7084
7085 // Step 4. "Replace all with fragment within target."
7086 aTarget->ReplaceChildren(fragment, IgnoreErrors());
7087}
7088
7089// We sanitize if the fragment occurs in a system privileged
7090// context, an about: page, or if there are explicit sanitization flags.
7091// Please note that about:blank and about:srcdoc inherit the security
7092// context from the embedding context and hence are not loaded using
7093// an about: scheme principal.
7094// static
7095bool nsContentUtils::ShouldSanitizeFragment(nsIPrincipal* aPrincipal,
7096 int32_t aFlags) {
7097 // We don't need to sanitize for setHTML(), which uses
7098 // kParseFragmentNoSanitization.
7099 if (aFlags == nsContentUtils::kParseFragmentNoSanitization) {
7100 return false;
7101 }
7102
7103 if (aFlags >= 0) {
7104 return true;
7105 }
7106
7107 MOZ_ASSERT(aFlags ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7108); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization"
")"); do { MOZ_CrashSequence(__null, 7108); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7108 nsContentUtils::kParseFragmentPrivilegedDefaultSanitization)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7108); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization"
")"); do { MOZ_CrashSequence(__null, 7108); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7109 return aPrincipal->IsSystemPrincipal() || aPrincipal->SchemeIs("about");
7110}
7111
7112// Helper function to compuate Sanitization Flags for ParseFramentHTML/XML
7113uint32_t ComputeSanitizationFlags(nsIPrincipal* aPrincipal, int32_t aFlags) {
7114 MOZ_ASSERT(aFlags ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization
|| aFlags >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization
|| aFlags >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7116); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0"
")"); do { MOZ_CrashSequence(__null, 7116); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7115 nsContentUtils::kParseFragmentPrivilegedDefaultSanitization ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization
|| aFlags >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization
|| aFlags >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7116); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0"
")"); do { MOZ_CrashSequence(__null, 7116); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7116 aFlags >= 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization
|| aFlags >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization
|| aFlags >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7116); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0"
")"); do { MOZ_CrashSequence(__null, 7116); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7117
7118 if (aPrincipal->IsSystemPrincipal() || aPrincipal->SchemeIs("about")) {
7119 if (aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization) {
7120 // If this is a chrome-privileged document and no explicit flags
7121 // were passed, then use these sanitization flags.
7122 return nsIParserUtils::SanitizerAllowStyle |
7123 nsIParserUtils::SanitizerAllowComments |
7124 // Don't drop forms in about: to avoid breaking existing users
7125 (aPrincipal->IsSystemPrincipal()
7126 ? nsIParserUtils::SanitizerDropForms
7127 : 0) |
7128 nsIParserUtils::SanitizerLogRemovals;
7129 }
7130
7131 // If the caller explicitly passes flags, then we use those
7132 // flags but additionally drop forms.
7133 return aFlags | nsIParserUtils::SanitizerDropForms;
7134 }
7135
7136 if (aFlags >= 0) {
7137 // aFlags by default is -1 and is only ever non equal to -1 if the
7138 // caller of ParseFragmentHTML/ParseFragmentXML is
7139 // ParserUtils::ParseFragment(). Only in that case we should use
7140 // the sanitization flags passed within aFlags.
7141 return aFlags;
7142 }
7143
7144 MOZ_ASSERT_UNREACHABLE("We should have explicit flags")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: "
"We should have explicit flags" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 7144); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "We should have explicit flags" ")"
); do { MOZ_CrashSequence(__null, 7144); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7145 return 0;
7146}
7147
7148/* https://html.spec.whatwg.org/#html-fragment-parsing-algorithm */
7149/* static */
7150nsresult nsContentUtils::ParseFragmentHTML(
7151 const nsAString& aSourceBuffer, nsIContent* aTargetNode,
7152 nsAtom* aContextLocalName, int32_t aContextNamespace, bool aQuirks,
7153 bool aPreventScriptExecution, int32_t aFlags,
7154 mozilla::Maybe<RefPtr<mozilla::dom::CustomElementRegistry>>
7155 aCustomElementRegistry,
7156 Sanitizer* aSanitizer, SanitizerMode aSanitizerMode) {
7157 MOZ_ASSERT(!aSanitizer ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7158); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing()"
")"); do { MOZ_CrashSequence(__null, 7158); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7158 StaticPrefs::dom_security_sanitizer_while_parsing())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7158); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing()"
")"); do { MOZ_CrashSequence(__null, 7158); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7159 if (nsContentUtils::sFragmentParsingActive) {
7160 MOZ_ASSERT_UNREACHABLE("Re-entrant fragment parsing attempted.")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: "
"Re-entrant fragment parsing attempted." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 7160); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted."
")"); do { MOZ_CrashSequence(__null, 7160); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7161 return NS_ERROR_DOM_INVALID_STATE_ERR;
7162 }
7163 mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
7164 nsContentUtils::sFragmentParsingActive = true;
7165 if (!sHTMLFragmentParser) {
7166 NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef(
)
;
7167 // Now sHTMLFragmentParser owns the object
7168 }
7169
7170 nsCOMPtr<nsIPrincipal> nodePrincipal = aTargetNode->NodePrincipal();
7171
7172#ifdef DEBUG1
7173 // aFlags should always be kParseFragmentPrivilegedDefaultSanitization unless
7174 // the caller of ParseFragmentHTML is ParserUtils::ParseFragment() which is
7175 // the only caller that intends sanitization. For all other callers we need to
7176 // ensure to call AuditParsingOfHTMLXMLFragments.
7177 //
7178 // For SetHTML the flag is kParseFragmentNoSanitization, because that function
7179 // already sanitizes.
7180 if (aFlags == kParseFragmentPrivilegedDefaultSanitization) {
7181 DOMSecurityMonitor::AuditParsingOfHTMLXMLFragments(nodePrincipal,
7182 aSourceBuffer);
7183 }
7184#endif
7185
7186 nsIContent* target = aTargetNode;
7187
7188 RefPtr<Document> doc = aTargetNode->OwnerDoc();
7189 RefPtr<DocumentFragment> fragment;
7190
7191 if (ShouldSanitizeFragment(nodePrincipal, aFlags)) {
7192 if (!doc->IsLoadedAsData()) {
7193 doc = nsContentUtils::CreateInertHTMLDocument(doc);
7194 if (!doc) {
7195 return NS_ERROR_FAILURE;
7196 }
7197 }
7198 fragment =
7199 new (doc->NodeInfoManager()) DocumentFragment(doc->NodeInfoManager());
7200 target = fragment;
7201 }
7202
7203 nsresult rv = sHTMLFragmentParser->ParseFragment(
7204 aSourceBuffer, target, aContextLocalName, aContextNamespace, aQuirks,
7205 aPreventScriptExecution, false, std::move(aCustomElementRegistry),
7206 aSanitizer, aSanitizerMode);
7207 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 7207); return rv; } } while (false)
;
7208
7209 if (fragment) {
7210 uint32_t sanitizationFlags =
7211 ComputeSanitizationFlags(nodePrincipal, aFlags);
7212 // Don't fire mutation events for nodes removed by the sanitizer.
7213 nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
7214 nsTreeSanitizer sanitizer(sanitizationFlags);
7215 sanitizer.Sanitize(fragment);
7216
7217 ErrorResult error;
7218 aTargetNode->AppendChild(*fragment, error);
7219 rv = error.StealNSResult();
7220 }
7221
7222 return rv;
7223}
7224
7225/* static */
7226nsresult nsContentUtils::ParseDocumentHTML(
7227 const nsAString& aSourceBuffer, Document* aTargetDocument,
7228 bool aScriptingEnabledForNoscriptParsing, Sanitizer* aSanitizer,
7229 SanitizerMode aSanitizerMode) {
7230 MOZ_ASSERT(!aSanitizer ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7231); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing()"
")"); do { MOZ_CrashSequence(__null, 7231); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7231 StaticPrefs::dom_security_sanitizer_while_parsing())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7231); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing()"
")"); do { MOZ_CrashSequence(__null, 7231); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7232 if (nsContentUtils::sFragmentParsingActive) {
7233 MOZ_ASSERT_UNREACHABLE("Re-entrant fragment parsing attempted.")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: "
"Re-entrant fragment parsing attempted." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 7233); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted."
")"); do { MOZ_CrashSequence(__null, 7233); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7234 return NS_ERROR_DOM_INVALID_STATE_ERR;
7235 }
7236 mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
7237 nsContentUtils::sFragmentParsingActive = true;
7238 if (!sHTMLFragmentParser) {
7239 NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef(
)
;
7240 // Now sHTMLFragmentParser owns the object
7241 }
7242 nsresult rv = sHTMLFragmentParser->ParseDocument(
7243 aSourceBuffer, aTargetDocument, aScriptingEnabledForNoscriptParsing,
7244 aSanitizer, aSanitizerMode);
7245 return rv;
7246}
7247
7248/* static */
7249nsresult nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer,
7250 Document* aDocument,
7251 nsTArray<nsString>& aTagStack,
7252 bool aPreventScriptExecution,
7253 int32_t aFlags,
7254 DocumentFragment** aReturn) {
7255 if (nsContentUtils::sFragmentParsingActive) {
7256 MOZ_ASSERT_UNREACHABLE("Re-entrant fragment parsing attempted.")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: "
"Re-entrant fragment parsing attempted." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 7256); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted."
")"); do { MOZ_CrashSequence(__null, 7256); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7257 return NS_ERROR_DOM_INVALID_STATE_ERR;
7258 }
7259 mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
7260 nsContentUtils::sFragmentParsingActive = true;
7261 if (!sXMLFragmentParser) {
7262 RefPtr<nsParser> parser = new nsParser();
7263 parser.forget(&sXMLFragmentParser);
7264 // sXMLFragmentParser now owns the parser
7265 }
7266 if (!sXMLFragmentSink) {
7267 NS_NewXMLFragmentContentSink(&sXMLFragmentSink);
7268 // sXMLFragmentSink now owns the sink
7269 }
7270 nsCOMPtr<nsIContentSink> contentsink = do_QueryInterface(sXMLFragmentSink);
7271 MOZ_ASSERT(contentsink, "Sink doesn't QI to nsIContentSink!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(contentsink)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(contentsink))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("contentsink" " ("
"Sink doesn't QI to nsIContentSink!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 7271); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentsink"
") (" "Sink doesn't QI to nsIContentSink!" ")"); do { MOZ_CrashSequence
(__null, 7271); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7272 sXMLFragmentParser->SetContentSink(contentsink);
7273
7274 RefPtr<Document> doc;
7275 nsCOMPtr<nsIPrincipal> nodePrincipal = aDocument->NodePrincipal();
7276
7277#ifdef DEBUG1
7278 // aFlags should always be kParseFragmentPrivilegedDefaultSanitization unless
7279 // the caller of ParseFragmentXML is ParserUtils::ParseFragment() which is the
7280 // only caller that intends sanitization. For all other callers we need to
7281 // ensure to call AuditParsingOfHTMLXMLFragments.
7282 if (aFlags == kParseFragmentPrivilegedDefaultSanitization) {
7283 DOMSecurityMonitor::AuditParsingOfHTMLXMLFragments(nodePrincipal,
7284 aSourceBuffer);
7285 }
7286#endif
7287
7288 bool shouldSanitize = ShouldSanitizeFragment(nodePrincipal, aFlags);
7289 if (shouldSanitize && !aDocument->IsLoadedAsData()) {
7290 doc = nsContentUtils::CreateInertXMLDocument(aDocument);
7291 } else {
7292 doc = aDocument;
7293 }
7294
7295 sXMLFragmentSink->SetTargetDocument(doc);
7296 sXMLFragmentSink->SetPreventScriptExecution(aPreventScriptExecution);
7297
7298 nsresult rv = sXMLFragmentParser->ParseFragment(aSourceBuffer, aTagStack);
7299 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7300 // Drop the fragment parser and sink that might be in an inconsistent state
7301 NS_IF_RELEASE(sXMLFragmentParser)do { if (sXMLFragmentParser) { (sXMLFragmentParser)->Release
(); (sXMLFragmentParser) = 0; } } while (0)
;
7302 NS_IF_RELEASE(sXMLFragmentSink)do { if (sXMLFragmentSink) { (sXMLFragmentSink)->Release()
; (sXMLFragmentSink) = 0; } } while (0)
;
7303 return rv;
7304 }
7305
7306 rv = sXMLFragmentSink->FinishFragmentParsing(aReturn);
7307
7308 sXMLFragmentParser->Reset();
7309 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 7309); return rv; } } while (false)
;
7310
7311 if (shouldSanitize) {
7312 uint32_t sanitizationFlags =
7313 ComputeSanitizationFlags(nodePrincipal, aFlags);
7314 // Don't fire mutation events for nodes removed by the sanitizer.
7315 nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
7316 nsTreeSanitizer sanitizer(sanitizationFlags);
7317 sanitizer.Sanitize(*aReturn);
7318 }
7319
7320 return rv;
7321}
7322
7323/* static */
7324nsresult nsContentUtils::ConvertToPlainText(const nsAString& aSourceBuffer,
7325 nsAString& aResultBuffer,
7326 uint32_t aFlags,
7327 uint32_t aWrapCol) {
7328 RefPtr<Document> document = nsContentUtils::CreateInertHTMLDocument(nullptr);
7329 if (!document) {
7330 return NS_ERROR_FAILURE;
7331 }
7332
7333 nsresult rv = nsContentUtils::ParseDocumentHTML(
7334 aSourceBuffer, document,
7335 !(aFlags & nsIDocumentEncoder::OutputNoScriptContent));
7336 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 7336); return rv; } } while (false)
;
7337
7338 nsCOMPtr<nsIDocumentEncoder> encoder = do_createDocumentEncoder("text/plain");
7339
7340 rv = encoder->Init(document, u"text/plain"_ns, aFlags);
7341 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 7341); return rv; } } while (false)
;
7342
7343 encoder->SetWrapColumn(aWrapCol);
7344
7345 return encoder->EncodeToString(aResultBuffer);
7346}
7347
7348static already_AddRefed<Document> CreateInertDocument(const Document* aTemplate,
7349 DocumentFlavor aFlavor) {
7350 if (aTemplate) {
7351 bool hasHad = true;
7352 nsIScriptGlobalObject* sgo = aTemplate->GetScriptHandlingObject(hasHad);
7353 NS_ENSURE_TRUE(sgo || !hasHad, nullptr)do { if ((__builtin_expect(!!(!(sgo || !hasHad)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "sgo || !hasHad" ") failed"
, nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp",
7353); return nullptr; } } while (false)
;
7354
7355 nsCOMPtr<Document> doc;
7356 nsresult rv = NS_NewDOMDocument(
7357 getter_AddRefs(doc), u""_ns, u""_ns, nullptr,
7358 aTemplate->GetDocumentURI(), aTemplate->GetDocBaseURI(),
7359 aTemplate->NodePrincipal(), LoadedAsData::AsData, sgo, aFlavor);
7360 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7361 return nullptr;
7362 }
7363 return doc.forget();
7364 }
7365 nsCOMPtr<nsIURI> uri;
7366 NS_NewURI(getter_AddRefs(uri), "about:blank"_ns);
7367 if (!uri) {
7368 return nullptr;
7369 }
7370
7371 RefPtr<NullPrincipal> nullPrincipal =
7372 NullPrincipal::CreateWithoutOriginAttributes();
7373 if (!nullPrincipal) {
7374 return nullptr;
7375 }
7376
7377 nsCOMPtr<Document> doc;
7378 nsresult rv =
7379 NS_NewDOMDocument(getter_AddRefs(doc), u""_ns, u""_ns, nullptr, uri, uri,
7380 nullPrincipal, LoadedAsData::AsData, nullptr, aFlavor);
7381 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7382 return nullptr;
7383 }
7384 return doc.forget();
7385}
7386
7387/* static */
7388already_AddRefed<Document> nsContentUtils::CreateInertXMLDocument(
7389 const Document* aTemplate) {
7390 return CreateInertDocument(aTemplate, DocumentFlavor::XML);
7391}
7392
7393/* static */
7394already_AddRefed<Document> nsContentUtils::CreateInertHTMLDocument(
7395 const Document* aTemplate) {
7396 return CreateInertDocument(aTemplate, DocumentFlavor::HTML);
7397}
7398
7399/* static */
7400nsresult nsContentUtils::SetNodeTextContent(
7401 nsIContent* aContent, const nsAString& aValue, bool aTryReuse,
7402 MutationEffectOnScript aMutationEffectOnScript) {
7403 // Optimize the common case of there being no observers
7404 if (MOZ_UNLIKELY((__builtin_expect(!!(aContent->MaybeNeedsToNotifyDevToolsOfNodeRemovalsInOwnerDoc
()), 0))
7405 aContent->MaybeNeedsToNotifyDevToolsOfNodeRemovalsInOwnerDoc())(__builtin_expect(!!(aContent->MaybeNeedsToNotifyDevToolsOfNodeRemovalsInOwnerDoc
()), 0))
) {
7406 if (aTryReuse) {
7407 bool skipFirstText = true;
7408 for (nsCOMPtr<nsINode> child = aContent->GetFirstChild();
7409 child && child->GetParentNode() == aContent;
7410 child = child->GetNextSibling()) {
7411 if (skipFirstText && child->IsText()) {
7412 skipFirstText = false;
7413 continue;
7414 }
7415 nsContentUtils::NotifyDevToolsOfNodeRemoval(*child);
7416 }
7417 } else {
7418 aContent->NotifyDevToolsOfRemovalsOfChildren();
7419 }
7420 }
7421
7422 // Might as well stick a batch around this since we're performing several
7423 // mutations.
7424 mozAutoDocUpdate updateBatch(aContent->GetComposedDoc(), true);
7425 nsAutoMutationBatch mb;
7426
7427 if (aTryReuse && !aValue.IsEmpty()) {
7428 // Let's remove nodes until we find a eTEXT.
7429 while (aContent->HasChildren()) {
7430 nsIContent* child = aContent->GetFirstChild();
7431 if (child->IsText()) {
7432 break;
7433 }
7434 aContent->RemoveChildNode(child, true, nullptr, nullptr,
7435 aMutationEffectOnScript);
7436 }
7437
7438 // If we have a node, it must be a eTEXT and we reuse it.
7439 if (aContent->HasChildren()) {
7440 nsIContent* child = aContent->GetFirstChild();
7441 ErrorResult rv;
7442 child->AsText()->SetNodeValueInternal(aValue, rv,
7443 aMutationEffectOnScript);
7444 NS_ENSURE_TRUE(!rv.Failed(), rv.StealNSResult())do { if ((__builtin_expect(!!(!(!rv.Failed())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!rv.Failed()" ") failed"
, nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp",
7444); return rv.StealNSResult(); } } while (false)
;
7445
7446 // All the following nodes, if they exist, must be deleted.
7447 while (nsIContent* lastChild = aContent->GetLastChild()) {
7448 if (lastChild == child) {
7449 break;
7450 }
7451 aContent->RemoveChildNode(lastChild, true, nullptr, nullptr,
7452 aMutationEffectOnScript);
7453 }
7454 }
7455
7456 if (aContent->HasChildren()) {
7457 return NS_OK;
7458 }
7459 } else {
7460 mb.Init(aContent, true, false);
7461 aContent->RemoveAllChildren(true);
7462 }
7463 mb.RemovalDone();
7464
7465 if (aValue.IsEmpty()) {
7466 return NS_OK;
7467 }
7468
7469 RefPtr<nsTextNode> textContent = new (aContent->NodeInfo()->NodeInfoManager())
7470 nsTextNode(aContent->NodeInfo()->NodeInfoManager());
7471
7472 textContent->SetText(aValue, true);
7473
7474 ErrorResult rv;
7475 aContent->AppendChildTo(textContent, true, rv, aMutationEffectOnScript);
7476 mb.NodesAdded();
7477 return rv.StealNSResult();
7478}
7479
7480template <typename CharT>
7481static bool AppendNodeTextContentsRecurse(const nsINode* aNode,
7482 nsTSubstring<CharT>& aResult,
7483 const fallible_t& aFallible) {
7484 for (nsIContent* child = aNode->GetFirstChild(); child;
7485 child = child->GetNextSibling()) {
7486 if (child->IsElement()) {
7487 if (!AppendNodeTextContentsRecurse(child, aResult, aFallible)) {
7488 return false;
7489 }
7490 } else if (Text* text = child->GetAsText()) {
7491 if (!text->AppendTextTo(aResult, aFallible)) {
7492 return false;
7493 }
7494 }
7495 }
7496 return true;
7497}
7498
7499template <typename CharT>
7500static bool AppendNodeTextContent(const nsINode* aNode, bool aDeep,
7501 nsTSubstring<CharT>& aResult,
7502 const fallible_t& aFallible) {
7503 if (const Text* text = aNode->GetAsText()) {
7504 return text->AppendTextTo(aResult, aFallible);
7505 }
7506 if (aDeep) {
7507 return AppendNodeTextContentsRecurse(aNode, aResult, aFallible);
7508 }
7509 for (nsIContent* child = aNode->GetFirstChild(); child;
7510 child = child->GetNextSibling()) {
7511 if (Text* text = child->GetAsText()) {
7512 bool ok = text->AppendTextTo(aResult, fallible);
7513 if (!ok) {
7514 return false;
7515 }
7516 }
7517 }
7518 return true;
7519}
7520
7521/* static */
7522bool nsContentUtils::AppendNodeTextContent(const nsINode* aNode, bool aDeep,
7523 nsAString& aResult,
7524 const fallible_t& aFallible) {
7525 return ::AppendNodeTextContent(aNode, aDeep, aResult, aFallible);
7526}
7527
7528bool nsContentUtils::AppendNodeTextContent(const nsINode* aNode, bool aDeep,
7529 nsACString& aResult,
7530 const fallible_t& aFallible) {
7531 return ::AppendNodeTextContent(aNode, aDeep, aResult, aFallible);
7532}
7533
7534bool nsContentUtils::HasNonEmptyTextContent(
7535 nsINode* aNode, TextContentDiscoverMode aDiscoverMode) {
7536 for (nsIContent* child = aNode->GetFirstChild(); child;
7537 child = child->GetNextSibling()) {
7538 if (child->IsText() && child->TextLength() > 0) {
7539 return true;
7540 }
7541
7542 if (aDiscoverMode == eRecurseIntoChildren &&
7543 HasNonEmptyTextContent(child, aDiscoverMode)) {
7544 return true;
7545 }
7546 }
7547
7548 return false;
7549}
7550
7551/* static */
7552bool nsContentUtils::IsInSameAnonymousTree(const nsINode* aNode,
7553 const nsINode* aOtherNode) {
7554 MOZ_ASSERT(aNode, "Must have a node to work with")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNode)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(aNode))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aNode" " (" "Must have a node to work with"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7554
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode" ") (" "Must have a node to work with"
")"); do { MOZ_CrashSequence(__null, 7554); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7555 MOZ_ASSERT(aOtherNode, "Must have a content to work with")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aOtherNode)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aOtherNode))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aOtherNode" " (" "Must have a content to work with"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7555
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOtherNode" ") ("
"Must have a content to work with" ")"); do { MOZ_CrashSequence
(__null, 7555); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7556
7557 const bool anon = aNode->IsInNativeAnonymousSubtree();
7558 if (anon != aOtherNode->IsInNativeAnonymousSubtree()) {
7559 return false;
7560 }
7561
7562 if (anon) {
7563 return aOtherNode->GetClosestNativeAnonymousSubtreeRoot() ==
7564 aNode->GetClosestNativeAnonymousSubtreeRoot();
7565 }
7566
7567 // FIXME: This doesn't deal with disconnected nodes whatsoever, but it didn't
7568 // use to either. Maybe that's fine.
7569 return aNode->GetContainingShadow() == aOtherNode->GetContainingShadow();
7570}
7571
7572/* static */
7573bool nsContentUtils::IsInInteractiveHTMLContent(const Element* aElement,
7574 const Element* aStop) {
7575 const Element* element = aElement;
7576 while (element && element != aStop) {
7577 if (element->IsInteractiveHTMLContent()) {
7578 return true;
7579 }
7580 element = element->GetFlattenedTreeParentElement();
7581 }
7582 return false;
7583}
7584
7585/* static */
7586void nsContentUtils::NotifyInstalledMenuKeyboardListener(bool aInstalling) {
7587 IMEStateManager::OnInstalledMenuKeyboardListener(aInstalling);
7588}
7589
7590/* static */
7591bool nsContentUtils::SchemeIs(nsIURI* aURI, const char* aScheme) {
7592 nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
7593 NS_ENSURE_TRUE(baseURI, false)do { if ((__builtin_expect(!!(!(baseURI)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "baseURI" ") failed", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7593); return
false; } } while (false)
;
7594 return baseURI->SchemeIs(aScheme);
7595}
7596
7597bool nsContentUtils::IsExpandedPrincipal(nsIPrincipal* aPrincipal) {
7598 return aPrincipal && aPrincipal->GetIsExpandedPrincipal();
7599}
7600
7601bool nsContentUtils::IsSystemOrExpandedPrincipal(nsIPrincipal* aPrincipal) {
7602 return (aPrincipal && aPrincipal->IsSystemPrincipal()) ||
7603 IsExpandedPrincipal(aPrincipal);
7604}
7605
7606nsIPrincipal* nsContentUtils::GetSystemPrincipal() {
7607 MOZ_ASSERT(IsInitialized())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsInitialized())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInitialized()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("IsInitialized()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7607); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInitialized()" ")"); do { MOZ_CrashSequence
(__null, 7607); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7608 return sSystemPrincipal;
7609}
7610
7611bool nsContentUtils::CombineResourcePrincipals(
7612 nsCOMPtr<nsIPrincipal>* aResourcePrincipal, nsIPrincipal* aExtraPrincipal) {
7613 if (!aExtraPrincipal) {
7614 return false;
7615 }
7616 if (!*aResourcePrincipal) {
7617 *aResourcePrincipal = aExtraPrincipal;
7618 return true;
7619 }
7620 if (*aResourcePrincipal == aExtraPrincipal) {
7621 return false;
7622 }
7623 bool subsumes;
7624 if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl((*aResourcePrincipal
)->Subsumes(aExtraPrincipal, &subsumes))), 1)))
7625 (*aResourcePrincipal)->Subsumes(aExtraPrincipal, &subsumes))((bool)(__builtin_expect(!!(!NS_FAILED_impl((*aResourcePrincipal
)->Subsumes(aExtraPrincipal, &subsumes))), 1)))
&&
7626 subsumes) {
7627 return false;
7628 }
7629 *aResourcePrincipal = sSystemPrincipal;
7630 return true;
7631}
7632
7633/* static */
7634void nsContentUtils::TriggerLinkClick(
7635 nsIContent* aContent, nsIURI* aLinkURI, const nsString& aTargetSpec,
7636 UserNavigationInvolvement aUserInvolvement) {
7637 MOZ_ASSERT(aLinkURI, "No link URI")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLinkURI)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLinkURI))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLinkURI" " (" "No link URI"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7637
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLinkURI" ") (" "No link URI"
")"); do { MOZ_CrashSequence(__null, 7637); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7638
7639 if (aContent->IsEditable() || !aContent->OwnerDoc()->LinkHandlingEnabled()) {
7640 return;
7641 }
7642
7643 RefPtr<nsDocShell> docShell =
7644 nsDocShell::Cast(aContent->OwnerDoc()->GetDocShell());
7645 if (!docShell) {
7646 return;
7647 }
7648
7649 // Check that this page is allowed to load this URI.
7650 nsresult proceed = NS_OK;
7651
7652 if (sSecurityManager) {
7653 uint32_t flag = static_cast<uint32_t>(nsIScriptSecurityManager::STANDARD);
7654 proceed = sSecurityManager->CheckLoadURIWithPrincipal(
7655 aContent->NodePrincipal(), aLinkURI, flag,
7656 aContent->OwnerDoc()->InnerWindowID());
7657 }
7658
7659 // Only pass off the click event if the script security manager says it's ok.
7660 // We need to rest aTargetSpec for forced downloads.
7661 if (NS_SUCCEEDED(proceed)((bool)(__builtin_expect(!!(!NS_FAILED_impl(proceed)), 1)))) {
7662 // A link/area element with a download attribute is allowed to set
7663 // a pseudo Content-Disposition header.
7664 // For security reasons we only allow websites to declare same-origin
7665 // resources as downloadable. If this check fails we will just do the normal
7666 // thing (i.e. navigate to the resource).
7667 nsAutoString fileName;
7668 if ((!aContent->IsHTMLElement(nsGkAtoms::a) &&
7669 !aContent->IsHTMLElement(nsGkAtoms::area) &&
7670 !aContent->IsSVGElement(nsGkAtoms::a) &&
7671 !(aContent->IsMathMLElement(nsGkAtoms::a) &&
7672 StaticPrefs::mathml_a_element_enabled())) ||
7673 !aContent->AsElement()->GetAttr(nsGkAtoms::download, fileName) ||
7674 NS_FAILED(aContent->NodePrincipal()->CheckMayLoad(aLinkURI, true))((bool)(__builtin_expect(!!(NS_FAILED_impl(aContent->NodePrincipal
()->CheckMayLoad(aLinkURI, true))), 0)))
) {
7675 fileName.SetIsVoid(true); // No actionable download attribute was found.
7676 }
7677
7678 nsCOMPtr<nsIPrincipal> triggeringPrincipal = aContent->NodePrincipal();
7679 nsCOMPtr<nsIPolicyContainer> policyContainer =
7680 aContent->GetPolicyContainer();
7681
7682 // Sanitize fileNames containing null characters by replacing them with
7683 // underscores.
7684 if (!fileName.IsVoid()) {
7685 fileName.ReplaceChar(char16_t(0), '_');
7686 }
7687
7688 docShell->OnLinkClick(
7689 aContent, aLinkURI, fileName.IsVoid() ? aTargetSpec : u""_ns, fileName,
7690 nullptr, nullptr, UserActivation::IsHandlingUserInput(),
7691 aUserInvolvement, triggeringPrincipal, policyContainer);
7692 }
7693}
7694
7695/* static */
7696void nsContentUtils::TriggerLinkMouseOver(nsIContent* aContent,
7697 nsIURI* aLinkURI) {
7698 MOZ_ASSERT(aLinkURI, "No link URI")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLinkURI)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLinkURI))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLinkURI" " (" "No link URI"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7698
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLinkURI" ") (" "No link URI"
")"); do { MOZ_CrashSequence(__null, 7698); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7699
7700 if (aContent->IsEditable() || !aContent->OwnerDoc()->LinkHandlingEnabled()) {
7701 return;
7702 }
7703
7704 RefPtr<nsDocShell> docShell =
7705 nsDocShell::Cast(aContent->OwnerDoc()->GetDocShell());
7706 if (!docShell) {
7707 return;
7708 }
7709
7710 docShell->OnOverLink(aContent, aLinkURI);
7711
7712 if (nsPresContext* pc = aContent->OwnerDoc()->GetPresContext()) {
7713 pc->EventStateManager()->SetLinkOverFrame(aContent->GetPrimaryFrame());
7714 }
7715}
7716
7717/* static */
7718void nsContentUtils::GetLinkLocation(Element* aElement,
7719 nsString& aLocationString) {
7720 nsCOMPtr<nsIURI> hrefURI = aElement->GetHrefURI();
7721 if (hrefURI) {
7722 nsAutoCString specUTF8;
7723 nsresult rv = hrefURI->GetSpec(specUTF8);
7724 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) CopyUTF8toUTF16(specUTF8, aLocationString);
7725 }
7726}
7727
7728/* static */
7729nsIWidget* nsContentUtils::GetTopLevelWidget(nsIWidget* aWidget) {
7730 if (!aWidget) return nullptr;
7731
7732 return aWidget->GetTopLevelWidget();
7733}
7734
7735/* static */
7736const nsDependentString nsContentUtils::GetLocalizedEllipsis() {
7737 static char16_t sBuf[4] = {0, 0, 0, 0};
7738 if (!sBuf[0]) {
7739 if (!nsContentUtils::ShouldResistFingerprinting("No context",
7740 RFPTarget::JSLocale)) {
7741 nsAutoString tmp;
7742 intl::LocaleService::GetInstance()->GetEllipsis(tmp);
7743 uint32_t len =
7744 std::min(uint32_t(tmp.Length()), uint32_t(std::size(sBuf) - 1));
7745 CopyUnicodeTo(tmp, 0, sBuf, len);
7746 }
7747 if (!sBuf[0]) {
7748 sBuf[0] = char16_t(0x2026);
7749 }
7750 }
7751 return nsDependentString(sBuf);
7752}
7753
7754/* static */
7755void nsContentUtils::AddScriptBlocker() {
7756 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7756); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 7756); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7757 if (!sScriptBlockerCount) {
7758 MOZ_ASSERT(sRunnersCountAtFirstBlocker == 0,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sRunnersCountAtFirstBlocker == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sRunnersCountAtFirstBlocker ==
0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("sRunnersCountAtFirstBlocker == 0" " (" "Should not already have a count"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7759
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sRunnersCountAtFirstBlocker == 0"
") (" "Should not already have a count" ")"); do { MOZ_CrashSequence
(__null, 7759); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
7759 "Should not already have a count")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sRunnersCountAtFirstBlocker == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sRunnersCountAtFirstBlocker ==
0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("sRunnersCountAtFirstBlocker == 0" " (" "Should not already have a count"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7759
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sRunnersCountAtFirstBlocker == 0"
") (" "Should not already have a count" ")"); do { MOZ_CrashSequence
(__null, 7759); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7760 sRunnersCountAtFirstBlocker =
7761 sBlockedScriptRunners ? sBlockedScriptRunners->Length() : 0;
7762 }
7763 ++sScriptBlockerCount;
7764}
7765
7766#ifdef DEBUG1
7767static bool sRemovingScriptBlockers = false;
7768#endif
7769
7770/* static */
7771void nsContentUtils::RemoveScriptBlocker() {
7772 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7772); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 7772); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7773 MOZ_ASSERT(!sRemovingScriptBlockers)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!sRemovingScriptBlockers)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!sRemovingScriptBlockers))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!sRemovingScriptBlockers"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7773); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!sRemovingScriptBlockers" ")"); do { MOZ_CrashSequence
(__null, 7773); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7774 NS_ASSERTION(sScriptBlockerCount != 0, "Negative script blockers")do { if (!(sScriptBlockerCount != 0)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Negative script blockers", "sScriptBlockerCount != 0", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 7774); MOZ_PretendNoReturn(); } } while (0)
;
7775 --sScriptBlockerCount;
7776 if (sScriptBlockerCount) {
7777 return;
7778 }
7779
7780 if (!sBlockedScriptRunners) {
7781 return;
7782 }
7783
7784 uint32_t firstBlocker = sRunnersCountAtFirstBlocker;
7785 uint32_t lastBlocker = sBlockedScriptRunners->Length();
7786 uint32_t originalFirstBlocker = firstBlocker;
7787 uint32_t blockersCount = lastBlocker - firstBlocker;
7788 sRunnersCountAtFirstBlocker = 0;
7789 NS_ASSERTION(firstBlocker <= lastBlocker, "bad sRunnersCountAtFirstBlocker")do { if (!(firstBlocker <= lastBlocker)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "bad sRunnersCountAtFirstBlocker", "firstBlocker <= lastBlocker"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7789); MOZ_PretendNoReturn
(); } } while (0)
;
7790
7791 while (firstBlocker < lastBlocker) {
7792 nsCOMPtr<nsIRunnable> runnable;
7793 runnable.swap((*sBlockedScriptRunners)[firstBlocker]);
7794 ++firstBlocker;
7795
7796 // Calling the runnable can reenter us
7797 {
7798 AUTO_PROFILE_FOLLOWING_RUNNABLE(runnable)mozilla::Maybe<mozilla::AutoProfileRunnable> raiiRunnableMarker
; if (profiler_thread_is_profiling_runnables()) { raiiRunnableMarker
.emplace(runnable); }
;
7799 runnable->Run();
7800 }
7801 // So can dropping the reference to the runnable
7802 runnable = nullptr;
7803
7804 NS_ASSERTION(sRunnersCountAtFirstBlocker == 0, "Bad count")do { if (!(sRunnersCountAtFirstBlocker == 0)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Bad count", "sRunnersCountAtFirstBlocker == 0"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7804); MOZ_PretendNoReturn
(); } } while (0)
;
7805 NS_ASSERTION(!sScriptBlockerCount, "This is really bad")do { if (!(!sScriptBlockerCount)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "This is really bad", "!sScriptBlockerCount", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 7805); MOZ_PretendNoReturn(); } } while (0)
;
7806 }
7807#ifdef DEBUG1
7808 AutoRestore<bool> removingScriptBlockers(sRemovingScriptBlockers);
7809 sRemovingScriptBlockers = true;
7810#endif
7811 sBlockedScriptRunners->RemoveElementsAt(originalFirstBlocker, blockersCount);
7812}
7813
7814nsAutoMicroTaskForDocument::nsAutoMicroTaskForDocument(
7815 const Document* aDocument)
7816 : mContext(aDocument && aDocument->GetInnerWindow()
7817 ? CycleCollectedJSContext::Get()
7818 : nullptr) {
7819 if (mContext) {
7820 mContext->EnterMicroTask();
7821 }
7822}
7823
7824nsAutoMicroTaskForDocument::~nsAutoMicroTaskForDocument() {
7825 if (mContext) {
7826 mContext->LeaveMicroTask();
7827 }
7828}
7829
7830/* static */
7831already_AddRefed<nsPIDOMWindowOuter>
7832nsContentUtils::GetMostRecentNonPBWindow() {
7833 nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID"@mozilla.org/appshell/window-mediator;1");
7834
7835 nsCOMPtr<mozIDOMWindowProxy> window;
7836 wm->GetMostRecentNonPBWindow(u"navigator:browser", getter_AddRefs(window));
7837 nsCOMPtr<nsPIDOMWindowOuter> pwindow;
7838 pwindow = do_QueryInterface(window);
7839
7840 return pwindow.forget();
7841}
7842
7843/* static */
7844already_AddRefed<nsPIDOMWindowOuter> nsContentUtils::GetMostRecentWindowBy(
7845 WindowMediatorFilter aFilter) {
7846 nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID"@mozilla.org/appshell/window-mediator;1");
7847
7848 nsCOMPtr<mozIDOMWindowProxy> window;
7849 wm->GetMostRecentWindowBy(u"navigator:browser", static_cast<uint8_t>(aFilter),
7850 getter_AddRefs(window));
7851 nsCOMPtr<nsPIDOMWindowOuter> pwindow;
7852 pwindow = do_QueryInterface(window);
7853
7854 return pwindow.forget();
7855}
7856
7857/* static */
7858void nsContentUtils::WarnScriptWasIgnored(Document* aDocument) {
7859 nsAutoString msg;
7860 bool privateBrowsing = false;
7861 bool chromeContext = false;
7862
7863 if (aDocument) {
7864 nsCOMPtr<nsIURI> uri = aDocument->GetDocumentURI();
7865 if (uri) {
7866 msg.Append(NS_ConvertUTF8toUTF16(uri->GetSpecOrDefault()));
7867 msg.AppendLiteral(" : ");
7868 }
7869 privateBrowsing =
7870 aDocument->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing();
7871 chromeContext = aDocument->NodePrincipal()->IsSystemPrincipal();
7872 }
7873
7874 msg.AppendLiteral(
7875 "Unable to run script because scripts are blocked internally.");
7876 LogSimpleConsoleError(msg, "DOM"_ns, privateBrowsing, chromeContext);
7877}
7878
7879/* static */
7880void nsContentUtils::AddScriptRunner(already_AddRefed<nsIRunnable> aRunnable) {
7881 nsCOMPtr<nsIRunnable> runnable = aRunnable;
7882 if (!runnable) {
7883 return;
7884 }
7885
7886 if (sScriptBlockerCount) {
7887 PROFILER_MARKER("nsContentUtils::AddScriptRunner", OTHER, {}, FlowMarker,do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("nsContentUtils::AddScriptRunner", ::geckoprofiler::category
::OTHER, {}, ::geckoprofiler::markers::FlowMarker{}, Flow::FromPointer
(runnable.get())); } } while (false); } while (false)
7888 Flow::FromPointer(runnable.get()))do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("nsContentUtils::AddScriptRunner", ::geckoprofiler::category
::OTHER, {}, ::geckoprofiler::markers::FlowMarker{}, Flow::FromPointer
(runnable.get())); } } while (false); } while (false)
;
7889 sBlockedScriptRunners->AppendElement(runnable.forget());
7890 return;
7891 }
7892
7893 AUTO_PROFILE_FOLLOWING_RUNNABLE(runnable)mozilla::Maybe<mozilla::AutoProfileRunnable> raiiRunnableMarker
; if (profiler_thread_is_profiling_runnables()) { raiiRunnableMarker
.emplace(runnable); }
;
7894 runnable->Run();
7895}
7896
7897/* static */
7898void nsContentUtils::AddScriptRunner(nsIRunnable* aRunnable) {
7899 nsCOMPtr<nsIRunnable> runnable = aRunnable;
7900 AddScriptRunner(runnable.forget());
7901}
7902
7903/* static */ bool nsContentUtils::IsSafeToRunScript() {
7904 MOZ_ASSERT(NS_IsMainThread(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "This static variable only makes sense on the main thread!"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7905
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "This static variable only makes sense on the main thread!"
")"); do { MOZ_CrashSequence(__null, 7905); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7905 "This static variable only makes sense on the main thread!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "This static variable only makes sense on the main thread!"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7905
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "This static variable only makes sense on the main thread!"
")"); do { MOZ_CrashSequence(__null, 7905); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7906 return sScriptBlockerCount == 0;
7907}
7908
7909/* static */
7910void nsContentUtils::RunInStableState(already_AddRefed<nsIRunnable> aRunnable) {
7911 MOZ_ASSERT(CycleCollectedJSContext::Get(), "Must be on a script thread!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(CycleCollectedJSContext::Get())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(CycleCollectedJSContext::Get
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("CycleCollectedJSContext::Get()" " (" "Must be on a script thread!"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7911
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()"
") (" "Must be on a script thread!" ")"); do { MOZ_CrashSequence
(__null, 7911); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7912 CycleCollectedJSContext::Get()->RunInStableState(std::move(aRunnable));
7913}
7914
7915/* static */
7916void nsContentUtils::AddPendingIDBTransaction(
7917 already_AddRefed<nsIRunnable> aTransaction) {
7918 MOZ_ASSERT(CycleCollectedJSContext::Get(), "Must be on a script thread!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(CycleCollectedJSContext::Get())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(CycleCollectedJSContext::Get
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("CycleCollectedJSContext::Get()" " (" "Must be on a script thread!"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7918
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()"
") (" "Must be on a script thread!" ")"); do { MOZ_CrashSequence
(__null, 7918); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7919 CycleCollectedJSContext::Get()->AddPendingIDBTransaction(
7920 std::move(aTransaction));
7921}
7922
7923/* static */
7924bool nsContentUtils::IsInStableOrMetaStableState() {
7925 MOZ_ASSERT(CycleCollectedJSContext::Get(), "Must be on a script thread!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(CycleCollectedJSContext::Get())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(CycleCollectedJSContext::Get
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("CycleCollectedJSContext::Get()" " (" "Must be on a script thread!"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7925
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()"
") (" "Must be on a script thread!" ")"); do { MOZ_CrashSequence
(__null, 7925); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7926 return CycleCollectedJSContext::Get()->IsInStableOrMetaStableState();
7927}
7928
7929/* static */
7930void nsContentUtils::HidePopupsInDocument(Document* aDocument) {
7931 RefPtr<nsXULPopupManager> pm = nsXULPopupManager::GetInstance();
7932 if (!pm || !aDocument) {
7933 return;
7934 }
7935 nsCOMPtr<nsIDocShellTreeItem> docShellToHide = aDocument->GetDocShell();
7936 if (docShellToHide) {
7937 pm->HidePopupsInDocShell(docShellToHide);
7938 }
7939}
7940
7941/* static */
7942already_AddRefed<nsIDragSession> nsContentUtils::GetDragSession(
7943 nsIWidget* aWidget) {
7944 nsCOMPtr<nsIDragSession> dragSession;
7945 nsCOMPtr<nsIDragService> dragService =
7946 do_GetService("@mozilla.org/widget/dragservice;1");
7947 if (dragService) {
7948 dragSession = dragService->GetCurrentSession(aWidget);
7949 }
7950 return dragSession.forget();
7951}
7952
7953/* static */
7954already_AddRefed<nsIDragSession> nsContentUtils::GetDragSession(
7955 nsPresContext* aPC) {
7956 NS_ENSURE_TRUE(aPC, nullptr)do { if ((__builtin_expect(!!(!(aPC)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "aPC" ") failed", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 7956); return nullptr; } } while (false)
;
7957 auto* widget = aPC->GetRootWidget();
7958 if (!widget) {
7959 return nullptr;
7960 }
7961 return GetDragSession(widget);
7962}
7963
7964/* static */
7965nsresult nsContentUtils::SetDataTransferInEvent(WidgetDragEvent* aDragEvent) {
7966 if (aDragEvent->mDataTransfer || !aDragEvent->IsTrusted()) {
7967 return NS_OK;
7968 }
7969
7970 // For dragstart events, the data transfer object is
7971 // created before the event fires, so it should already be set. For other
7972 // drag events, get the object from the drag session.
7973 NS_ASSERTION(aDragEvent->mMessage != eDragStart,do { if (!(aDragEvent->mMessage != eDragStart)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "draggesture event created without a dataTransfer"
, "aDragEvent->mMessage != eDragStart", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 7974); MOZ_PretendNoReturn(); } } while (0)
7974 "draggesture event created without a dataTransfer")do { if (!(aDragEvent->mMessage != eDragStart)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "draggesture event created without a dataTransfer"
, "aDragEvent->mMessage != eDragStart", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 7974); MOZ_PretendNoReturn(); } } while (0)
;
7975
7976 nsCOMPtr<nsIDragSession> dragSession = GetDragSession(aDragEvent->mWidget);
7977 NS_ENSURE_TRUE(dragSession, NS_OK)do { if ((__builtin_expect(!!(!(dragSession)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "dragSession" ") failed"
, nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp",
7977); return NS_OK; } } while (false)
; // no drag in progress
7978
7979 RefPtr<DataTransfer> initialDataTransfer = dragSession->GetDataTransfer();
7980 if (!initialDataTransfer) {
7981 // A dataTransfer won't exist when a drag was started by some other
7982 // means, for instance calling the drag service directly, or a drag
7983 // from another application. In either case, a new dataTransfer should
7984 // be created that reflects the data.
7985 initialDataTransfer = new DataTransfer(
7986 aDragEvent->mTarget, aDragEvent->mMessage, true, Nothing());
7987
7988 // now set it in the drag session so we don't need to create it again
7989 dragSession->SetDataTransfer(initialDataTransfer);
7990 }
7991
7992 bool isCrossDomainSubFrameDrop = false;
7993 if (aDragEvent->mMessage == eDrop) {
7994 isCrossDomainSubFrameDrop = CheckForSubFrameDrop(dragSession, aDragEvent);
7995 }
7996
7997 // each event should use a clone of the original dataTransfer.
7998 initialDataTransfer->Clone(
7999 aDragEvent->mTarget, aDragEvent->mMessage, aDragEvent->mUserCancelled,
8000 isCrossDomainSubFrameDrop, getter_AddRefs(aDragEvent->mDataTransfer));
8001 if (NS_WARN_IF(!aDragEvent->mDataTransfer)NS_warn_if_impl(!aDragEvent->mDataTransfer, "!aDragEvent->mDataTransfer"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8001)
) {
8002 return NS_ERROR_OUT_OF_MEMORY;
8003 }
8004
8005 // for the dragenter and dragover events, initialize the drop effect
8006 // from the drop action, which platform specific widget code sets before
8007 // the event is fired based on the keyboard state.
8008 if (aDragEvent->mMessage == eDragEnter || aDragEvent->mMessage == eDragOver) {
8009 uint32_t action;
8010 dragSession->GetDragAction(&action);
8011 uint32_t effectAllowed = aDragEvent->mDataTransfer->EffectAllowedInt();
8012 aDragEvent->mDataTransfer->SetDropEffectInt(
8013 FilterDropEffect(action, effectAllowed));
8014 } else if (aDragEvent->mMessage == eDrop ||
8015 aDragEvent->mMessage == eDragEnd) {
8016 // For the drop and dragend events, set the drop effect based on the
8017 // last value that the dropEffect had. This will have been set in
8018 // EventStateManager::PostHandleEvent for the last dragenter or
8019 // dragover event.
8020 aDragEvent->mDataTransfer->SetDropEffectInt(
8021 initialDataTransfer->DropEffectInt());
8022 }
8023
8024 return NS_OK;
8025}
8026
8027/* static */
8028uint32_t nsContentUtils::FilterDropEffect(uint32_t aAction,
8029 uint32_t aEffectAllowed) {
8030 // It is possible for the drag action to include more than one action, but
8031 // the widget code which sets the action from the keyboard state should only
8032 // be including one. If multiple actions were set, we just consider them in
8033 // the following order:
8034 // copy, link, move
8035 if (aAction & nsIDragService::DRAGDROP_ACTION_COPY)
8036 aAction = nsIDragService::DRAGDROP_ACTION_COPY;
8037 else if (aAction & nsIDragService::DRAGDROP_ACTION_LINK)
8038 aAction = nsIDragService::DRAGDROP_ACTION_LINK;
8039 else if (aAction & nsIDragService::DRAGDROP_ACTION_MOVE)
8040 aAction = nsIDragService::DRAGDROP_ACTION_MOVE;
8041
8042 // Filter the action based on the effectAllowed. If the effectAllowed
8043 // doesn't include the action, then that action cannot be done, so adjust
8044 // the action to something that is allowed. For a copy, adjust to move or
8045 // link. For a move, adjust to copy or link. For a link, adjust to move or
8046 // link. Otherwise, use none.
8047 if (aAction & aEffectAllowed ||
8048 aEffectAllowed == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED)
8049 return aAction;
8050 if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_MOVE)
8051 return nsIDragService::DRAGDROP_ACTION_MOVE;
8052 if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_COPY)
8053 return nsIDragService::DRAGDROP_ACTION_COPY;
8054 if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_LINK)
8055 return nsIDragService::DRAGDROP_ACTION_LINK;
8056 return nsIDragService::DRAGDROP_ACTION_NONE;
8057}
8058
8059/* static */
8060bool nsContentUtils::CheckForSubFrameDrop(nsIDragSession* aDragSession,
8061 WidgetDragEvent* aDropEvent) {
8062 nsCOMPtr<nsIContent> target =
8063 nsIContent::FromEventTargetOrNull(aDropEvent->mOriginalTarget);
8064 if (!target) {
8065 return true;
8066 }
8067
8068 // Always allow dropping onto chrome shells.
8069 BrowsingContext* targetBC = target->OwnerDoc()->GetBrowsingContext();
8070 if (targetBC->IsChrome()) {
8071 return false;
8072 }
8073
8074 WindowContext* targetWC = target->OwnerDoc()->GetWindowContext();
8075
8076 // If there is no source browsing context, then this is a drag from another
8077 // application, which should be allowed.
8078 RefPtr<WindowContext> sourceWC;
8079 aDragSession->GetSourceWindowContext(getter_AddRefs(sourceWC));
8080 if (sourceWC) {
8081 // Get each successive parent of the source document and compare it to
8082 // the drop document. If they match, then this is a drag from a child frame.
8083 for (sourceWC = sourceWC->GetParentWindowContext(); sourceWC;
8084 sourceWC = sourceWC->GetParentWindowContext()) {
8085 // If the source and the target match, then the drag started in a
8086 // descendant frame. If the source is discarded, err on the side of
8087 // caution and treat it as a subframe drag.
8088 if (sourceWC == targetWC || sourceWC->IsDiscarded()) {
8089 return true;
8090 }
8091 }
8092 }
8093
8094 return false;
8095}
8096
8097/* static */
8098bool nsContentUtils::URIIsLocalFile(nsIURI* aURI) {
8099 bool isFile;
8100 nsCOMPtr<nsINetUtil> util = mozilla::components::IO::Service();
8101
8102 // Important: we do NOT test the entire URI chain here!
8103 return util &&
8104 NS_SUCCEEDED(util->ProtocolHasFlags(((bool)(__builtin_expect(!!(!NS_FAILED_impl(util->ProtocolHasFlags
( aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile)))
, 1)))
8105 aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile))((bool)(__builtin_expect(!!(!NS_FAILED_impl(util->ProtocolHasFlags
( aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile)))
, 1)))
&&
8106 isFile;
8107}
8108
8109/* static */
8110JSContext* nsContentUtils::GetCurrentJSContext() {
8111 MOZ_ASSERT(IsInitialized())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsInitialized())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsInitialized()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("IsInitialized()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8111); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInitialized()" ")"); do { MOZ_CrashSequence
(__null, 8111); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8112 if (!IsJSAPIActive()) {
8113 return nullptr;
8114 }
8115 return danger::GetJSContext();
8116}
8117
8118template <typename StringType, typename CharType>
8119void _ASCIIToLowerInSitu(StringType& aStr) {
8120 CharType* iter = aStr.BeginWriting();
8121 CharType* end = aStr.EndWriting();
8122 MOZ_ASSERT(iter && end)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(iter && end)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(iter && end))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("iter && end"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8122); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "iter && end" ")"); do { MOZ_CrashSequence
(__null, 8122); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8123
8124 while (iter != end) {
8125 CharType c = *iter;
8126 if (c >= 'A' && c <= 'Z') {
8127 *iter = c + ('a' - 'A');
8128 }
8129 ++iter;
8130 }
8131}
8132
8133/* static */
8134void nsContentUtils::ASCIIToLower(nsAString& aStr) {
8135 return _ASCIIToLowerInSitu<nsAString, char16_t>(aStr);
8136}
8137
8138/* static */
8139void nsContentUtils::ASCIIToLower(nsACString& aStr) {
8140 return _ASCIIToLowerInSitu<nsACString, char>(aStr);
8141}
8142
8143template <typename StringType, typename CharType>
8144void _ASCIIToLowerCopy(const StringType& aSource, StringType& aDest) {
8145 uint32_t len = aSource.Length();
8146 aDest.SetLength(len);
8147 MOZ_ASSERT(aDest.Length() == len)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDest.Length() == len)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDest.Length() == len))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("aDest.Length() == len"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8147); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aDest.Length() == len" ")"); do { MOZ_CrashSequence
(__null, 8147); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8148
8149 CharType* dest = aDest.BeginWriting();
8150 MOZ_ASSERT(dest)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(dest)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(dest))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("dest", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8150); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dest" ")");
do { MOZ_CrashSequence(__null, 8150); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8151
8152 const CharType* iter = aSource.BeginReading();
8153 const CharType* end = aSource.EndReading();
8154 while (iter != end) {
8155 CharType c = *iter;
8156 *dest = (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
8157 ++iter;
8158 ++dest;
8159 }
8160}
8161
8162/* static */
8163void nsContentUtils::ASCIIToLower(const nsAString& aSource, nsAString& aDest) {
8164 return _ASCIIToLowerCopy<nsAString, char16_t>(aSource, aDest);
8165}
8166
8167/* static */
8168void nsContentUtils::ASCIIToLower(const nsACString& aSource,
8169 nsACString& aDest) {
8170 return _ASCIIToLowerCopy<nsACString, char>(aSource, aDest);
8171}
8172
8173template <typename StringType, typename CharType>
8174void _ASCIIToUpperInSitu(StringType& aStr) {
8175 CharType* iter = aStr.BeginWriting();
8176 CharType* end = aStr.EndWriting();
8177 MOZ_ASSERT(iter && end)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(iter && end)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(iter && end))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("iter && end"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8177); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "iter && end" ")"); do { MOZ_CrashSequence
(__null, 8177); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8178
8179 while (iter != end) {
8180 CharType c = *iter;
8181 if (c >= 'a' && c <= 'z') {
8182 *iter = c + ('A' - 'a');
8183 }
8184 ++iter;
8185 }
8186}
8187
8188/* static */
8189void nsContentUtils::ASCIIToUpper(nsAString& aStr) {
8190 return _ASCIIToUpperInSitu<nsAString, char16_t>(aStr);
8191}
8192
8193/* static */
8194void nsContentUtils::ASCIIToUpper(nsACString& aStr) {
8195 return _ASCIIToUpperInSitu<nsACString, char>(aStr);
8196}
8197
8198template <typename StringType, typename CharType>
8199void _ASCIIToUpperCopy(const StringType& aSource, StringType& aDest) {
8200 uint32_t len = aSource.Length();
8201 aDest.SetLength(len);
8202 MOZ_ASSERT(aDest.Length() == len)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDest.Length() == len)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDest.Length() == len))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("aDest.Length() == len"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8202); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aDest.Length() == len" ")"); do { MOZ_CrashSequence
(__null, 8202); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8203
8204 CharType* dest = aDest.BeginWriting();
8205 MOZ_ASSERT(dest)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(dest)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(dest))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("dest", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8205); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dest" ")");
do { MOZ_CrashSequence(__null, 8205); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8206
8207 const CharType* iter = aSource.BeginReading();
8208 const CharType* end = aSource.EndReading();
8209 while (iter != end) {
8210 CharType c = *iter;
8211 *dest = (c >= 'a' && c <= 'z') ? c + ('A' - 'a') : c;
8212 ++iter;
8213 ++dest;
8214 }
8215}
8216
8217/* static */
8218void nsContentUtils::ASCIIToUpper(const nsAString& aSource, nsAString& aDest) {
8219 return _ASCIIToUpperCopy<nsAString, char16_t>(aSource, aDest);
8220}
8221
8222/* static */
8223void nsContentUtils::ASCIIToUpper(const nsACString& aSource,
8224 nsACString& aDest) {
8225 return _ASCIIToUpperCopy<nsACString, char>(aSource, aDest);
8226}
8227
8228/* static */
8229bool nsContentUtils::EqualsIgnoreASCIICase(nsAtom* aAtom1, nsAtom* aAtom2) {
8230 if (aAtom1 == aAtom2) {
8231 return true;
8232 }
8233
8234 // If both are ascii lowercase already, we know that the slow comparison
8235 // below is going to return false.
8236 if (aAtom1->IsAsciiLowercase() && aAtom2->IsAsciiLowercase()) {
8237 return false;
8238 }
8239
8240 return EqualsIgnoreASCIICase(nsDependentAtomString(aAtom1),
8241 nsDependentAtomString(aAtom2));
8242}
8243
8244/* static */
8245bool nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1,
8246 const nsAString& aStr2) {
8247 uint32_t len = aStr1.Length();
8248 if (len != aStr2.Length()) {
8249 return false;
8250 }
8251
8252 const char16_t* str1 = aStr1.BeginReading();
8253 const char16_t* str2 = aStr2.BeginReading();
8254 const char16_t* end = str1 + len;
8255
8256 while (str1 < end) {
8257 char16_t c1 = *str1++;
8258 char16_t c2 = *str2++;
8259
8260 // First check if any bits other than the 0x0020 differs
8261 if ((c1 ^ c2) & 0xffdf) {
8262 return false;
8263 }
8264
8265 // We know they can only differ in the 0x0020 bit.
8266 // Likely the two chars are the same, so check that first
8267 if (c1 != c2) {
8268 // They do differ, but since it's only in the 0x0020 bit, check if it's
8269 // the same ascii char, but just differing in case
8270 char16_t c1Upper = c1 & 0xffdf;
8271 if (!('A' <= c1Upper && c1Upper <= 'Z')) {
8272 return false;
8273 }
8274 }
8275 }
8276
8277 return true;
8278}
8279
8280/* static */
8281bool nsContentUtils::StringContainsASCIIUpper(const nsAString& aStr) {
8282 const char16_t* iter = aStr.BeginReading();
8283 const char16_t* end = aStr.EndReading();
8284 while (iter != end) {
8285 char16_t c = *iter;
8286 if (c >= 'A' && c <= 'Z') {
8287 return true;
8288 }
8289 ++iter;
8290 }
8291
8292 return false;
8293}
8294
8295/* static */
8296nsIInterfaceRequestor* nsContentUtils::SameOriginChecker() {
8297 if (!sSameOriginChecker) {
8298 sSameOriginChecker = new SameOriginCheckerImpl();
8299 NS_ADDREF(sSameOriginChecker)(sSameOriginChecker)->AddRef();
8300 }
8301 return sSameOriginChecker;
8302}
8303
8304/* static */
8305nsresult nsContentUtils::CheckSameOrigin(nsIChannel* aOldChannel,
8306 nsIChannel* aNewChannel) {
8307 if (!nsContentUtils::GetSecurityManager()) return NS_ERROR_NOT_AVAILABLE;
8308
8309 nsCOMPtr<nsIPrincipal> oldPrincipal;
8310 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
8311 aOldChannel, getter_AddRefs(oldPrincipal));
8312
8313 nsCOMPtr<nsIURI> newURI;
8314 aNewChannel->GetURI(getter_AddRefs(newURI));
8315 nsCOMPtr<nsIURI> newOriginalURI;
8316 aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
8317
8318 NS_ENSURE_STATE(oldPrincipal && newURI && newOriginalURI)do { if ((__builtin_expect(!!(!(oldPrincipal && newURI
&& newOriginalURI)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "oldPrincipal && newURI && newOriginalURI"
") failed", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8318); return NS_ERROR_UNEXPECTED; } } while (false)
;
8319
8320 nsresult rv = oldPrincipal->CheckMayLoad(newURI, false);
8321 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && newOriginalURI != newURI) {
8322 rv = oldPrincipal->CheckMayLoad(newOriginalURI, false);
8323 }
8324
8325 return rv;
8326}
8327
8328NS_IMPL_ISUPPORTS(SameOriginCheckerImpl, nsIChannelEventSink,MozExternalRefCountType SameOriginCheckerImpl::AddRef(void) {
static_assert(!std::is_destructible_v<SameOriginCheckerImpl
>, "Reference-counted class " "SameOriginCheckerImpl" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 8329
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("SameOriginCheckerImpl" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("SameOriginCheckerImpl" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"SameOriginCheckerImpl\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 8329); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("SameOriginCheckerImpl" " not thread-safe");
nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ("SameOriginCheckerImpl"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
SameOriginCheckerImpl::Release(void) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(int32_t(mRefCnt)
> 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8329
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 8329
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("SameOriginCheckerImpl" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("SameOriginCheckerImpl" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"SameOriginCheckerImpl\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 8329); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("SameOriginCheckerImpl" " not thread-safe");
const char* const nametmp = "SameOriginCheckerImpl"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; } nsresult SameOriginCheckerImpl::QueryInterface(const
nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8329); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(2 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<SameOriginCheckerImpl, nsIChannelEventSink
>, int32_t( reinterpret_cast<char*>(static_cast<nsIChannelEventSink
*>((SameOriginCheckerImpl*)0x1000)) - reinterpret_cast<
char*>((SameOriginCheckerImpl*)0x1000))}, {&mozilla::detail
::kImplementedIID<SameOriginCheckerImpl, nsIInterfaceRequestor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor
*>((SameOriginCheckerImpl*)0x1000)) - reinterpret_cast<
char*>((SameOriginCheckerImpl*)0x1000))}, {&mozilla::detail
::kImplementedIID<SameOriginCheckerImpl, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIChannelEventSink*>((SameOriginCheckerImpl
*)0x1000))) - reinterpret_cast<char*>((SameOriginCheckerImpl
*)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table
) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
8329 nsIInterfaceRequestor)MozExternalRefCountType SameOriginCheckerImpl::AddRef(void) {
static_assert(!std::is_destructible_v<SameOriginCheckerImpl
>, "Reference-counted class " "SameOriginCheckerImpl" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 8329
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("SameOriginCheckerImpl" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("SameOriginCheckerImpl" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"SameOriginCheckerImpl\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 8329); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("SameOriginCheckerImpl" " not thread-safe");
nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ("SameOriginCheckerImpl"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
SameOriginCheckerImpl::Release(void) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(int32_t(mRefCnt)
> 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8329
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 8329
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("SameOriginCheckerImpl" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("SameOriginCheckerImpl" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"SameOriginCheckerImpl\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 8329); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("SameOriginCheckerImpl" " not thread-safe");
const char* const nametmp = "SameOriginCheckerImpl"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; } nsresult SameOriginCheckerImpl::QueryInterface(const
nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8329); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(2 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<SameOriginCheckerImpl, nsIChannelEventSink
>, int32_t( reinterpret_cast<char*>(static_cast<nsIChannelEventSink
*>((SameOriginCheckerImpl*)0x1000)) - reinterpret_cast<
char*>((SameOriginCheckerImpl*)0x1000))}, {&mozilla::detail
::kImplementedIID<SameOriginCheckerImpl, nsIInterfaceRequestor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIInterfaceRequestor
*>((SameOriginCheckerImpl*)0x1000)) - reinterpret_cast<
char*>((SameOriginCheckerImpl*)0x1000))}, {&mozilla::detail
::kImplementedIID<SameOriginCheckerImpl, nsISupports>, int32_t
(reinterpret_cast<char*>(static_cast<nsISupports*>
( static_cast<nsIChannelEventSink*>((SameOriginCheckerImpl
*)0x1000))) - reinterpret_cast<char*>((SameOriginCheckerImpl
*)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table
) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
8330
8331NS_IMETHODIMPnsresult
8332SameOriginCheckerImpl::AsyncOnChannelRedirect(
8333 nsIChannel* aOldChannel, nsIChannel* aNewChannel, uint32_t aFlags,
8334 nsIAsyncVerifyRedirectCallback* cb) {
8335 MOZ_ASSERT(aNewChannel, "Redirecting to null channel?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNewChannel)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aNewChannel))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aNewChannel" " ("
"Redirecting to null channel?" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8335); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewChannel"
") (" "Redirecting to null channel?" ")"); do { MOZ_CrashSequence
(__null, 8335); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8336
8337 nsresult rv = nsContentUtils::CheckSameOrigin(aOldChannel, aNewChannel);
8338 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
8339 cb->OnRedirectVerifyCallback(NS_OK);
8340 }
8341
8342 return rv;
8343}
8344
8345NS_IMETHODIMPnsresult
8346SameOriginCheckerImpl::GetInterface(const nsIID& aIID, void** aResult) {
8347 return QueryInterface(aIID, aResult);
8348}
8349
8350/* static */
8351nsresult nsContentUtils::GetWebExposedOriginSerialization(nsIURI* aURI,
8352 nsACString& aOrigin) {
8353 nsresult rv;
8354 MOZ_ASSERT(aURI, "missing uri")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURI)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURI" " (" "missing uri" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8354); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"missing uri" ")"); do { MOZ_CrashSequence(__null, 8354); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
8355
8356 // For Blob URI, the path is the URL of the owning page.
8357 if (aURI->SchemeIs(BLOBURI_SCHEME"blob")) {
8358 nsAutoCString path;
8359 rv = aURI->GetPathQueryRef(path);
8360 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8360); return rv; } } while (false)
;
8361
8362 nsCOMPtr<nsIURI> uri;
8363 rv = NS_NewURI(getter_AddRefs(uri), path);
8364 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8365 aOrigin.AssignLiteral("null");
8366 return NS_OK;
8367 }
8368
8369 if (
8370 // Schemes in spec. https://url.spec.whatwg.org/#origin
8371 !net::SchemeIsHttpOrHttps(uri) && !uri->SchemeIs("file") &&
8372 !uri->SchemeIs("resource") &&
8373 // Our own schemes.
8374 !uri->SchemeIs("moz-extension")) {
8375 aOrigin.AssignLiteral("null");
8376 return NS_OK;
8377 }
8378
8379 return GetWebExposedOriginSerialization(uri, aOrigin);
8380 }
8381
8382 nsAutoCString scheme;
8383 aURI->GetScheme(scheme);
8384
8385 // If the protocol doesn't have URI_HAS_WEB_EXPOSED_ORIGIN, then
8386 // return "null" as the origin serialization.
8387 // We make an exception for "ftp" since we don't have a protocol handler
8388 // for this scheme
8389 uint32_t flags = 0;
8390 nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service(&rv);
8391 if (!scheme.Equals("ftp") && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) &&
8392 NS_SUCCEEDED(io->GetProtocolFlags(scheme.get(), &flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(io->GetProtocolFlags
(scheme.get(), &flags))), 1)))
) {
8393 if (!(flags & nsIProtocolHandler::URI_HAS_WEB_EXPOSED_ORIGIN)) {
8394 aOrigin.AssignLiteral("null");
8395 return NS_OK;
8396 }
8397 }
8398
8399 aOrigin.Truncate();
8400
8401 nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
8402 NS_ENSURE_TRUE(uri, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(uri)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "uri" ") failed", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8402); return NS_ERROR_UNEXPECTED; } } while (false)
;
8403
8404 nsAutoCString host;
8405 rv = uri->GetAsciiHost(host);
8406
8407 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !host.IsEmpty()) {
8408 nsAutoCString userPass;
8409 uri->GetUserPass(userPass);
8410
8411 nsAutoCString prePath;
8412 if (!userPass.IsEmpty()) {
8413 rv = NS_MutateURI(uri).SetUserPass(""_ns).Finalize(uri);
8414 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8414); return rv; } } while (false)
;
8415 }
8416
8417 rv = uri->GetPrePath(prePath);
8418 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8418); return rv; } } while (false)
;
8419
8420 aOrigin = std::move(prePath);
8421 } else {
8422 aOrigin.AssignLiteral("null");
8423 }
8424
8425 return NS_OK;
8426}
8427
8428/* static */
8429nsresult nsContentUtils::GetWebExposedOriginSerialization(
8430 nsIPrincipal* aPrincipal, nsAString& aOrigin) {
8431 MOZ_ASSERT(aPrincipal, "missing principal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPrincipal))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aPrincipal" " (" "missing principal"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8431
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal" ") ("
"missing principal" ")"); do { MOZ_CrashSequence(__null, 8431
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
8432
8433 aOrigin.Truncate();
8434 nsAutoCString webExposedOriginSerialization;
8435
8436 nsresult rv = aPrincipal->GetWebExposedOriginSerialization(
8437 webExposedOriginSerialization);
8438 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8439 webExposedOriginSerialization.AssignLiteral("null");
8440 }
8441
8442 CopyUTF8toUTF16(webExposedOriginSerialization, aOrigin);
8443 return NS_OK;
8444}
8445
8446/* static */
8447nsresult nsContentUtils::GetWebExposedOriginSerialization(nsIURI* aURI,
8448 nsAString& aOrigin) {
8449 MOZ_ASSERT(aURI, "missing uri")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aURI)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aURI))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aURI" " (" "missing uri" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8449); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"missing uri" ")"); do { MOZ_CrashSequence(__null, 8449); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
8450 nsresult rv;
8451
8452#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
8453 // Check if either URI has a special origin.
8454 nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin =
8455 do_QueryInterface(aURI);
8456 if (uriWithSpecialOrigin) {
8457 nsCOMPtr<nsIURI> origin;
8458 rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
8459 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8459); return rv; } } while (false)
;
8460
8461 return GetWebExposedOriginSerialization(origin, aOrigin);
8462 }
8463#endif
8464
8465 nsAutoCString webExposedOriginSerialization;
8466 rv = GetWebExposedOriginSerialization(aURI, webExposedOriginSerialization);
8467 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8467); return rv; } } while (false)
;
8468
8469 CopyUTF8toUTF16(webExposedOriginSerialization, aOrigin);
8470 return NS_OK;
8471}
8472
8473/* static */
8474bool nsContentUtils::CheckMayLoad(nsIPrincipal* aPrincipal,
8475 nsIChannel* aChannel,
8476 bool aAllowIfInheritsPrincipal) {
8477 nsCOMPtr<nsIURI> channelURI;
8478 nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
8479 NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8479); return false; } } while (false)
;
8480
8481 return NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->CheckMayLoad
(channelURI, aAllowIfInheritsPrincipal))), 1)))
8482 aPrincipal->CheckMayLoad(channelURI, aAllowIfInheritsPrincipal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->CheckMayLoad
(channelURI, aAllowIfInheritsPrincipal))), 1)))
;
8483}
8484
8485/* static */
8486bool nsContentUtils::CanAccessNativeAnon() {
8487 return LegacyIsCallerChromeOrNativeCode();
8488}
8489
8490/* static */
8491nsresult nsContentUtils::DispatchXULCommand(nsIContent* aTarget, bool aTrusted,
8492 Event* aSourceEvent,
8493 PresShell* aPresShell, bool aCtrl,
8494 bool aAlt, bool aShift, bool aMeta,
8495 uint16_t aInputSource,
8496 int16_t aButton) {
8497 NS_ENSURE_STATE(aTarget)do { if ((__builtin_expect(!!(!(aTarget)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aTarget" ") failed", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8497); return
NS_ERROR_UNEXPECTED; } } while (false)
;
8498 Document* doc = aTarget->OwnerDoc();
8499 nsPresContext* presContext = doc->GetPresContext();
8500
8501 RefPtr<XULCommandEvent> xulCommand =
8502 new XULCommandEvent(doc, presContext, nullptr);
8503 xulCommand->InitCommandEvent(u"command"_ns, true, true,
8504 nsGlobalWindowInner::Cast(doc->GetInnerWindow()),
8505 0, aCtrl, aAlt, aShift, aMeta, aButton,
8506 aSourceEvent, aInputSource, IgnoreErrors());
8507
8508 if (aPresShell) {
8509 nsEventStatus status = nsEventStatus_eIgnore;
8510 return aPresShell->HandleDOMEventWithTarget(aTarget, xulCommand, &status);
8511 }
8512
8513 ErrorResult rv;
8514 aTarget->DispatchEvent(*xulCommand, rv);
8515 return rv.StealNSResult();
8516}
8517
8518// static
8519nsresult nsContentUtils::WrapNative(JSContext* cx, nsISupports* native,
8520 nsWrapperCache* cache, const nsIID* aIID,
8521 JS::MutableHandle<JS::Value> vp,
8522 bool aAllowWrapping) {
8523 MOZ_ASSERT(cx == GetCurrentJSContext())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(cx == GetCurrentJSContext())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(cx == GetCurrentJSContext())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("cx == GetCurrentJSContext()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8523); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "cx == GetCurrentJSContext()" ")"); do { MOZ_CrashSequence
(__null, 8523); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8524
8525 if (!native) {
8526 vp.setNull();
8527
8528 return NS_OK;
8529 }
8530
8531 JSObject* wrapper = xpc_FastGetCachedWrapper(cx, cache, vp);
8532 if (wrapper) {
8533 return NS_OK;
8534 }
8535
8536 NS_ENSURE_TRUE(sXPConnect, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(sXPConnect)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "sXPConnect" ") failed",
nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8536
); return NS_ERROR_UNEXPECTED; } } while (false)
;
8537
8538 if (!NS_IsMainThread()) {
8539 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8539); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { MOZ_CrashSequence
(__null, 8539); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
8540 }
8541
8542 JS::Rooted<JSObject*> scope(cx, JS::CurrentGlobalOrNull(cx));
8543 nsresult rv = sXPConnect->WrapNativeToJSVal(cx, scope, native, cache, aIID,
8544 aAllowWrapping, vp);
8545 return rv;
8546}
8547
8548void nsContentUtils::StripNullChars(const nsAString& aInStr,
8549 nsAString& aOutStr) {
8550 // In common cases where we don't have nulls in the
8551 // string we can simple simply bypass the checking code.
8552 int32_t firstNullPos = aInStr.FindChar('\0');
8553 if (firstNullPos == kNotFound) {
8554 aOutStr.Assign(aInStr);
8555 return;
8556 }
8557
8558 aOutStr.SetCapacity(aInStr.Length() - 1);
8559 nsAString::const_iterator start, end;
8560 aInStr.BeginReading(start);
8561 aInStr.EndReading(end);
8562 while (start != end) {
8563 if (*start != '\0') aOutStr.Append(*start);
8564 ++start;
8565 }
8566}
8567
8568struct ClassMatchingInfo {
8569 AtomArray mClasses;
8570 nsCaseTreatment mCaseTreatment;
8571};
8572
8573// static
8574bool nsContentUtils::MatchClassNames(Element* aElement, int32_t aNamespaceID,
8575 nsAtom* aAtom, void* aData) {
8576 // We can't match if there are no class names
8577 const nsAttrValue* classAttr = aElement->GetClasses();
8578 if (!classAttr) {
8579 return false;
8580 }
8581
8582 // need to match *all* of the classes
8583 ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
8584 if (info->mClasses.IsEmpty()) {
8585 // If we actually had no classes, don't match.
8586 return false;
8587 }
8588
8589 for (nsAtom* cls : info->mClasses) {
8590 if (!classAttr->Contains(cls, info->mCaseTreatment)) {
8591 return false;
8592 }
8593 }
8594 return true;
8595}
8596
8597// static
8598void nsContentUtils::DestroyClassNameArray(void* aData) {
8599 ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
8600 delete info;
8601}
8602
8603// static
8604void* nsContentUtils::AllocClassMatchingInfo(nsINode* aRootNode,
8605 const nsString* aClasses) {
8606 nsAttrValue attrValue;
8607 attrValue.ParseAtomArray(*aClasses);
8608 // nsAttrValue::Equals is sensitive to order, so we'll send an array
8609 auto* info = new ClassMatchingInfo;
8610 if (attrValue.Type() == nsAttrValue::eAtomArray) {
8611 info->mClasses.AppendElements(attrValue.GetAtomArrayValue()->Array());
8612 } else if (attrValue.Type() == nsAttrValue::eAtom) {
8613 info->mClasses.AppendElement(attrValue.GetAtomValue());
8614 }
8615
8616 info->mCaseTreatment =
8617 aRootNode->OwnerDoc()->GetCompatibilityMode() == eCompatibility_NavQuirks
8618 ? eIgnoreCase
8619 : eCaseMatters;
8620 return info;
8621}
8622
8623void nsContentUtils::FlushLayoutForTree(nsPIDOMWindowOuter* aWindow) {
8624 if (!aWindow) {
8625 return;
8626 }
8627
8628 // Note that because FlushPendingNotifications flushes parents, this
8629 // is O(N^2) in docshell tree depth. However, the docshell tree is
8630 // usually pretty shallow.
8631
8632 if (RefPtr<Document> doc = aWindow->GetDoc()) {
8633 doc->FlushPendingNotifications(FlushType::Layout);
8634 }
8635
8636 if (nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell()) {
8637 int32_t i = 0, i_end;
8638 docShell->GetInProcessChildCount(&i_end);
8639 for (; i < i_end; ++i) {
8640 nsCOMPtr<nsIDocShellTreeItem> item;
8641 if (docShell->GetInProcessChildAt(i, getter_AddRefs(item)) == NS_OK &&
8642 item) {
8643 if (nsCOMPtr<nsPIDOMWindowOuter> win = item->GetWindow()) {
8644 FlushLayoutForTree(win);
8645 }
8646 }
8647 }
8648 }
8649}
8650
8651void nsContentUtils::RemoveNewlines(nsAString& aString) { aString.StripCRLF(); }
8652
8653void nsContentUtils::PlatformToDOMLineBreaks(nsAString& aString) {
8654 if (!PlatformToDOMLineBreaks(aString, fallible)) {
8655 aString.AllocFailed(aString.Length());
8656 }
8657}
8658
8659bool nsContentUtils::PlatformToDOMLineBreaks(nsAString& aString,
8660 const fallible_t& aFallible) {
8661 if (aString.FindChar(char16_t('\r')) != -1) {
8662 // Windows linebreaks: Map CRLF to LF:
8663 if (!aString.ReplaceSubstring(u"\r\n", u"\n", aFallible)) {
8664 return false;
8665 }
8666
8667 // Mac linebreaks: Map any remaining CR to LF:
8668 if (!aString.ReplaceSubstring(u"\r", u"\n", aFallible)) {
8669 return false;
8670 }
8671 }
8672
8673 return true;
8674}
8675
8676already_AddRefed<ContentList> nsContentUtils::GetElementsByClassName(
8677 nsINode* aRootNode, const nsAString& aClasses) {
8678 MOZ_ASSERT(aRootNode, "Must have root node")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRootNode)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRootNode))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aRootNode" " (" "Must have root node"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 8678
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRootNode" ") (" "Must have root node"
")"); do { MOZ_CrashSequence(__null, 8678); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8679
8680 return GetFuncStringContentList<CacheableFuncStringHTMLCollection>(
8681 aRootNode, MatchClassNames, DestroyClassNameArray, AllocClassMatchingInfo,
8682 aClasses);
8683}
8684
8685PresShell* nsContentUtils::FindPresShellForDocument(const Document* aDocument) {
8686 const Document* doc = aDocument;
8687 Document* displayDoc = doc->GetDisplayDocument();
8688 if (displayDoc) {
8689 doc = displayDoc;
8690 }
8691
8692 PresShell* presShell = doc->GetPresShell();
8693 if (presShell) {
8694 return presShell;
8695 }
8696
8697 nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = doc->GetDocShell();
8698 while (docShellTreeItem) {
8699 // We may be in a display:none subdocument, or we may not have a presshell
8700 // created yet.
8701 // Walk the docshell tree to find the nearest container that has a
8702 // presshell, and return that.
8703 nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(docShellTreeItem);
8704 if (PresShell* presShell = docShell->GetPresShell()) {
8705 return presShell;
8706 }
8707 nsCOMPtr<nsIDocShellTreeItem> parent;
8708 docShellTreeItem->GetInProcessParent(getter_AddRefs(parent));
8709 docShellTreeItem = parent;
8710 }
8711
8712 return nullptr;
8713}
8714
8715/* static */
8716nsPresContext* nsContentUtils::FindPresContextForDocument(
8717 const Document* aDocument) {
8718 if (PresShell* presShell = FindPresShellForDocument(aDocument)) {
8719 return presShell->GetPresContext();
8720 }
8721 return nullptr;
8722}
8723
8724nsIWidget* nsContentUtils::WidgetForDocument(const Document* aDocument) {
8725 PresShell* presShell = FindPresShellForDocument(aDocument);
8726 return presShell ? presShell->GetNearestWidget() : nullptr;
8727}
8728
8729nsIWidget* nsContentUtils::WidgetForContent(const nsIContent* aContent) {
8730 nsIFrame* frame = aContent->GetPrimaryFrame();
8731 if (!frame) {
8732 return nullptr;
8733 }
8734 return frame->GetNearestWidget();
8735}
8736
8737WindowRenderer* nsContentUtils::WindowRendererForContent(
8738 const nsIContent* aContent) {
8739 nsIWidget* widget = nsContentUtils::WidgetForContent(aContent);
8740 if (widget) {
8741 return widget->GetWindowRenderer();
8742 }
8743
8744 return nullptr;
8745}
8746
8747WindowRenderer* nsContentUtils::WindowRendererForDocument(
8748 const Document* aDoc) {
8749 if (nsIWidget* widget = nsContentUtils::WidgetForDocument(aDoc)) {
8750 return widget->GetWindowRenderer();
8751 }
8752 return nullptr;
8753}
8754
8755bool nsContentUtils::AllowXULXBLForPrincipal(nsIPrincipal* aPrincipal) {
8756 if (!aPrincipal) {
8757 return false;
8758 }
8759
8760 if (aPrincipal->IsSystemPrincipal()) {
8761 return true;
8762 }
8763
8764 return xpc::IsInAutomation() && IsSitePermAllow(aPrincipal, "allowXULXBL"_ns);
8765}
8766
8767bool nsContentUtils::IsPDFJSEnabled() { return !StaticPrefs::pdfjs_disabled(); }
8768
8769bool nsContentUtils::IsPDFJS(nsIPrincipal* aPrincipal) {
8770 if (!aPrincipal || !aPrincipal->SchemeIs("resource")) {
8771 return false;
8772 }
8773 nsAutoCString originNoSuffix;
8774 nsresult rv = aPrincipal->GetOriginNoSuffix(originNoSuffix);
8775 NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8775); return false; } } while (false)
;
8776 return originNoSuffix.Equals("resource://pdf.js"_ns);
8777}
8778
8779bool nsContentUtils::IsSystemOrPDFJS(JSContext* aCx, JSObject*) {
8780 nsIPrincipal* principal = SubjectPrincipal(aCx);
8781 return principal && (principal->IsSystemPrincipal() || IsPDFJS(principal));
8782}
8783
8784bool nsContentUtils::IsSecureContextOrWebExtension(JSContext* aCx,
8785 JSObject* aGlobal) {
8786 nsIPrincipal* principal = SubjectPrincipal(aCx);
8787 return mozilla::dom::IsSecureContextOrObjectIsFromSecureContext(aCx,
8788 aGlobal) ||
8789 (principal && principal->GetIsAddonOrExpandedAddonPrincipal());
8790}
8791
8792already_AddRefed<nsIDocumentLoaderFactory>
8793nsContentUtils::FindInternalDocumentViewer(const nsACString& aType,
8794 DocumentViewerType* aLoaderType) {
8795 if (aLoaderType) {
8796 *aLoaderType = TYPE_UNSUPPORTED;
8797 }
8798
8799 // one helper factory, please
8800 nsCOMPtr<nsICategoryManager> catMan(
8801 do_GetService(NS_CATEGORYMANAGER_CONTRACTID"@mozilla.org/categorymanager;1"));
8802 if (!catMan) return nullptr;
8803
8804 nsCOMPtr<nsIDocumentLoaderFactory> docFactory;
8805
8806 nsCString contractID;
8807 nsresult rv =
8808 catMan->GetCategoryEntry("Gecko-Content-Viewers", aType, contractID);
8809 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
8810 docFactory = do_GetService(contractID.get());
8811 if (docFactory && aLoaderType) {
8812 if (contractID.EqualsLiteral(CONTENT_DLF_CONTRACTID"@mozilla.org/content/document-loader-factory;1"))
8813 *aLoaderType = TYPE_CONTENT;
8814 else
8815 *aLoaderType = TYPE_UNKNOWN;
8816 }
8817 return docFactory.forget();
8818 }
8819
8820 // If the type wasn't registered in `Gecko-Content-Viewers`, check if it's
8821 // another type which we may dynamically support, such as `text/*` types or
8822 // video document types. These types are all backed by the nsContentDLF.
8823 if (IsPlainTextType(aType) ||
8824 DecoderTraits::IsSupportedInVideoDocument(aType)) {
8825 docFactory = do_GetService(CONTENT_DLF_CONTRACTID"@mozilla.org/content/document-loader-factory;1");
8826 if (docFactory && aLoaderType) {
8827 *aLoaderType = TYPE_CONTENT;
8828 }
8829 return docFactory.forget();
8830 }
8831
8832 return nullptr;
8833}
8834
8835static void ReportPatternCompileFailure(nsAString& aPattern,
8836 const JS::RegExpFlags& aFlags,
8837 const Document* aDocument,
8838 JS::MutableHandle<JS::Value> error,
8839 JSContext* cx) {
8840 AutoTArray<nsString, 3> strings;
8841
8842 strings.AppendElement(aPattern);
8843
8844 std::stringstream flag_ss;
8845 flag_ss << aFlags;
8846 nsString* flagstr = strings.AppendElement();
8847 AppendUTF8toUTF16(flag_ss.str(), *flagstr);
8848
8849 JS::AutoSaveExceptionState savedExc(cx);
8850 JS::Rooted<JSObject*> exnObj(cx, &error.toObject());
8851 JS::Rooted<JS::Value> messageVal(cx);
8852 if (!JS_GetProperty(cx, exnObj, "message", &messageVal)) {
8853 return;
8854 }
8855 JS::Rooted<JSString*> messageStr(cx, messageVal.toString());
8856 MOZ_ASSERT(messageStr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(messageStr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(messageStr))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("messageStr", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "messageStr"
")"); do { MOZ_CrashSequence(__null, 8856); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8857 if (!AssignJSString(cx, *strings.AppendElement(), messageStr)) {
8858 return;
8859 }
8860
8861 nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, "DOM"_ns,
8862 aDocument, PropertiesFile::DOM_PROPERTIES,
8863 "PatternAttributeCompileFailurev2", strings);
8864 savedExc.drop();
8865}
8866
8867// static
8868Maybe<bool> nsContentUtils::IsPatternMatching(const nsAString& aValue,
8869 nsString&& aPattern,
8870 const Document* aDocument,
8871 bool aHasMultiple,
8872 JS::RegExpFlags aFlags) {
8873 NS_ASSERTION(aDocument, "aDocument should be a valid pointer (not null)")do { if (!(aDocument)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "aDocument should be a valid pointer (not null)"
, "aDocument", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8873); MOZ_PretendNoReturn(); } } while (0)
;
8874
8875 // The fact that we're using a JS regexp under the hood should not be visible
8876 // to things like window onerror handlers, so we don't initialize our JSAPI
8877 // with the document's window (which may not exist anyway).
8878 AutoJSAPI jsapi;
8879 jsapi.Init();
8880 JSContext* cx = jsapi.cx();
8881 AutoDisableJSInterruptCallback disabler(cx);
8882
8883 // We can use the junk scope here, because we're just using it for regexp
8884 // evaluation, not actual script execution, and we disable statics so that the
8885 // evaluation does not interact with the execution global.
8886 JSAutoRealm ar(cx, xpc::PrivilegedJunkScope());
8887
8888 // Check if the pattern by itself is valid first, and not that it only becomes
8889 // valid once we add ^(?: and )$.
8890 JS::Rooted<JS::Value> error(cx);
8891 if (!JS::CheckRegExpSyntax(cx, aPattern.BeginReading(), aPattern.Length(),
8892 aFlags, &error)) {
8893 return Nothing();
8894 }
8895
8896 if (!error.isUndefined()) {
8897 ReportPatternCompileFailure(aPattern, aFlags, aDocument, &error, cx);
8898 return Some(true);
8899 }
8900
8901 // The pattern has to match the entire value.
8902 aPattern.InsertLiteral(u"^(?:", 0);
8903 aPattern.AppendLiteral(")$");
8904
8905 JS::Rooted<JSObject*> re(
8906 cx, JS::NewUCRegExpObject(cx, aPattern.BeginReading(), aPattern.Length(),
8907 aFlags));
8908 if (!re) {
8909 return Nothing();
8910 }
8911
8912 JS::Rooted<JS::Value> rval(cx, JS::NullValue());
8913 if (!aHasMultiple) {
8914 size_t idx = 0;
8915 if (!JS::ExecuteRegExpNoStatics(cx, re, aValue.BeginReading(),
8916 aValue.Length(), &idx, true, &rval)) {
8917 return Nothing();
8918 }
8919 return Some(!rval.isNull());
8920 }
8921
8922 HTMLSplitOnSpacesTokenizer tokenizer(aValue, ',');
8923 while (tokenizer.hasMoreTokens()) {
8924 const nsAString& value = tokenizer.nextToken();
8925 size_t idx = 0;
8926 if (!JS::ExecuteRegExpNoStatics(cx, re, value.BeginReading(),
8927 value.Length(), &idx, true, &rval)) {
8928 return Nothing();
8929 }
8930 if (rval.isNull()) {
8931 return Some(false);
8932 }
8933 }
8934 return Some(true);
8935}
8936
8937// static
8938nsresult nsContentUtils::URIInheritsSecurityContext(nsIURI* aURI,
8939 bool* aResult) {
8940 // Note: about:blank URIs do NOT inherit the security context from the
8941 // current document, which is what this function tests for...
8942 return NS_URIChainHasFlags(
8943 aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, aResult);
8944}
8945
8946// static
8947bool nsContentUtils::ChannelShouldInheritPrincipal(
8948 nsIPrincipal* aLoadingPrincipal, nsIURI* aURI, bool aInheritForAboutBlank,
8949 bool aForceInherit) {
8950 MOZ_ASSERT(aLoadingPrincipal,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadingPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadingPrincipal))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aLoadingPrincipal"
" (" "Can not check inheritance without a principal" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Can not check inheritance without a principal" ")"); do
{ MOZ_CrashSequence(__null, 8951); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
8951 "Can not check inheritance without a principal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadingPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadingPrincipal))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aLoadingPrincipal"
" (" "Can not check inheritance without a principal" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8951); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Can not check inheritance without a principal" ")"); do
{ MOZ_CrashSequence(__null, 8951); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
8952
8953 // Only tell the channel to inherit if it can't provide its own security
8954 // context.
8955 //
8956 // XXX: If this is ever changed, check all callers for what owners
8957 // they're passing in. In particular, see the code and
8958 // comments in nsDocShell::LoadURI where we fall back on
8959 // inheriting the owner if called from chrome. That would be
8960 // very wrong if this code changed anything but channels that
8961 // can't provide their own security context!
8962 //
8963 // If aForceInherit is true, we will inherit, even for a channel that
8964 // can provide its own security context. This is used for srcdoc loads.
8965 bool inherit = aForceInherit;
8966 if (!inherit) {
8967 bool uriInherits;
8968 // We expect URIInheritsSecurityContext to return success for an
8969 // about:blank URI, so don't call NS_IsAboutBlank() if this call fails.
8970 // This condition needs to match the one in nsDocShell::InternalLoad where
8971 // we're checking for things that will use the owner.
8972 inherit =
8973 (NS_SUCCEEDED(URIInheritsSecurityContext(aURI, &uriInherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(URIInheritsSecurityContext
(aURI, &uriInherits))), 1)))
&&
8974 (uriInherits || (aInheritForAboutBlank &&
8975 NS_IsAboutBlankAllowQueryAndFragment(aURI)))) ||
8976 //
8977 // file: uri special-casing
8978 //
8979 // If this is a file: load opened from another file: then it may need
8980 // to inherit the owner from the referrer so they can script each other.
8981 // If we don't set the owner explicitly then each file: gets an owner
8982 // based on its own codebase later.
8983 //
8984 (URIIsLocalFile(aURI) &&
8985 NS_SUCCEEDED(aLoadingPrincipal->CheckMayLoad(aURI, false))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aLoadingPrincipal
->CheckMayLoad(aURI, false))), 1)))
&&
8986 // One more check here. CheckMayLoad will always return true for the
8987 // system principal, but we do NOT want to inherit in that case.
8988 !aLoadingPrincipal->IsSystemPrincipal());
8989 }
8990 return inherit;
8991}
8992
8993/* static */
8994bool nsContentUtils::IsCutCopyAllowed(Document* aDocument,
8995 nsIPrincipal& aSubjectPrincipal) {
8996 if (StaticPrefs::dom_allow_cut_copy() && aDocument &&
8997 aDocument->HasValidTransientUserGestureActivation()) {
8998 return true;
8999 }
9000
9001 return PrincipalHasPermission(aSubjectPrincipal, nsGkAtoms::clipboardWrite);
9002}
9003
9004/* static */
9005bool nsContentUtils::HaveEqualPrincipals(Document* aDoc1, Document* aDoc2) {
9006 if (!aDoc1 || !aDoc2) {
9007 return false;
9008 }
9009 bool principalsEqual = false;
9010 aDoc1->NodePrincipal()->Equals(aDoc2->NodePrincipal(), &principalsEqual);
9011 return principalsEqual;
9012}
9013
9014/* static */
9015const Document* nsContentUtils::GetInProcessSubtreeRootDocument(
9016 const Document* aDoc) {
9017 if (!aDoc) {
9018 return nullptr;
9019 }
9020 const Document* doc = aDoc;
9021 while (doc->GetInProcessParentDocument()) {
9022 doc = doc->GetInProcessParentDocument();
9023 }
9024 return doc;
9025}
9026
9027// static
9028bool nsContentUtils::IsPointInSelection(
9029 const mozilla::dom::Selection& aSelection, const nsINode& aNode,
9030 const uint32_t aOffset, const bool aAllowCrossShadowBoundary) {
9031 const bool selectionIsCollapsed =
9032 !aAllowCrossShadowBoundary
9033 ? aSelection.IsCollapsed()
9034 : aSelection.AreNormalAndCrossShadowBoundaryRangesCollapsed();
9035 if (selectionIsCollapsed) {
9036 return false;
9037 }
9038
9039 const uint32_t rangeCount = aSelection.RangeCount();
9040 for (const uint32_t i : IntegerRange(rangeCount)) {
9041 MOZ_ASSERT(aSelection.RangeCount() == rangeCount)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSelection.RangeCount() == rangeCount)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(aSelection.RangeCount() == rangeCount))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aSelection.RangeCount() == rangeCount"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9041); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aSelection.RangeCount() == rangeCount" ")"
); do { MOZ_CrashSequence(__null, 9041); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9042 RefPtr<const dom::Range> range = aSelection.GetRangeAt(i);
9043 if (NS_WARN_IF(!range)NS_warn_if_impl(!range, "!range", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 9043)
) {
9044 // Don't bail yet, iterate through them all
9045 continue;
9046 }
9047
9048 // Done when we find a range that we are in
9049 if (range->IsPointInRange(aNode, aOffset, IgnoreErrors(),
9050 aAllowCrossShadowBoundary)) {
9051 return true;
9052 }
9053 }
9054
9055 return false;
9056}
9057
9058// static
9059void nsContentUtils::GetSelectionInTextControl(Selection* aSelection,
9060 Element* aRoot,
9061 uint32_t& aOutStartOffset,
9062 uint32_t& aOutEndOffset) {
9063 MOZ_ASSERT(aSelection && aRoot)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSelection && aRoot)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aSelection && aRoot)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aSelection && aRoot"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9063); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aSelection && aRoot" ")"); do { MOZ_CrashSequence
(__null, 9063); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9064
9065 // We don't care which end of this selection is anchor and which is focus. In
9066 // fact, we explicitly want to know which is the _start_ and which is the
9067 // _end_, not anchor vs focus.
9068 const dom::Range* range = aSelection->GetAnchorFocusRange();
9069 if (!range) {
9070 // Nothing selected
9071 aOutStartOffset = aOutEndOffset = 0;
9072 return;
9073 }
9074
9075 // All the node pointers here are raw pointers for performance. We shouldn't
9076 // be doing anything in this function that invalidates the node tree.
9077 nsINode* startContainer = range->GetStartContainer();
9078 uint32_t startOffset = range->StartOffset();
9079 nsINode* endContainer = range->GetEndContainer();
9080 uint32_t endOffset = range->EndOffset();
9081
9082 // We have at most two children, consisting of an optional text node followed
9083 // by an optional <br>.
9084 NS_ASSERTION(aRoot->GetChildCount() <= 2, "Unexpected children")do { if (!(aRoot->GetChildCount() <= 2)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Unexpected children", "aRoot->GetChildCount() <= 2"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9084); MOZ_PretendNoReturn
(); } } while (0)
;
9085 nsIContent* firstChild = aRoot->GetFirstChild();
9086#ifdef DEBUG1
9087 nsCOMPtr<nsIContent> lastChild = aRoot->GetLastChild();
9088 NS_ASSERTION(startContainer == aRoot || startContainer == firstChild ||do { if (!(startContainer == aRoot || startContainer == firstChild
|| startContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected startContainer", "startContainer == aRoot || startContainer == firstChild || startContainer == lastChild"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9090); MOZ_PretendNoReturn
(); } } while (0)
9089 startContainer == lastChild,do { if (!(startContainer == aRoot || startContainer == firstChild
|| startContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected startContainer", "startContainer == aRoot || startContainer == firstChild || startContainer == lastChild"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9090); MOZ_PretendNoReturn
(); } } while (0)
9090 "Unexpected startContainer")do { if (!(startContainer == aRoot || startContainer == firstChild
|| startContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected startContainer", "startContainer == aRoot || startContainer == firstChild || startContainer == lastChild"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9090); MOZ_PretendNoReturn
(); } } while (0)
;
9091 NS_ASSERTION(endContainer == aRoot || endContainer == firstChild ||do { if (!(endContainer == aRoot || endContainer == firstChild
|| endContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected endContainer", "endContainer == aRoot || endContainer == firstChild || endContainer == lastChild"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9093); MOZ_PretendNoReturn
(); } } while (0)
9092 endContainer == lastChild,do { if (!(endContainer == aRoot || endContainer == firstChild
|| endContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected endContainer", "endContainer == aRoot || endContainer == firstChild || endContainer == lastChild"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9093); MOZ_PretendNoReturn
(); } } while (0)
9093 "Unexpected endContainer")do { if (!(endContainer == aRoot || endContainer == firstChild
|| endContainer == lastChild)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Unexpected endContainer", "endContainer == aRoot || endContainer == firstChild || endContainer == lastChild"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9093); MOZ_PretendNoReturn
(); } } while (0)
;
9094 // firstChild is either text or a <br> (hence an element).
9095 MOZ_ASSERT_IF(firstChild, firstChild->IsText() || firstChild->IsElement())do { if (firstChild) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(firstChild->IsText() || firstChild->IsElement
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(firstChild->IsText() || firstChild->IsElement(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("firstChild->IsText() || firstChild->IsElement()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 9095); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstChild->IsText() || firstChild->IsElement()"
")"); do { MOZ_CrashSequence(__null, 9095); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
9096#endif
9097 if (!firstChild || firstChild->IsElement()) {
9098 // No text node, so everything is 0
9099 startOffset = endOffset = 0;
9100 } else {
9101 // First child is text. If the start/end is already in the text node,
9102 // or the start of the root node, no change needed. If it's in the root
9103 // node but not the start, or in the trailing <br>, we need to set the
9104 // offset to the end.
9105 if ((startContainer == aRoot && startOffset != 0) ||
9106 (startContainer != aRoot && startContainer != firstChild)) {
9107 startOffset = firstChild->Length();
9108 }
9109 if ((endContainer == aRoot && endOffset != 0) ||
9110 (endContainer != aRoot && endContainer != firstChild)) {
9111 endOffset = firstChild->Length();
9112 }
9113 }
9114
9115 MOZ_ASSERT(startOffset <= endOffset)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(startOffset <= endOffset)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(startOffset <= endOffset)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("startOffset <= endOffset"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9115); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "startOffset <= endOffset" ")"); do { MOZ_CrashSequence
(__null, 9115); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9116 aOutStartOffset = startOffset;
9117 aOutEndOffset = endOffset;
9118}
9119
9120// static
9121HTMLEditor* nsContentUtils::GetHTMLEditor(nsPresContext* aPresContext) {
9122 if (!aPresContext) {
9123 return nullptr;
9124 }
9125 return GetHTMLEditor(aPresContext->GetDocShell());
9126}
9127
9128// static
9129HTMLEditor* nsContentUtils::GetHTMLEditor(nsDocShell* aDocShell) {
9130 bool isEditable;
9131 if (!aDocShell || NS_FAILED(aDocShell->GetEditable(&isEditable))((bool)(__builtin_expect(!!(NS_FAILED_impl(aDocShell->GetEditable
(&isEditable))), 0)))
||
9132 !isEditable) {
9133 return nullptr;
9134 }
9135 return aDocShell->GetHTMLEditor();
9136}
9137
9138// static
9139EditorBase* nsContentUtils::GetActiveEditor(nsPresContext* aPresContext) {
9140 if (!aPresContext) {
9141 return nullptr;
9142 }
9143
9144 return GetActiveEditor(aPresContext->Document()->GetWindow());
9145}
9146
9147// static
9148EditorBase* nsContentUtils::GetActiveEditor(nsPIDOMWindowOuter* aWindow) {
9149 if (!aWindow || !aWindow->GetExtantDoc()) {
9150 return nullptr;
9151 }
9152
9153 // If it's in designMode, nobody can have focus. Therefore, the HTMLEditor
9154 // handles all events. I.e., it's focused editor in this case.
9155 if (aWindow->GetExtantDoc()->IsInDesignMode()) {
9156 return GetHTMLEditor(nsDocShell::Cast(aWindow->GetDocShell()));
9157 }
9158
9159 // If focused element is associated with TextEditor, it must be <input>
9160 // element or <textarea> element. Let's return it even if it's in a
9161 // contenteditable element.
9162 nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
9163 if (Element* focusedElement = nsFocusManager::GetFocusedDescendant(
9164 aWindow, nsFocusManager::SearchRange::eOnlyCurrentWindow,
9165 getter_AddRefs(focusedWindow))) {
9166 if (TextEditor* textEditor = focusedElement->GetTextEditorInternal()) {
9167 return textEditor;
9168 }
9169 }
9170
9171 // Otherwise, HTMLEditor may handle inputs even non-editable element has
9172 // focus or nobody has focus.
9173 return GetHTMLEditor(nsDocShell::Cast(aWindow->GetDocShell()));
9174}
9175
9176// static
9177TextEditor* nsContentUtils::GetExtantTextEditorFromAnonymousNode(
9178 const nsIContent* aAnonymousContent) {
9179 if (!aAnonymousContent) {
9180 return nullptr;
9181 }
9182 nsIContent* parent = aAnonymousContent->FindFirstNonChromeOnlyAccessContent();
9183 if (!parent || parent == aAnonymousContent) {
9184 return nullptr;
9185 }
9186 if (const HTMLInputElement* const inputElement =
9187 HTMLInputElement::FromNodeOrNull(parent)) {
9188 return inputElement->GetExtantTextEditor();
9189 }
9190 if (const HTMLTextAreaElement* const textareaElement =
9191 HTMLTextAreaElement::FromNodeOrNull(parent)) {
9192 return textareaElement->GetExtantTextEditor();
9193 }
9194 return nullptr;
9195}
9196
9197// static
9198bool nsContentUtils::IsNodeInEditableRegion(nsINode* aNode) {
9199 while (aNode) {
9200 if (aNode->IsEditable()) {
9201 return true;
9202 }
9203 aNode = aNode->GetParent();
9204 }
9205 return false;
9206}
9207
9208// static
9209bool nsContentUtils::IsForbiddenRequestHeader(const nsACString& aHeader,
9210 const nsACString& aValue) {
9211 if (IsForbiddenSystemRequestHeader(aHeader)) {
9212 return true;
9213 }
9214
9215 if ((nsContentUtils::IsOverrideMethodHeader(aHeader) &&
9216 nsContentUtils::ContainsForbiddenMethod(aValue))) {
9217 return true;
9218 }
9219
9220 if (StringBeginsWith(aHeader, "proxy-"_ns,
9221 nsCaseInsensitiveCStringComparator) ||
9222 StringBeginsWith(aHeader, "sec-"_ns,
9223 nsCaseInsensitiveCStringComparator)) {
9224 return true;
9225 }
9226
9227 return false;
9228}
9229
9230// static
9231bool nsContentUtils::IsForbiddenSystemRequestHeader(const nsACString& aHeader) {
9232 static const char* kInvalidHeaders[] = {"accept-charset",
9233 "accept-encoding",
9234 "access-control-request-headers",
9235 "access-control-request-method",
9236 "connection",
9237 "content-length",
9238 "cookie",
9239 "cookie2",
9240 "date",
9241 "dnt",
9242 "expect",
9243 "host",
9244 "keep-alive",
9245 "origin",
9246 "referer",
9247 "set-cookie",
9248 "te",
9249 "trailer",
9250 "transfer-encoding",
9251 "upgrade",
9252 "via"};
9253 for (auto& kInvalidHeader : kInvalidHeaders) {
9254 if (aHeader.LowerCaseEqualsASCII(kInvalidHeader)) {
9255 return true;
9256 }
9257 }
9258 return false;
9259}
9260
9261// static
9262bool nsContentUtils::IsForbiddenResponseHeader(const nsACString& aHeader) {
9263 return (aHeader.LowerCaseEqualsASCII("set-cookie") ||
9264 aHeader.LowerCaseEqualsASCII("set-cookie2"));
9265}
9266
9267// static
9268bool nsContentUtils::IsOverrideMethodHeader(const nsACString& headerName) {
9269 return headerName.EqualsIgnoreCase("x-http-method-override") ||
9270 headerName.EqualsIgnoreCase("x-http-method") ||
9271 headerName.EqualsIgnoreCase("x-method-override");
9272}
9273
9274// static
9275bool nsContentUtils::ContainsForbiddenMethod(const nsACString& headerValue) {
9276 bool hasInsecureMethod = false;
9277 nsCCharSeparatedTokenizer tokenizer(headerValue, ',');
9278
9279 while (tokenizer.hasMoreTokens()) {
9280 const nsDependentCSubstring& value = tokenizer.nextToken();
9281
9282 if (value.EqualsIgnoreCase("connect") || value.EqualsIgnoreCase("trace") ||
9283 value.EqualsIgnoreCase("track")) {
9284 hasInsecureMethod = true;
9285 break;
9286 }
9287 }
9288
9289 return hasInsecureMethod;
9290}
9291
9292Maybe<nsContentUtils::ParsedRange> nsContentUtils::ParseSingleRangeRequest(
9293 const nsACString& aHeaderValue, bool aAllowWhitespace) {
9294 // See https://fetch.spec.whatwg.org/#simple-range-header-value
9295 mozilla::Tokenizer p(aHeaderValue);
9296 Maybe<uint64_t> rangeStart;
9297 Maybe<uint64_t> rangeEnd;
9298
9299 // Step 2 and 3
9300 if (!p.CheckWord("bytes")) {
9301 return Nothing();
9302 }
9303
9304 // Step 4
9305 if (aAllowWhitespace) {
9306 p.SkipWhites();
9307 }
9308
9309 // Step 5 and 6
9310 if (!p.CheckChar('=')) {
9311 return Nothing();
9312 }
9313
9314 // Step 7
9315 if (aAllowWhitespace) {
9316 p.SkipWhites();
9317 }
9318
9319 // Step 8 and 9
9320 uint64_t res;
9321 if (p.ReadInteger(&res)) {
9322 rangeStart = Some(res);
9323 }
9324
9325 // Step 10
9326 if (aAllowWhitespace) {
9327 p.SkipWhites();
9328 }
9329
9330 // Step 11
9331 if (!p.CheckChar('-')) {
9332 return Nothing();
9333 }
9334
9335 // Step 13
9336 if (aAllowWhitespace) {
9337 p.SkipWhites();
9338 }
9339
9340 // Step 14 and 15
9341 if (p.ReadInteger(&res)) {
9342 rangeEnd = Some(res);
9343 }
9344
9345 // Step 16
9346 if (!p.CheckEOF()) {
9347 return Nothing();
9348 }
9349
9350 // Step 17
9351 if (!rangeStart && !rangeEnd) {
9352 return Nothing();
9353 }
9354
9355 // Step 18
9356 if (rangeStart && rangeEnd && *rangeStart > *rangeEnd) {
9357 return Nothing();
9358 }
9359
9360 return Some(ParsedRange(rangeStart, rangeEnd));
9361}
9362
9363// static
9364bool nsContentUtils::IsCorsUnsafeRequestHeaderValue(
9365 const nsACString& aHeaderValue) {
9366 const char* cur = aHeaderValue.BeginReading();
9367 const char* end = aHeaderValue.EndReading();
9368
9369 while (cur != end) {
9370 // Implementation of
9371 // https://fetch.spec.whatwg.org/#cors-unsafe-request-header-byte Is less
9372 // than a space but not a horizontal tab
9373 if ((*cur < ' ' && *cur != '\t') || *cur == '"' || *cur == '(' ||
9374 *cur == ')' || *cur == ':' || *cur == '<' || *cur == '>' ||
9375 *cur == '?' || *cur == '@' || *cur == '[' || *cur == '\\' ||
9376 *cur == ']' || *cur == '{' || *cur == '}' ||
9377 *cur == 0x7F) { // 0x75 is DEL
9378 return true;
9379 }
9380 cur++;
9381 }
9382 return false;
9383}
9384
9385// static
9386bool nsContentUtils::IsAllowedNonCorsAccept(const nsACString& aHeaderValue) {
9387 if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) {
9388 return false;
9389 }
9390 return true;
9391}
9392
9393// static
9394bool nsContentUtils::IsAllowedNonCorsContentType(
9395 const nsACString& aHeaderValue) {
9396 nsAutoCString contentType;
9397 nsAutoCString unused;
9398
9399 if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) {
9400 return false;
9401 }
9402
9403 nsresult rv = NS_ParseRequestContentType(aHeaderValue, contentType, unused);
9404 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9405 return false;
9406 }
9407
9408 return contentType.LowerCaseEqualsLiteral("text/plain") ||
9409 contentType.LowerCaseEqualsLiteral(
9410 "application/x-www-form-urlencoded") ||
9411 contentType.LowerCaseEqualsLiteral("multipart/form-data");
9412}
9413
9414// static
9415bool nsContentUtils::IsAllowedNonCorsLanguage(const nsACString& aHeaderValue) {
9416 const char* cur = aHeaderValue.BeginReading();
9417 const char* end = aHeaderValue.EndReading();
9418
9419 while (cur != end) {
9420 if ((*cur >= '0' && *cur <= '9') || (*cur >= 'A' && *cur <= 'Z') ||
9421 (*cur >= 'a' && *cur <= 'z') || *cur == ' ' || *cur == '*' ||
9422 *cur == ',' || *cur == '-' || *cur == '.' || *cur == ';' ||
9423 *cur == '=') {
9424 cur++;
9425 continue;
9426 }
9427 return false;
9428 }
9429 return true;
9430}
9431
9432bool nsContentUtils::IsAllowedNonCorsRange(const nsACString& aHeaderValue) {
9433 Maybe<ParsedRange> parsedRange = ParseSingleRangeRequest(aHeaderValue, false);
9434 if (!parsedRange) {
9435 return false;
9436 }
9437
9438 if (!parsedRange->Start()) {
9439 return false;
9440 }
9441
9442 return true;
9443}
9444
9445// static
9446bool nsContentUtils::IsCORSSafelistedRequestHeader(const nsACString& aName,
9447 const nsACString& aValue) {
9448 // see https://fetch.spec.whatwg.org/#cors-safelisted-request-header
9449 if (aValue.Length() > 128) {
9450 return false;
9451 }
9452 return (aName.LowerCaseEqualsLiteral("accept") &&
9453 nsContentUtils::IsAllowedNonCorsAccept(aValue)) ||
9454 (aName.LowerCaseEqualsLiteral("accept-language") &&
9455 nsContentUtils::IsAllowedNonCorsLanguage(aValue)) ||
9456 (aName.LowerCaseEqualsLiteral("content-language") &&
9457 nsContentUtils::IsAllowedNonCorsLanguage(aValue)) ||
9458 (aName.LowerCaseEqualsLiteral("content-type") &&
9459 nsContentUtils::IsAllowedNonCorsContentType(aValue)) ||
9460 (aName.LowerCaseEqualsLiteral("range") &&
9461 nsContentUtils::IsAllowedNonCorsRange(aValue)) ||
9462 (StaticPrefs::network_http_idempotencyKey_enabled() &&
9463 aName.LowerCaseEqualsLiteral("idempotency-key"));
9464}
9465
9466mozilla::LogModule* nsContentUtils::ResistFingerprintingLog() {
9467 return gResistFingerprintingLog;
9468}
9469mozilla::LogModule* nsContentUtils::DOMDumpLog() { return sDOMDumpLog; }
9470
9471bool nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep,
9472 nsAString& aResult,
9473 const fallible_t& aFallible) {
9474 aResult.Truncate();
9475 return AppendNodeTextContent(aNode, aDeep, aResult, aFallible);
9476}
9477
9478bool nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep,
9479 nsACString& aResult,
9480 const fallible_t& aFallible) {
9481 aResult.Truncate();
9482 return AppendNodeTextContent(aNode, aDeep, aResult, aFallible);
9483}
9484
9485void nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep,
9486 nsAString& aResult) {
9487 if (!GetNodeTextContent(aNode, aDeep, aResult, fallible)) {
9488 NS_ABORT_OOM(0); // Unfortunately we don't know the allocation size
9489 }
9490}
9491
9492void nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep,
9493 nsACString& aResult) {
9494 if (!GetNodeTextContent(aNode, aDeep, aResult, fallible)) {
9495 NS_ABORT_OOM(0); // Unfortunately we don't know the allocation size
9496 }
9497}
9498
9499void nsContentUtils::DestroyMatchString(void* aData) {
9500 if (aData) {
9501 nsString* matchString = static_cast<nsString*>(aData);
9502 delete matchString;
9503 }
9504}
9505
9506// Table ordered from most to least likely JS MIME types.
9507static constexpr std::string_view kJavascriptMIMETypes[] = {
9508 "text/javascript",
9509 "text/ecmascript",
9510 "application/javascript",
9511 "application/ecmascript",
9512 "application/x-javascript",
9513 "application/x-ecmascript",
9514 "text/javascript1.0",
9515 "text/javascript1.1",
9516 "text/javascript1.2",
9517 "text/javascript1.3",
9518 "text/javascript1.4",
9519 "text/javascript1.5",
9520 "text/jscript",
9521 "text/livescript",
9522 "text/x-ecmascript",
9523 "text/x-javascript"};
9524
9525bool nsContentUtils::IsJavascriptMIMEType(const nsAString& aMIMEType) {
9526 for (std::string_view type : kJavascriptMIMETypes) {
9527 if (aMIMEType.LowerCaseEqualsASCII(type.data(), type.length())) {
9528 return true;
9529 }
9530 }
9531 return false;
9532}
9533
9534bool nsContentUtils::IsJavascriptMIMEType(const nsACString& aMIMEType) {
9535 for (std::string_view type : kJavascriptMIMETypes) {
9536 if (aMIMEType.LowerCaseEqualsASCII(type.data(), type.length())) {
9537 return true;
9538 }
9539 }
9540 return false;
9541}
9542
9543// https://mimesniff.spec.whatwg.org/#json-mime-type
9544bool nsContentUtils::IsJsonMimeType(const nsAString& aMimeType) {
9545 // Table ordered from most to least likely JSON MIME types.
9546 static constexpr std::string_view jsonTypes[] = {"application/json",
9547 "text/json"};
9548
9549 for (std::string_view type : jsonTypes) {
9550 if (aMimeType.LowerCaseEqualsASCII(type.data(), type.length())) {
9551 return true;
9552 }
9553 }
9554
9555 // Below checks if the 'subtype' ends in "+json".
9556 RefPtr<MimeType> parsed = MimeType::Parse(aMimeType);
9557 if (!parsed) {
9558 return false;
9559 }
9560
9561 nsAutoString subtype;
9562 parsed->GetSubtype(subtype);
9563 return StringEndsWith(subtype, u"+json"_ns);
9564}
9565
9566// https://html.spec.whatwg.org/#fetch-a-single-module-script, 13.7.3
9567bool nsContentUtils::HasCssMimeTypeEssence(const nsAString& aMimeType) {
9568 nsString contentType, contentCharset;
9569 if (MimeType::Parse(aMimeType, contentType, contentCharset)) {
9570 return contentType.LowerCaseEqualsLiteral("text/css");
9571 }
9572 return false;
9573}
9574
9575// https://html.spec.whatwg.org/#fetch-a-single-module-script, 13.6
9576bool nsContentUtils::HasWasmMimeTypeEssence(const nsAString& aMimeType) {
9577 nsString contentType, contentCharset;
9578 if (MimeType::Parse(aMimeType, contentType, contentCharset)) {
9579 return contentType.LowerCaseEqualsLiteral("application/wasm");
9580 }
9581 return false;
9582}
9583
9584bool nsContentUtils::PrefetchPreloadEnabled(nsIDocShell* aDocShell) {
9585 //
9586 // SECURITY CHECK: disable prefetching and preloading from mailnews!
9587 //
9588 // walk up the docshell tree to see if any containing
9589 // docshell are of type MAIL.
9590 //
9591
9592 if (!aDocShell) {
9593 return false;
9594 }
9595
9596 nsCOMPtr<nsIDocShell> docshell = aDocShell;
9597 nsCOMPtr<nsIDocShellTreeItem> parentItem;
9598
9599 do {
9600 auto appType = docshell->GetAppType();
9601 if (appType == nsIDocShell::APP_TYPE_MAIL) {
9602 return false; // do not prefetch, preload, preconnect from mailnews
9603 }
9604
9605 docshell->GetInProcessParent(getter_AddRefs(parentItem));
9606 if (parentItem) {
9607 docshell = do_QueryInterface(parentItem);
9608 if (!docshell) {
9609 NS_ERROR("cannot get a docshell from a treeItem!")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "cannot get a docshell from a treeItem!"
, "Error", "/root/firefox-clang/dom/base/nsContentUtils.cpp",
9609); MOZ_PretendNoReturn(); } while (0)
;
9610 return false;
9611 }
9612 }
9613 } while (parentItem);
9614
9615 return true;
9616}
9617
9618uint64_t nsContentUtils::GetInnerWindowID(nsIRequest* aRequest) {
9619 // can't do anything if there's no nsIRequest!
9620 if (!aRequest) {
9621 return 0;
9622 }
9623
9624 if (nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest)) {
9625 nsCOMPtr loadInfo = channel->LoadInfo();
9626 if (auto id = loadInfo->GetInnerWindowID()) {
9627 return id;
9628 }
9629 if (auto id = loadInfo->GetTriggeringWindowId()) {
9630 return id;
9631 }
9632 }
9633
9634 nsCOMPtr<nsILoadGroup> loadGroup;
9635 nsresult rv = aRequest->GetLoadGroup(getter_AddRefs(loadGroup));
9636
9637 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadGroup) {
9638 return 0;
9639 }
9640
9641 return GetInnerWindowID(loadGroup);
9642}
9643
9644uint64_t nsContentUtils::GetInnerWindowID(nsILoadGroup* aLoadGroup) {
9645 if (!aLoadGroup) {
9646 return 0;
9647 }
9648
9649 nsCOMPtr<nsIInterfaceRequestor> callbacks;
9650 nsresult rv = aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
9651 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !callbacks) {
9652 return 0;
9653 }
9654
9655 nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
9656 if (!loadContext) {
9657 return 0;
9658 }
9659
9660 nsCOMPtr<mozIDOMWindowProxy> window;
9661 rv = loadContext->GetAssociatedWindow(getter_AddRefs(window));
9662 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !window) {
9663 return 0;
9664 }
9665
9666 auto* pwindow = nsPIDOMWindowOuter::From(window);
9667 if (!pwindow) {
9668 return 0;
9669 }
9670
9671 nsPIDOMWindowInner* inner = pwindow->GetCurrentInnerWindow();
9672 return inner ? inner->WindowID() : 0;
9673}
9674
9675// static
9676void nsContentUtils::MaybeFixIPv6Host(nsACString& aHost) {
9677 if (aHost.FindChar(':') != -1) { // Escape IPv6 address
9678 MOZ_ASSERT(!aHost.IsEmpty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aHost.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aHost.IsEmpty()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!aHost.IsEmpty()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9678); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aHost.IsEmpty()" ")"); do { MOZ_CrashSequence
(__null, 9678); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9679 if (aHost.Length() >= 2 && aHost[0] != '[' &&
9680 aHost[aHost.Length() - 1] != ']') {
9681 aHost.Insert('[', 0);
9682 aHost.Append(']');
9683 }
9684 }
9685}
9686
9687nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI,
9688 nsACString& aHost) {
9689 aHost.Truncate();
9690 nsresult rv = aURI->GetHost(aHost);
9691 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { // Some URIs do not have a host
9692 return rv;
9693 }
9694
9695 MaybeFixIPv6Host(aHost);
9696
9697 return NS_OK;
9698}
9699
9700nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI,
9701 nsAString& aHost) {
9702 nsAutoCString hostname;
9703 nsresult rv = GetHostOrIPv6WithBrackets(aURI, hostname);
9704 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9705 return rv;
9706 }
9707 CopyUTF8toUTF16(hostname, aHost);
9708 return NS_OK;
9709}
9710
9711nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIPrincipal* aPrincipal,
9712 nsACString& aHost) {
9713 nsresult rv = aPrincipal->GetAsciiHost(aHost);
9714 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { // Some URIs do not have a host
9715 return rv;
9716 }
9717
9718 MaybeFixIPv6Host(aHost);
9719 return NS_OK;
9720}
9721
9722nsresult nsContentUtils::GetAsciiHostOrIPv6WithBrackets(nsIURI* aURI,
9723 nsACString& aHost) {
9724 aHost.Truncate();
9725 nsresult rv = aURI->GetAsciiHost(aHost);
9726 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9727 return rv;
9728 }
9729
9730 MaybeFixIPv6Host(aHost);
9731 return NS_OK;
9732}
9733
9734CallState nsContentUtils::CallOnAllRemoteChildren(
9735 MessageBroadcaster* aManager,
9736 const std::function<CallState(BrowserParent*)>& aCallback) {
9737 uint32_t browserChildCount = aManager->ChildCount();
9738 for (uint32_t j = 0; j < browserChildCount; ++j) {
9739 RefPtr<MessageListenerManager> childMM = aManager->GetChildAt(j);
9740 if (!childMM) {
9741 continue;
9742 }
9743
9744 RefPtr<MessageBroadcaster> nonLeafMM = MessageBroadcaster::From(childMM);
9745 if (nonLeafMM) {
9746 if (CallOnAllRemoteChildren(nonLeafMM, aCallback) == CallState::Stop) {
9747 return CallState::Stop;
9748 }
9749 continue;
9750 }
9751
9752 mozilla::dom::ipc::MessageManagerCallback* cb = childMM->GetCallback();
9753 if (cb) {
9754 nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb);
9755 BrowserParent* remote = BrowserParent::GetFrom(fl);
9756 if (remote && aCallback) {
9757 if (aCallback(remote) == CallState::Stop) {
9758 return CallState::Stop;
9759 }
9760 }
9761 }
9762 }
9763
9764 return CallState::Continue;
9765}
9766
9767void nsContentUtils::CallOnAllRemoteChildren(
9768 nsPIDOMWindowOuter* aWindow,
9769 const std::function<CallState(BrowserParent*)>& aCallback) {
9770 nsGlobalWindowOuter* window = nsGlobalWindowOuter::Cast(aWindow);
9771 if (window->IsChromeWindow()) {
9772 RefPtr<MessageBroadcaster> windowMM = window->GetMessageManager();
9773 if (windowMM) {
9774 CallOnAllRemoteChildren(windowMM, aCallback);
9775 }
9776 }
9777}
9778
9779bool nsContentUtils::IPCTransferableDataItemHasKnownFlavor(
9780 const IPCTransferableDataItem& aItem) {
9781 // Unknown types are converted to kCustomTypesMime.
9782 if (aItem.flavor().EqualsASCII(kCustomTypesMime"application/x-moz-custom-clipdata")) {
9783 return true;
9784 }
9785
9786 for (const char* format : DataTransfer::kKnownFormats) {
9787 if (aItem.flavor().EqualsASCII(format)) {
9788 return true;
9789 }
9790 }
9791
9792 // Clipboard custom type. Only recognise "web foo/bar" as a known flavor
9793 // when the web custom format feature is enabled; otherwise DnD or other
9794 // callers must not be able to slip web custom flavors through this helper.
9795 const nsCString& flavor = aItem.flavor();
9796 if (StaticPrefs::dom_clipboard_customFormatSupport_enabled() &&
9797 StringBeginsWith(flavor, nsLiteralCString(kWebCustomFormatPrefix"web "))) {
9798 if (RefPtr<CMimeType> parsedType = CMimeType::Parse(Substring(
9799 flavor, strlen(kWebCustomFormatPrefix"web "), flavor.Length()))) {
9800 return true;
9801 }
9802 }
9803
9804 return false;
9805}
9806
9807nsresult nsContentUtils::IPCTransferableDataToTransferable(
9808 const IPCTransferableData& aTransferableData, bool aAddDataFlavor,
9809 nsITransferable* aTransferable, const bool aFilterUnknownFlavors) {
9810 nsresult rv;
9811 const nsTArray<IPCTransferableDataItem>& items = aTransferableData.items();
9812 for (const auto& item : items) {
9813 if (aFilterUnknownFlavors) {
9814 if (item.flavor().EqualsLiteral(kFilePromiseDirectoryMime"application/x-moz-file-promise-dir")) {
9815 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9817)
9816 "Ignoring unknown flavor in "NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9817)
9817 "nsContentUtils::IPCTransferableDataToTransferable")NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9817)
;
9818 continue;
9819 }
9820
9821 if ((item.flavor().EqualsLiteral(kFilePromiseMime"application/x-moz-file-promise") ||
9822 item.flavor().EqualsLiteral(kFilePromiseURLMime"application/x-moz-file-promise-url") ||
9823 item.flavor().EqualsLiteral(kFilePromiseDestFilename"application/x-moz-file-promise-dest-filename"))
9824#ifdef XP_WIN
9825 && !StaticPrefs::clipboard_imageAsFile_enabled()
9826#endif
9827 ) {
9828 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9830)
9829 "Ignoring unknown flavor in "NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9830)
9830 "nsContentUtils::IPCTransferableDataToTransferable")NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9830)
;
9831 continue;
9832 }
9833
9834 if (!IPCTransferableDataItemHasKnownFlavor(item)) {
9835 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9837)
9836 "Ignoring unknown flavor in "NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9837)
9837 "nsContentUtils::IPCTransferableDataToTransferable")NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9837)
;
9838 continue;
9839 }
9840 }
9841
9842 if (aAddDataFlavor) {
9843 aTransferable->AddDataFlavor(item.flavor().get());
9844 }
9845
9846 nsCOMPtr<nsISupports> transferData;
9847 switch (item.data().type()) {
9848 case IPCTransferableDataType::TIPCTransferableDataString: {
9849 const auto& data = item.data().get_IPCTransferableDataString();
9850 nsCOMPtr<nsISupportsString> dataWrapper =
9851 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv);
9852 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 9852); return rv; } } while (false)
;
9853 rv = dataWrapper->SetData(nsDependentSubstring(
9854 reinterpret_cast<const char16_t*>(data.data().Data()),
9855 data.data().Size() / sizeof(char16_t)));
9856 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 9856); return rv; } } while (false)
;
9857 transferData = dataWrapper;
9858 break;
9859 }
9860 case IPCTransferableDataType::TIPCTransferableDataCString: {
9861 const auto& data = item.data().get_IPCTransferableDataCString();
9862 nsCOMPtr<nsISupportsCString> dataWrapper =
9863 do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID"@mozilla.org/supports-cstring;1", &rv);
9864 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 9864); return rv; } } while (false)
;
9865 rv = dataWrapper->SetData(nsDependentCSubstring(
9866 reinterpret_cast<const char*>(data.data().Data()),
9867 data.data().Size()));
9868 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 9868); return rv; } } while (false)
;
9869 transferData = dataWrapper;
9870 break;
9871 }
9872 case IPCTransferableDataType::TIPCTransferableDataInputStream: {
9873 const auto& data = item.data().get_IPCTransferableDataInputStream();
9874 nsCOMPtr<nsIInputStream> stream;
9875 rv = NS_NewByteInputStream(getter_AddRefs(stream),
9876 AsChars(data.data().AsSpan()),
9877 NS_ASSIGNMENT_COPY);
9878 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 9878); return rv; } } while (false)
;
9879 transferData = stream.forget();
9880 break;
9881 }
9882 case IPCTransferableDataType::TIPCTransferableDataImageContainer: {
9883 const auto& data = item.data().get_IPCTransferableDataImageContainer();
9884 nsCOMPtr<imgIContainer> container = IPCImageToImage(data.image());
9885 if (!container) {
9886 return NS_ERROR_FAILURE;
9887 }
9888 transferData = container;
9889 break;
9890 }
9891 case IPCTransferableDataType::TIPCTransferableDataBlob: {
9892 const auto& data = item.data().get_IPCTransferableDataBlob();
9893 transferData = IPCBlobUtils::Deserialize(data.blob());
9894 break;
9895 }
9896 case IPCTransferableDataType::T__None:
9897 MOZ_ASSERT_UNREACHABLE()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: "
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9897
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
")"); do { MOZ_CrashSequence(__null, 9897); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9898 return NS_ERROR_FAILURE;
9899 }
9900
9901 rv = aTransferable->SetTransferData(item.flavor().get(), transferData);
9902 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 9902); return rv; } } while (false)
;
9903 }
9904 return NS_OK;
9905}
9906
9907nsresult nsContentUtils::IPCTransferableToTransferable(
9908 const IPCTransferable& aIPCTransferable, bool aAddDataFlavor,
9909 nsITransferable* aTransferable, const bool aFilterUnknownFlavors) {
9910 // Note that we need to set privacy status of transferable before adding any
9911 // data into it.
9912 aTransferable->SetIsPrivateData(aIPCTransferable.isPrivateData());
9913
9914 nsresult rv =
9915 IPCTransferableDataToTransferable(aIPCTransferable.data(), aAddDataFlavor,
9916 aTransferable, aFilterUnknownFlavors);
9917 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 9917); return rv; } } while (false)
;
9918
9919 if (aIPCTransferable.cookieJarSettings().isSome()) {
9920 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
9921 net::CookieJarSettings::Deserialize(
9922 aIPCTransferable.cookieJarSettings().ref(),
9923 getter_AddRefs(cookieJarSettings));
9924 aTransferable->SetCookieJarSettings(cookieJarSettings);
9925 }
9926 aTransferable->SetReferrerInfo(aIPCTransferable.referrerInfo());
9927 aTransferable->SetDataPrincipal(aIPCTransferable.dataPrincipal());
9928 aTransferable->SetContentPolicyType(aIPCTransferable.contentPolicyType());
9929
9930 return NS_OK;
9931}
9932
9933nsresult nsContentUtils::IPCTransferableDataItemToVariant(
9934 const IPCTransferableDataItem& aItem, nsIWritableVariant* aVariant) {
9935 MOZ_ASSERT(aVariant)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aVariant)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aVariant))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aVariant", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 9935); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aVariant" ")"
); do { MOZ_CrashSequence(__null, 9935); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9936
9937 switch (aItem.data().type()) {
9938 case IPCTransferableDataType::TIPCTransferableDataString: {
9939 const auto& data = aItem.data().get_IPCTransferableDataString();
9940 return aVariant->SetAsAString(nsDependentSubstring(
9941 reinterpret_cast<const char16_t*>(data.data().Data()),
9942 data.data().Size() / sizeof(char16_t)));
9943 }
9944 case IPCTransferableDataType::TIPCTransferableDataCString: {
9945 const auto& data = aItem.data().get_IPCTransferableDataCString();
9946 return aVariant->SetAsACString(nsDependentCSubstring(
9947 reinterpret_cast<const char*>(data.data().Data()),
9948 data.data().Size()));
9949 }
9950 case IPCTransferableDataType::TIPCTransferableDataInputStream: {
9951 const auto& data = aItem.data().get_IPCTransferableDataInputStream();
9952 nsCOMPtr<nsIInputStream> stream;
9953 nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
9954 AsChars(data.data().AsSpan()),
9955 NS_ASSIGNMENT_COPY);
9956 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 9956); return rv; } } while (false)
;
9957 return aVariant->SetAsISupports(stream);
9958 }
9959 case IPCTransferableDataType::TIPCTransferableDataImageContainer: {
9960 const auto& data = aItem.data().get_IPCTransferableDataImageContainer();
9961 nsCOMPtr<imgIContainer> container = IPCImageToImage(data.image());
9962 if (!container) {
9963 return NS_ERROR_FAILURE;
9964 }
9965 return aVariant->SetAsISupports(container);
9966 }
9967 case IPCTransferableDataType::TIPCTransferableDataBlob: {
9968 const auto& data = aItem.data().get_IPCTransferableDataBlob();
9969 RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(data.blob());
9970 return aVariant->SetAsISupports(blobImpl);
9971 }
9972 case IPCTransferableDataType::T__None:
9973 break;
9974 }
9975
9976 MOZ_ASSERT_UNREACHABLE()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: "
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9976
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
")"); do { MOZ_CrashSequence(__null, 9976); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9977 return NS_ERROR_UNEXPECTED;
9978}
9979
9980void nsContentUtils::TransferablesToIPCTransferableDatas(
9981 nsIArray* aTransferables, nsTArray<IPCTransferableData>& aIPC,
9982 bool aInSyncMessage, mozilla::dom::ContentParent* aParent) {
9983 aIPC.Clear();
9984 if (aTransferables) {
9985 uint32_t transferableCount = 0;
9986 aTransferables->GetLength(&transferableCount);
9987 for (uint32_t i = 0; i < transferableCount; ++i) {
9988 IPCTransferableData* dt = aIPC.AppendElement();
9989 nsCOMPtr<nsITransferable> transferable =
9990 do_QueryElementAt(aTransferables, i);
9991 TransferableToIPCTransferableData(transferable, dt, aInSyncMessage,
9992 aParent);
9993 }
9994 }
9995}
9996
9997nsresult nsContentUtils::CalculateBufferSizeForImage(
9998 const uint32_t& aStride, const IntSize& aImageSize,
9999 const SurfaceFormat& aFormat, size_t* aMaxBufferSize,
10000 size_t* aUsedBufferSize) {
10001 if (aImageSize.width <= 0 || aImageSize.height <= 0) {
10002 return NS_ERROR_FAILURE;
10003 }
10004
10005 CheckedInt32 rowBytes =
10006 CheckedInt32(aImageSize.width) * BytesPerPixel(aFormat);
10007 CheckedInt32 stride(aStride);
10008 if (!rowBytes.isValid() || !stride.isValid() ||
10009 stride.value() < rowBytes.value()) {
10010 return NS_ERROR_FAILURE;
10011 }
10012
10013 CheckedInt32 requiredBytes = stride * CheckedInt32(aImageSize.height);
10014 CheckedInt32 usedBytes = requiredBytes - stride + rowBytes;
10015 if (!requiredBytes.isValid() || !usedBytes.isValid()) {
10016 return NS_ERROR_FAILURE;
10017 }
10018
10019 *aMaxBufferSize = requiredBytes.value();
10020 *aUsedBufferSize = usedBytes.value();
10021 return NS_OK;
10022}
10023
10024static already_AddRefed<DataSourceSurface> BigBufferToDataSurface(
10025 const BigBuffer& aData, uint32_t aStride, const IntSize& aImageSize,
10026 SurfaceFormat aFormat) {
10027 if (!aData.Size() || !aImageSize.width || !aImageSize.height) {
10028 return nullptr;
10029 }
10030
10031 // Validate shared memory buffer size
10032 size_t imageBufLen = 0;
10033 size_t maxBufLen = 0;
10034 if (NS_FAILED(nsContentUtils::CalculateBufferSizeForImage(((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::CalculateBufferSizeForImage
( aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen
))), 0)))
10035 aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::CalculateBufferSizeForImage
( aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen
))), 0)))
) {
10036 return nullptr;
10037 }
10038 if (imageBufLen > aData.Size()) {
10039 return nullptr;
10040 }
10041 return CreateDataSourceSurfaceFromData(aImageSize, aFormat, aData.Data(),
10042 aStride);
10043}
10044
10045bool nsContentUtils::IsFlavorImage(const nsACString& aFlavor) {
10046 return aFlavor.EqualsLiteral(kNativeImageMime"application/x-moz-nativeimage") ||
10047 aFlavor.EqualsLiteral(kJPEGImageMime"image/jpeg") ||
10048 aFlavor.EqualsLiteral(kJPGImageMime"image/jpg") ||
10049 aFlavor.EqualsLiteral(kPNGImageMime"image/png") ||
10050 aFlavor.EqualsLiteral(kGIFImageMime"image/gif");
10051}
10052
10053// FIXME: This can probably be removed once bug 1783240 lands, as `nsString`
10054// will be implicitly serialized in shmem when sent over IPDL directly.
10055static IPCTransferableDataString AsIPCTransferableDataString(
10056 Span<const char16_t> aInput) {
10057 return IPCTransferableDataString{BigBuffer(AsBytes(aInput))};
10058}
10059
10060// FIXME: This can probably be removed once bug 1783240 lands, as `nsCString`
10061// will be implicitly serialized in shmem when sent over IPDL directly.
10062static IPCTransferableDataCString AsIPCTransferableDataCString(
10063 Span<const char> aInput) {
10064 return IPCTransferableDataCString{BigBuffer(AsBytes(aInput))};
10065}
10066
10067void nsContentUtils::TransferableToIPCTransferableData(
10068 nsITransferable* aTransferable, IPCTransferableData* aTransferableData,
10069 bool aInSyncMessage, mozilla::dom::ContentParent* aParent) {
10070 MOZ_ASSERT_IF(XRE_IsParentProcess(), aParent)do { if (XRE_IsParentProcess()) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(aParent)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aParent))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aParent", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10070); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent" ")"
); do { MOZ_CrashSequence(__null, 10070); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
10071
10072 if (aTransferable) {
10073 nsTArray<nsCString> flavorList;
10074 aTransferable->FlavorsTransferableCanExport(flavorList);
10075
10076 for (uint32_t j = 0; j < flavorList.Length(); ++j) {
10077 nsCString& flavorStr = flavorList[j];
10078 if (!flavorStr.Length()) {
10079 continue;
10080 }
10081
10082 nsCOMPtr<nsISupports> data;
10083 nsresult rv =
10084 aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(data));
10085
10086 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !data) {
10087 if (aInSyncMessage) {
10088 // Can't do anything.
10089 // FIXME: This shouldn't be the case anymore!
10090 continue;
10091 }
10092
10093 // This is a hack to support kFilePromiseMime.
10094 // On Windows there just needs to be an entry for it,
10095 // and for OSX we need to create
10096 // nsContentAreaDragDropDataProvider as nsIFlavorDataProvider.
10097 if (flavorStr.EqualsLiteral(kFilePromiseMime"application/x-moz-file-promise")) {
10098 IPCTransferableDataItem* item =
10099 aTransferableData->items().AppendElement();
10100 item->flavor() = flavorStr;
10101 item->data() =
10102 AsIPCTransferableDataString(NS_ConvertUTF8toUTF16(flavorStr));
10103 continue;
10104 }
10105
10106 // Empty element, transfer only the flavor
10107 IPCTransferableDataItem* item =
10108 aTransferableData->items().AppendElement();
10109 item->flavor() = flavorStr;
10110 item->data() = AsIPCTransferableDataString(EmptyString());
10111 continue;
10112 }
10113
10114 // We need to handle nsIInputStream before nsISupportsCString, otherwise
10115 // nsStringInputStream would be converted into a wrong type.
10116 if (nsCOMPtr<nsIInputStream> stream = do_QueryInterface(data)) {
10117 IPCTransferableDataItem* item =
10118 aTransferableData->items().AppendElement();
10119 item->flavor() = flavorStr;
10120 nsCString imageData;
10121 DebugOnly<nsresult> rv =
10122 NS_ConsumeStream(stream, UINT32_MAX(4294967295U), imageData);
10123 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(rv != NS_BASE_STREAM_WOULD_BLOCK)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(rv != NS_BASE_STREAM_WOULD_BLOCK
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"rv != NS_BASE_STREAM_WOULD_BLOCK" " (" "cannot use async input streams in nsITransferable right now"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10125
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK"
") (" "cannot use async input streams in nsITransferable right now"
")"); do { MOZ_CrashSequence(__null, 10125); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10124 rv != NS_BASE_STREAM_WOULD_BLOCK,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(rv != NS_BASE_STREAM_WOULD_BLOCK)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(rv != NS_BASE_STREAM_WOULD_BLOCK
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"rv != NS_BASE_STREAM_WOULD_BLOCK" " (" "cannot use async input streams in nsITransferable right now"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10125
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK"
") (" "cannot use async input streams in nsITransferable right now"
")"); do { MOZ_CrashSequence(__null, 10125); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10125 "cannot use async input streams in nsITransferable right now")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(rv != NS_BASE_STREAM_WOULD_BLOCK)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(rv != NS_BASE_STREAM_WOULD_BLOCK
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"rv != NS_BASE_STREAM_WOULD_BLOCK" " (" "cannot use async input streams in nsITransferable right now"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10125
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK"
") (" "cannot use async input streams in nsITransferable right now"
")"); do { MOZ_CrashSequence(__null, 10125); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10126 // FIXME: This can probably be simplified once bug 1783240 lands, as
10127 // `nsCString` will be implicitly serialized in shmem when sent over
10128 // IPDL directly.
10129 item->data() =
10130 IPCTransferableDataInputStream(BigBuffer(AsBytes(Span(imageData))));
10131 continue;
10132 }
10133
10134 if (nsCOMPtr<nsISupportsString> text = do_QueryInterface(data)) {
10135 nsAutoString dataAsString;
10136 MOZ_ALWAYS_SUCCEEDS(text->GetData(dataAsString))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(text->GetData(dataAsString))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(text->GetData(dataAsString))"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10136); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(text->GetData(dataAsString))" ")"
); do { MOZ_CrashSequence(__null, 10136); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
10137
10138 IPCTransferableDataItem* item =
10139 aTransferableData->items().AppendElement();
10140 item->flavor() = flavorStr;
10141 item->data() = AsIPCTransferableDataString(dataAsString);
10142 continue;
10143 }
10144
10145 if (nsCOMPtr<nsISupportsCString> ctext = do_QueryInterface(data)) {
10146 nsAutoCString dataAsString;
10147 MOZ_ALWAYS_SUCCEEDS(ctext->GetData(dataAsString))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(ctext->GetData(dataAsString))), 1)))), 1))) { } else { do
{ do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(ctext->GetData(dataAsString))"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10147); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(ctext->GetData(dataAsString))"
")"); do { MOZ_CrashSequence(__null, 10147); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
10148
10149 IPCTransferableDataItem* item =
10150 aTransferableData->items().AppendElement();
10151 item->flavor() = flavorStr;
10152 item->data() = AsIPCTransferableDataCString(dataAsString);
10153 continue;
10154 }
10155
10156 if (nsCOMPtr<imgIContainer> image = do_QueryInterface(data)) {
10157 // Images to be placed on the clipboard are imgIContainers.
10158 RefPtr<mozilla::gfx::SourceSurface> surface = image->GetFrame(
10159 imgIContainer::FRAME_CURRENT,
10160 imgIContainer::FLAG_SYNC_DECODE | imgIContainer::FLAG_ASYNC_NOTIFY);
10161 if (!surface) {
10162 continue;
10163 }
10164 RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
10165 surface->GetDataSurface();
10166 if (!dataSurface) {
10167 continue;
10168 }
10169
10170 auto imageData = nsContentUtils::SurfaceToIPCImage(*dataSurface);
10171 if (!imageData) {
10172 continue;
10173 }
10174
10175 IPCTransferableDataItem* item =
10176 aTransferableData->items().AppendElement();
10177 item->flavor() = flavorStr;
10178 item->data() = IPCTransferableDataImageContainer(std::move(*imageData));
10179 continue;
10180 }
10181
10182 // Otherwise, handle this as a file.
10183 nsCOMPtr<BlobImpl> blobImpl;
10184 if (nsCOMPtr<nsIFile> file = do_QueryInterface(data)) {
10185 if (aParent) {
10186 bool isDir = false;
10187 if (NS_SUCCEEDED(file->IsDirectory(&isDir))((bool)(__builtin_expect(!!(!NS_FAILED_impl(file->IsDirectory
(&isDir))), 1)))
&& isDir) {
10188 nsAutoString path;
10189 if (NS_WARN_IF(NS_FAILED(file->GetPath(path)))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(file
->GetPath(path))), 0))), "NS_FAILED(file->GetPath(path))"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10189)
) {
10190 continue;
10191 }
10192
10193 RefPtr<FileSystemSecurity> fss = FileSystemSecurity::GetOrCreate();
10194 fss->GrantAccessToContentProcess(aParent->ChildID(), path);
10195 }
10196 }
10197
10198 blobImpl = new FileBlobImpl(file);
10199
10200 IgnoredErrorResult rv;
10201
10202 // Ensure that file data is cached no that the content process
10203 // has this data available to it when passed over:
10204 blobImpl->GetSize(rv);
10205 if (NS_WARN_IF(rv.Failed())NS_warn_if_impl(rv.Failed(), "rv.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10205)
) {
10206 continue;
10207 }
10208
10209 blobImpl->GetLastModified(rv);
10210 if (NS_WARN_IF(rv.Failed())NS_warn_if_impl(rv.Failed(), "rv.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10210)
) {
10211 continue;
10212 }
10213 } else {
10214 if (aInSyncMessage) {
10215 // Can't do anything.
10216 // FIXME: This shouldn't be the case anymore!
10217 continue;
10218 }
10219
10220 blobImpl = do_QueryInterface(data);
10221 }
10222
10223 if (blobImpl) {
10224 // If we failed to create the blob actor, then this blob probably
10225 // can't get the file size for the underlying file, ignore it for
10226 // now. TODO pass this through anyway.
10227 IPCBlob ipcBlob;
10228 nsresult rv = IPCBlobUtils::Serialize(blobImpl, ipcBlob);
10229 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10229)
) {
10230 continue;
10231 }
10232
10233 IPCTransferableDataItem* item =
10234 aTransferableData->items().AppendElement();
10235 item->flavor() = flavorStr;
10236 item->data() = IPCTransferableDataBlob(ipcBlob);
10237 }
10238 }
10239 }
10240}
10241
10242void nsContentUtils::TransferableToIPCTransferable(
10243 nsITransferable* aTransferable, IPCTransferable* aIPCTransferable,
10244 bool aInSyncMessage, mozilla::dom::ContentParent* aParent) {
10245 IPCTransferableData ipcTransferableData;
10246 TransferableToIPCTransferableData(aTransferable, &ipcTransferableData,
10247 aInSyncMessage, aParent);
10248
10249 Maybe<net::CookieJarSettingsArgs> cookieJarSettingsArgs;
10250 if (nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
10251 aTransferable->GetCookieJarSettings()) {
10252 net::CookieJarSettingsArgs args;
10253 net::CookieJarSettings::Cast(cookieJarSettings)->Serialize(args);
10254 cookieJarSettingsArgs = Some(std::move(args));
10255 }
10256
10257 aIPCTransferable->data() = std::move(ipcTransferableData);
10258 aIPCTransferable->isPrivateData() = aTransferable->GetIsPrivateData();
10259 aIPCTransferable->dataPrincipal() = aTransferable->GetDataPrincipal();
10260 aIPCTransferable->cookieJarSettings() = std::move(cookieJarSettingsArgs);
10261 aIPCTransferable->contentPolicyType() = aTransferable->GetContentPolicyType();
10262 aIPCTransferable->referrerInfo() = aTransferable->GetReferrerInfo();
10263}
10264
10265Maybe<BigBuffer> nsContentUtils::GetSurfaceData(DataSourceSurface& aSurface,
10266 size_t* aLength,
10267 int32_t* aStride) {
10268 mozilla::gfx::DataSourceSurface::MappedSurface map;
10269 if (!aSurface.Map(mozilla::gfx::DataSourceSurface::MapType::READ, &map)) {
10270 return Nothing();
10271 }
10272
10273 size_t bufLen = 0;
10274 size_t maxBufLen = 0;
10275 nsresult rv = nsContentUtils::CalculateBufferSizeForImage(
10276 map.mStride, aSurface.GetSize(), aSurface.GetFormat(), &maxBufLen,
10277 &bufLen);
10278 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10279 aSurface.Unmap();
10280 return Nothing();
10281 }
10282
10283 BigBuffer surfaceData = BigBuffer::TryAlloc(maxBufLen);
10284 if (surfaceData.Size() != maxBufLen) {
10285 aSurface.Unmap();
10286 return Nothing();
10287 }
10288 memcpy(surfaceData.Data(), map.mData, bufLen);
10289 memset(surfaceData.Data() + bufLen, 0, maxBufLen - bufLen);
10290
10291 *aLength = maxBufLen;
10292 *aStride = map.mStride;
10293
10294 aSurface.Unmap();
10295 return Some(std::move(surfaceData));
10296}
10297
10298Maybe<IPCImage> nsContentUtils::SurfaceToIPCImage(DataSourceSurface& aSurface) {
10299 size_t len = 0;
10300 int32_t stride = 0;
10301 auto mem = GetSurfaceData(aSurface, &len, &stride);
10302 if (!mem) {
10303 return Nothing();
10304 }
10305 return Some(IPCImage{std::move(*mem), uint32_t(stride), aSurface.GetFormat(),
10306 ImageIntSize::FromUnknownSize(aSurface.GetSize())});
10307}
10308
10309already_AddRefed<DataSourceSurface> nsContentUtils::IPCImageToSurface(
10310 const IPCImage& aImage) {
10311 return BigBufferToDataSurface(aImage.data(), aImage.stride(),
10312 aImage.size().ToUnknownSize(), aImage.format());
10313}
10314
10315already_AddRefed<imgIContainer> nsContentUtils::IPCImageToImage(
10316 const IPCImage& aImage) {
10317 RefPtr<DataSourceSurface> surface = IPCImageToSurface(aImage);
10318 if (!surface) {
10319 return nullptr;
10320 }
10321
10322 auto drawable = MakeRefPtr<gfxSurfaceDrawable>(surface, surface->GetSize());
10323 nsCOMPtr<imgIContainer> imageContainer =
10324 image::ImageOps::CreateFromDrawable(drawable);
10325 return imageContainer.forget();
10326}
10327
10328Modifiers nsContentUtils::GetWidgetModifiers(int32_t aModifiers) {
10329 Modifiers result = 0;
10330 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SHIFT) {
10331 result |= mozilla::MODIFIER_SHIFT;
10332 }
10333 if (aModifiers & nsIDOMWindowUtils::MODIFIER_CONTROL) {
10334 result |= mozilla::MODIFIER_CONTROL;
10335 }
10336 if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALT) {
10337 result |= mozilla::MODIFIER_ALT;
10338 }
10339 if (aModifiers & nsIDOMWindowUtils::MODIFIER_META) {
10340 result |= mozilla::MODIFIER_META;
10341 }
10342 if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALTGRAPH) {
10343 result |= mozilla::MODIFIER_ALTGRAPH;
10344 }
10345 if (aModifiers & nsIDOMWindowUtils::MODIFIER_CAPSLOCK) {
10346 result |= mozilla::MODIFIER_CAPSLOCK;
10347 }
10348 if (aModifiers & nsIDOMWindowUtils::MODIFIER_FN) {
10349 result |= mozilla::MODIFIER_FN;
10350 }
10351 if (aModifiers & nsIDOMWindowUtils::MODIFIER_FNLOCK) {
10352 result |= mozilla::MODIFIER_FNLOCK;
10353 }
10354 if (aModifiers & nsIDOMWindowUtils::MODIFIER_NUMLOCK) {
10355 result |= mozilla::MODIFIER_NUMLOCK;
10356 }
10357 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SCROLLLOCK) {
10358 result |= mozilla::MODIFIER_SCROLLLOCK;
10359 }
10360 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOL) {
10361 result |= mozilla::MODIFIER_SYMBOL;
10362 }
10363 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOLLOCK) {
10364 result |= mozilla::MODIFIER_SYMBOLLOCK;
10365 }
10366 return result;
10367}
10368
10369nsIWidget* nsContentUtils::GetWidget(PresShell* aPresShell, nsPoint* aOffset) {
10370 if (!aPresShell) {
10371 return nullptr;
10372 }
10373 nsIFrame* frame = aPresShell->GetRootFrame();
10374 if (!frame) {
10375 return nullptr;
10376 }
10377 return aOffset ? frame->GetNearestWidget(*aOffset)
10378 : frame->GetNearestWidget();
10379}
10380
10381int16_t nsContentUtils::GetButtonsFlagForButton(int32_t aButton) {
10382 switch (aButton) {
10383 case -1:
10384 return MouseButtonsFlag::eNoButtons;
10385 case MouseButton::ePrimary:
10386 return MouseButtonsFlag::ePrimaryFlag;
10387 case MouseButton::eMiddle:
10388 return MouseButtonsFlag::eMiddleFlag;
10389 case MouseButton::eSecondary:
10390 return MouseButtonsFlag::eSecondaryFlag;
10391 case 3:
10392 return MouseButtonsFlag::e4thFlag;
10393 case 4:
10394 return MouseButtonsFlag::e5thFlag;
10395 case MouseButton::eEraser:
10396 return MouseButtonsFlag::eEraserFlag;
10397 default:
10398 NS_ERROR("Button not known.")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Button not known.", "Error"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10398); MOZ_PretendNoReturn
(); } while (0)
;
10399 return 0;
10400 }
10401}
10402
10403LayoutDeviceIntPoint nsContentUtils::ToWidgetPoint(
10404 const CSSPoint& aPoint, const nsPoint& aOffset,
10405 nsPresContext* aPresContext) {
10406 nsPoint layoutRelative = CSSPoint::ToAppUnits(aPoint) + aOffset;
10407 nsPoint visualRelative =
10408 ViewportUtils::LayoutToVisual(layoutRelative, aPresContext->PresShell());
10409 return LayoutDeviceIntPoint::FromAppUnitsRounded(
10410 visualRelative, aPresContext->AppUnitsPerDevPixel());
10411}
10412
10413namespace {
10414
10415class SynthesizedEventCallback final : public nsISynthesizedEventCallback {
10416 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
10417
10418 public:
10419 explicit SynthesizedEventCallback(VoidFunction& aCallback)
10420 : mCallback(&aCallback) {}
10421
10422 MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODvirtual nsresult OnCompleteDispatch() override {
10423 MOZ_ASSERT(mCallback, "How can we have a null mCallback here?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCallback)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mCallback))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mCallback" " (" "How can we have a null mCallback here?"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10423
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCallback" ") (" "How can we have a null mCallback here?"
")"); do { MOZ_CrashSequence(__null, 10423); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10424
10425 ErrorResult rv;
10426 MOZ_KnownLive(mCallback)(mCallback)->Call(rv);
10427 if (MOZ_UNLIKELY(rv.Failed())(__builtin_expect(!!(rv.Failed()), 0))) {
10428 return rv.StealNSResult();
10429 }
10430
10431 return NS_OK;
10432 }
10433
10434 private:
10435 virtual ~SynthesizedEventCallback() = default;
10436
10437 const RefPtr<VoidFunction> mCallback;
10438};
10439
10440NS_IMPL_ISUPPORTS(SynthesizedEventCallback, nsISynthesizedEventCallback)MozExternalRefCountType SynthesizedEventCallback::AddRef(void
) { static_assert(!std::is_destructible_v<SynthesizedEventCallback
>, "Reference-counted class " "SynthesizedEventCallback" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10440); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 10440
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("SynthesizedEventCallback" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("SynthesizedEventCallback" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"SynthesizedEventCallback\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10440); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SynthesizedEventCallback\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 10440); __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("SynthesizedEventCallback" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"SynthesizedEventCallback"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType SynthesizedEventCallback::Release
(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10440); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 10440
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("SynthesizedEventCallback" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("SynthesizedEventCallback" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"SynthesizedEventCallback\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10440); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SynthesizedEventCallback\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 10440); __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("SynthesizedEventCallback" " not thread-safe"
); const char* const nametmp = "SynthesizedEventCallback"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; } nsresult SynthesizedEventCallback::QueryInterface(const
nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10440); MOZ_PretendNoReturn(); } } while (0); nsresult rv =
NS_ERROR_FAILURE; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<SynthesizedEventCallback, nsISynthesizedEventCallback
>, int32_t( reinterpret_cast<char*>(static_cast<nsISynthesizedEventCallback
*>((SynthesizedEventCallback*)0x1000)) - reinterpret_cast<
char*>((SynthesizedEventCallback*)0x1000))}, {&mozilla
::detail::kImplementedIID<SynthesizedEventCallback, nsISupports
>, int32_t(reinterpret_cast<char*>(static_cast<nsISupports
*>( static_cast<nsISynthesizedEventCallback*>((SynthesizedEventCallback
*)0x1000))) - reinterpret_cast<char*>((SynthesizedEventCallback
*)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table
) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
10441
10442} // namespace
10443
10444Result<bool, nsresult> nsContentUtils::SynthesizeMouseEvent(
10445 mozilla::PresShell* aPresShell, nsIWidget* aWidget, const nsAString& aType,
10446 LayoutDeviceIntPoint& aRefPoint,
10447 const SynthesizeMouseEventData& aMouseEventData,
10448 const SynthesizeMouseEventOptions& aOptions,
10449 const Optional<OwningNonNull<VoidFunction>>& aCallback) {
10450 MOZ_ASSERT(aPresShell)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPresShell)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPresShell))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aPresShell", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10450); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresShell"
")"); do { MOZ_CrashSequence(__null, 10450); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10451 MOZ_ASSERT(aWidget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aWidget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aWidget))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aWidget", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10451); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWidget" ")"
); do { MOZ_CrashSequence(__null, 10451); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10452 AUTO_PROFILER_LABEL("nsContentUtils::SynthesizeMouseEvent", OTHER)mozilla::AutoProfilerLabel raiiObject10452( "nsContentUtils::SynthesizeMouseEvent"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
10453
10454 if (aCallback.WasPassed()) {
10455 if (!XRE_IsParentProcess()) {
10456 // TODO(edgar): There is currently no real use case for synthesizing a
10457 // mouse event with a callback from the content process. For now, throw an
10458 // error in this case. We can add support later if a valid use case
10459 // arises.
10460 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeMouseEvent() does not support being "
"called in the content process with a callback", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10462)
10461 "nsContentUtils::SynthesizeMouseEvent() does not support being "NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeMouseEvent() does not support being "
"called in the content process with a callback", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10462)
10462 "called in the content process with a callback")NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeMouseEvent() does not support being "
"called in the content process with a callback", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10462)
;
10463 return Err(NS_ERROR_FAILURE);
10464 }
10465
10466 if (!aOptions.mIsDOMEventSynthesized) {
10467 // TODO(edgar): There is currently no real use case for synthesizing a
10468 // mouse event with a callback that could be coalesced. For now, throw an
10469 // error. We can add support later if a need arises.
10470 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeMouseEvent() does not support being "
"called in the parent process with isDOMEventSynthesized=false, due "
"to the callback doesn't not support on coalesced events", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10473)
10471 "nsContentUtils::SynthesizeMouseEvent() does not support being "NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeMouseEvent() does not support being "
"called in the parent process with isDOMEventSynthesized=false, due "
"to the callback doesn't not support on coalesced events", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10473)
10472 "called in the parent process with isDOMEventSynthesized=false, due "NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeMouseEvent() does not support being "
"called in the parent process with isDOMEventSynthesized=false, due "
"to the callback doesn't not support on coalesced events", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10473)
10473 "to the callback doesn't not support on coalesced events")NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeMouseEvent() does not support being "
"called in the parent process with isDOMEventSynthesized=false, due "
"to the callback doesn't not support on coalesced events", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10473)
;
10474 return Err(NS_ERROR_FAILURE);
10475 }
10476 }
10477
10478 EventMessage msg;
10479 Maybe<WidgetMouseEvent::ExitFrom> exitFrom;
10480 bool contextMenuKey = false;
10481 if (aType.EqualsLiteral("mousedown")) {
10482 msg = eMouseDown;
10483 } else if (aType.EqualsLiteral("mouseup")) {
10484 msg = eMouseUp;
10485 } else if (aType.EqualsLiteral("mousemove")) {
10486 msg = eMouseMove;
10487 } else if (aType.EqualsLiteral("mouseover")) {
10488 msg = eMouseEnterIntoWidget;
10489 } else if (aType.EqualsLiteral("mouseout")) {
10490 msg = eMouseExitFromWidget;
10491 exitFrom = Some(WidgetMouseEvent::ePlatformChild);
10492 } else if (aType.EqualsLiteral("mousecancel")) {
10493 msg = eMouseExitFromWidget;
10494 exitFrom = Some(XRE_IsParentProcess() ? WidgetMouseEvent::ePlatformTopLevel
10495 : WidgetMouseEvent::ePuppet);
10496 } else if (aType.EqualsLiteral("mouselongtap")) {
10497 msg = eMouseLongTap;
10498 } else if (aType.EqualsLiteral("contextmenu")) {
10499 msg = eContextMenu;
10500 contextMenuKey =
10501 !aMouseEventData.mButton &&
10502 aMouseEventData.mInputSource != MouseEvent_Binding::MOZ_SOURCE_TOUCH;
10503 } else if (aType.EqualsLiteral("MozMouseHittest")) {
10504 msg = eMouseHitTest;
10505 } else {
10506 return Err(NS_ERROR_FAILURE);
10507 }
10508
10509 if (aMouseEventData.mMovementX.WasPassed() !=
10510 aMouseEventData.mMovementY.WasPassed()) {
10511 return Err(NS_ERROR_INVALID_ARG);
10512 }
10513
10514 Maybe<WidgetPointerEvent> pointerEvent;
10515 Maybe<WidgetMouseEvent> mouseEvent;
10516 if (IsPointerEventMessage(msg)) {
10517 if (MOZ_UNLIKELY(aOptions.mIsWidgetEventSynthesized)(__builtin_expect(!!(aOptions.mIsWidgetEventSynthesized), 0))) {
10518 MOZ_ASSERT_UNREACHABLE(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: "
"The event shouldn't be dispatched as a synthesized event" ")"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10519); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "The event shouldn't be dispatched as a synthesized event"
")"); do { MOZ_CrashSequence(__null, 10519); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10519 "The event shouldn't be dispatched as a synthesized event")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: "
"The event shouldn't be dispatched as a synthesized event" ")"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10519); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "The event shouldn't be dispatched as a synthesized event"
")"); do { MOZ_CrashSequence(__null, 10519); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10520 // `click`, `auxclick` nor `contextmenu` should not be dispatched as a
10521 // synthesized event.
10522 return Err(NS_ERROR_INVALID_ARG);
10523 }
10524 pointerEvent.emplace(true, msg, aWidget,
10525 contextMenuKey ? WidgetMouseEvent::eContextMenuKey
10526 : WidgetMouseEvent::eNormal);
10527 } else {
10528 mouseEvent.emplace(true, msg, aWidget,
10529 aOptions.mIsWidgetEventSynthesized
10530 ? WidgetMouseEvent::eSynthesized
10531 : WidgetMouseEvent::eReal,
10532 contextMenuKey ? WidgetMouseEvent::eContextMenuKey
10533 : WidgetMouseEvent::eNormal);
10534 }
10535
10536 nsCOMPtr<nsISynthesizedEventCallback> callback;
10537 if (aCallback.WasPassed()) {
10538 callback = MakeAndAddRef<SynthesizedEventCallback>(aCallback.Value());
10539 }
10540
10541 mozilla::widget::AutoSynthesizedEventCallbackNotifier notifier(callback);
10542
10543 WidgetMouseEvent& mouseOrPointerEvent =
10544 pointerEvent.isSome() ? pointerEvent.ref() : mouseEvent.ref();
10545 mouseOrPointerEvent.pointerId = aMouseEventData.mIdentifier;
10546 mouseOrPointerEvent.mModifiers =
10547 GetWidgetModifiers(aMouseEventData.mModifiers);
10548 mouseOrPointerEvent.mButton = aMouseEventData.mButton;
10549 mouseOrPointerEvent.mButtons =
10550 aMouseEventData.mButtons.WasPassed()
10551 ? aMouseEventData.mButtons.Value()
10552 : (msg != eMouseDown
10553 ? 0
10554 : GetButtonsFlagForButton(aMouseEventData.mButton));
10555 // https://w3c.github.io/pointerevents/#dom-pointerevent-pressure.
10556 mouseOrPointerEvent.mPressure =
10557 aMouseEventData.mPressure.WasPassed()
10558 ? aMouseEventData.mPressure.Value()
10559 : ((mouseOrPointerEvent.mButtons == 0) ? 0.0f : 0.5f);
10560 mouseOrPointerEvent.mInputSource = aMouseEventData.mInputSource;
10561 mouseOrPointerEvent.mClickCount =
10562 aMouseEventData.mClickCount.WasPassed()
10563 ? aMouseEventData.mClickCount.Value()
10564 : ((msg == eMouseDown || msg == eMouseUp) ? 1 : 0);
10565 mouseOrPointerEvent.mFlags.mIsSynthesizedForTests =
10566 aOptions.mIsDOMEventSynthesized;
10567 mouseOrPointerEvent.mExitFrom = std::move(exitFrom);
10568 mouseOrPointerEvent.mCallbackId = notifier.SaveCallback();
10569
10570 nsPresContext* presContext = aPresShell->GetPresContext();
10571 if (!presContext) {
10572 return Err(NS_ERROR_FAILURE);
10573 }
10574
10575 mouseOrPointerEvent.mRefPoint = aRefPoint;
10576 mouseOrPointerEvent.mIgnoreRootScrollFrame = aOptions.mIgnoreRootScrollFrame;
10577 if (aMouseEventData.mMovementX.WasPassed()) {
10578 MOZ_ASSERT(aMouseEventData.mMovementY.WasPassed())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aMouseEventData.mMovementY.WasPassed())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aMouseEventData.mMovementY.WasPassed()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aMouseEventData.mMovementY.WasPassed()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10578); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aMouseEventData.mMovementY.WasPassed()" ")"
); do { MOZ_CrashSequence(__null, 10578); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10579 mouseOrPointerEvent.mMovement.emplace(aMouseEventData.mMovementX.Value(),
10580 aMouseEventData.mMovementY.Value());
10581 }
10582
10583 nsEventStatus status = nsEventStatus_eIgnore;
10584 if (aOptions.mToWindow) {
10585 nsresult rv = aPresShell->HandleEvent(aPresShell->GetRootFrame(),
10586 &mouseOrPointerEvent, false, &status);
10587 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10588 return Err(rv);
10589 }
10590 } else if (aOptions.mIsAsyncEnabled ||
10591 StaticPrefs::test_events_async_enabled()) {
10592 // The event is dispatched asynchronously via WebDriver when it is not
10593 // targeted directly at a window and async dispatching is requested.
10594 mouseOrPointerEvent.mFlags.mIsAsyncSynthesizedForTests =
10595 aOptions.mIsDOMEventSynthesized;
10596 status = aWidget->DispatchInputEvent(&mouseOrPointerEvent).mContentStatus;
10597 } else {
10598 status = aWidget->DispatchEvent(&mouseOrPointerEvent);
10599 }
10600
10601 // The callback ID may be cleared when the event also needs to be dispatched
10602 // to a content process. In such cases, the callback will be notified after
10603 // the event has been dispatched in the target content process.
10604 if (mouseOrPointerEvent.mCallbackId.isSome()) {
10605 mozilla::widget::AutoSynthesizedEventCallbackNotifier::NotifySavedCallback(
10606 mouseOrPointerEvent.mCallbackId.ref());
10607 }
10608
10609 return status == nsEventStatus_eConsumeNoDefault;
10610}
10611
10612mozilla::Result<bool, nsresult> nsContentUtils::SynthesizeTouchEvent(
10613 nsPresContext* aPresContext, nsIWidget* aWidget,
10614 const nsPoint& aWidgetOffset, const nsAString& aType,
10615 const nsTArray<SynthesizeTouchEventData>& aTouches,
10616 const int32_t aModifiers, const SynthesizeTouchEventOptions& aOptions,
10617 const Optional<OwningNonNull<VoidFunction>>& aCallback) {
10618 MOZ_ASSERT(aPresContext)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPresContext)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPresContext))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aPresContext", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10618); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresContext"
")"); do { MOZ_CrashSequence(__null, 10618); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10619 MOZ_ASSERT(aWidget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aWidget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aWidget))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aWidget", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10619); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWidget" ")"
); do { MOZ_CrashSequence(__null, 10619); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10620 AUTO_PROFILER_LABEL("nsContentUtils::SynthesizeTouchEvent", OTHER)mozilla::AutoProfilerLabel raiiObject10620( "nsContentUtils::SynthesizeTouchEvent"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
10621
10622 if (aCallback.WasPassed()) {
10623 if (!XRE_IsParentProcess()) {
10624 // TODO(edgar): There is currently no real use case for synthesizing a
10625 // touch event with a callback from the content process. For now, throw an
10626 // error in this case. We can add support later if a valid use case
10627 // arises.
10628 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being "
"called in the content process with a callback", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10630)
10629 "nsContentUtils::SynthesizeTouchEvent() does not support being "NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being "
"called in the content process with a callback", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10630)
10630 "called in the content process with a callback")NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being "
"called in the content process with a callback", nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10630)
;
10631 return Err(NS_ERROR_FAILURE);
10632 }
10633
10634 if (!aOptions.mIsDOMEventSynthesized) {
10635 // TODO(edgar): There is currently no real use case for synthesizing a
10636 // touch event with a callback that could be coalesced. For now, throw an
10637 // error. We can add support later if a need arises.
10638 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being "
"called in the parent process with isDOMEventSynthesized=false, due "
"to the callback doesn't not support on coalesced events", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10641)
10639 "nsContentUtils::SynthesizeTouchEvent() does not support being "NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being "
"called in the parent process with isDOMEventSynthesized=false, due "
"to the callback doesn't not support on coalesced events", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10641)
10640 "called in the parent process with isDOMEventSynthesized=false, due "NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being "
"called in the parent process with isDOMEventSynthesized=false, due "
"to the callback doesn't not support on coalesced events", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10641)
10641 "to the callback doesn't not support on coalesced events")NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being "
"called in the parent process with isDOMEventSynthesized=false, due "
"to the callback doesn't not support on coalesced events", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10641)
;
10642 return Err(NS_ERROR_FAILURE);
10643 }
10644 }
10645
10646 if (XRE_IsParentProcess() && !aOptions.mIsAsyncEnabled &&
10647 !StaticPrefs::test_events_async_enabled()) {
10648 // TODO(edgar): Currently, dispatching touch event from parent process
10649 // without going through APZ would cause content process crash on debug
10650 // build.
10651 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being "
"called in the parent process without going through APZ", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10653)
10652 "nsContentUtils::SynthesizeTouchEvent() does not support being "NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being "
"called in the parent process without going through APZ", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10653)
10653 "called in the parent process without going through APZ")NS_DebugBreak(NS_DEBUG_WARNING, "nsContentUtils::SynthesizeTouchEvent() does not support being "
"called in the parent process without going through APZ", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10653)
;
10654 return Err(NS_ERROR_FAILURE);
10655 }
10656
10657 EventMessage msg;
10658 if (aType.EqualsLiteral("touchstart")) {
10659 msg = eTouchStart;
10660 } else if (aType.EqualsLiteral("touchmove")) {
10661 msg = eTouchMove;
10662 } else if (aType.EqualsLiteral("touchend")) {
10663 msg = eTouchEnd;
10664 } else if (aType.EqualsLiteral("touchcancel")) {
10665 msg = eTouchCancel;
10666 } else {
10667 return Err(NS_ERROR_UNEXPECTED);
10668 }
10669
10670 nsCOMPtr<nsISynthesizedEventCallback> callback;
10671 if (aCallback.WasPassed()) {
10672 callback = MakeAndAddRef<SynthesizedEventCallback>(aCallback.Value());
10673 }
10674
10675 mozilla::widget::AutoSynthesizedEventCallbackNotifier notifier(callback);
10676
10677 WidgetTouchEvent event(true, msg, aWidget);
10678 event.mFlags.mIsSynthesizedForTests = aOptions.mIsDOMEventSynthesized;
10679 event.mModifiers = nsContentUtils::GetWidgetModifiers(aModifiers);
10680 if (aOptions.mIsPen) {
10681 event.mInputSource = MouseEvent_Binding::MOZ_SOURCE_PEN;
10682 }
10683 event.mCallbackId = notifier.SaveCallback();
10684
10685 uint32_t count = aTouches.Length();
10686 event.mTouches.SetCapacity(count);
10687 for (uint32_t i = 0; i < count; ++i) {
10688 if (aTouches[i].mAltitudeAngle.WasPassed() !=
10689 aTouches[i].mAzimuthAngle.WasPassed()) {
10690 return Err(NS_ERROR_INVALID_ARG);
10691 }
10692
10693 LayoutDeviceIntPoint pt = nsContentUtils::ToWidgetPoint(
10694 CSSPoint(aTouches[i].mOffsetX, aTouches[i].mOffsetY), aWidgetOffset,
10695 aPresContext);
10696 LayoutDeviceIntPoint radius = LayoutDeviceIntPoint::FromAppUnitsRounded(
10697 CSSPoint::ToAppUnits(
10698 CSSPoint(aTouches[i].mRadiiX, aTouches[i].mRadiiY)),
10699 aPresContext->AppUnitsPerDevPixel());
10700 // https://w3c.github.io/pointerevents/#dom-pointerevent-pressure.
10701 float pressure = aTouches[i].mPressure.WasPassed()
10702 ? aTouches[i].mPressure.Value()
10703 : (msg == eTouchEnd ? 0.0f : 0.5f);
10704
10705 RefPtr<Touch> t =
10706 new Touch(CheckedInt<int32_t>(aTouches[i].mIdentifier).value(), pt,
10707 radius, aTouches[i].mRotationAngle, pressure);
10708 if (aTouches[i].mAltitudeAngle.WasPassed()) {
10709 MOZ_ASSERT(aTouches[i].mAzimuthAngle.WasPassed())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTouches[i].mAzimuthAngle.WasPassed())>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(aTouches[i].mAzimuthAngle.WasPassed()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aTouches[i].mAzimuthAngle.WasPassed()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10709); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aTouches[i].mAzimuthAngle.WasPassed()" ")"
); do { MOZ_CrashSequence(__null, 10709); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10710 t->mAngle.emplace(aTouches[i].mAltitudeAngle.Value(),
10711 aTouches[i].mAzimuthAngle.Value());
10712 } else {
10713 t->mTilt.emplace(aTouches[i].mTiltX, aTouches[i].mTiltY);
10714 }
10715 t->twist = aTouches[i].mTwist;
10716 event.mTouches.AppendElement(t);
10717 }
10718
10719 nsEventStatus status = nsEventStatus_eIgnore;
10720 if (aOptions.mToWindow) {
10721 RefPtr<PresShell> presShell = aPresContext->PresShell();
10722 MOZ_TRY(presShell->HandleEvent(presShell->GetRootFrame(), &event, false,__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(presShell->HandleEvent(presShell->GetRootFrame(), &
event, false, &status)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
10723 &status))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(presShell->HandleEvent(presShell->GetRootFrame(), &
event, false, &status)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
;
10724 } else if (aOptions.mIsAsyncEnabled ||
10725 StaticPrefs::test_events_async_enabled()) {
10726 status = aWidget->DispatchInputEvent(&event).mContentStatus;
10727 } else {
10728 status = aWidget->DispatchEvent(&event);
10729 }
10730
10731 // The callback ID may be cleared when the event also needs to be dispatched
10732 // to a content process. In such cases, the callback will be notified after
10733 // the event has been dispatched in the target content process.
10734 if (event.mCallbackId.isSome()) {
10735 mozilla::widget::AutoSynthesizedEventCallbackNotifier::NotifySavedCallback(
10736 event.mCallbackId.ref());
10737 }
10738
10739 return status == nsEventStatus_eConsumeNoDefault;
10740}
10741
10742/* static */
10743void nsContentUtils::FirePageHideEventForFrameLoaderSwap(
10744 nsIDocShellTreeItem* aItem, EventTarget* aChromeEventHandler,
10745 bool aOnlySystemGroup) {
10746 MOZ_DIAGNOSTIC_ASSERT(aItem)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aItem)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(aItem))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("aItem", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10746); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aItem"
")"); do { MOZ_CrashSequence(__null, 10746); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10747 MOZ_DIAGNOSTIC_ASSERT(aChromeEventHandler)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChromeEventHandler)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChromeEventHandler))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("aChromeEventHandler"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10747); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "aChromeEventHandler" ")"); do {
MOZ_CrashSequence(__null, 10747); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
10748
10749 if (RefPtr<Document> doc = aItem->GetDocument()) {
10750 doc->OnPageHide(true, aChromeEventHandler, aOnlySystemGroup);
10751 }
10752
10753 int32_t childCount = 0;
10754 aItem->GetInProcessChildCount(&childCount);
10755 AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids;
10756 kids.AppendElements(childCount);
10757 for (int32_t i = 0; i < childCount; ++i) {
10758 aItem->GetInProcessChildAt(i, getter_AddRefs(kids[i]));
10759 }
10760
10761 for (uint32_t i = 0; i < kids.Length(); ++i) {
10762 if (kids[i]) {
10763 FirePageHideEventForFrameLoaderSwap(
10764 MOZ_KnownLive(kids[i])(kids[i]), aChromeEventHandler, aOnlySystemGroup);
10765 }
10766 }
10767}
10768
10769// The pageshow event is fired for a given document only if IsShowing()
10770// returns the same thing as aFireIfShowing. This gives us a way to fire
10771// pageshow only on documents that are still loading or only on documents that
10772// are already loaded.
10773/* static */
10774void nsContentUtils::FirePageShowEventForFrameLoaderSwap(
10775 nsIDocShellTreeItem* aItem, EventTarget* aChromeEventHandler,
10776 bool aFireIfShowing, bool aOnlySystemGroup) {
10777 int32_t childCount = 0;
10778 aItem->GetInProcessChildCount(&childCount);
10779 AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids;
10780 kids.AppendElements(childCount);
10781 for (int32_t i = 0; i < childCount; ++i) {
10782 aItem->GetInProcessChildAt(i, getter_AddRefs(kids[i]));
10783 }
10784
10785 for (uint32_t i = 0; i < kids.Length(); ++i) {
10786 if (kids[i]) {
10787 FirePageShowEventForFrameLoaderSwap(MOZ_KnownLive(kids[i])(kids[i]),
10788 aChromeEventHandler, aFireIfShowing,
10789 aOnlySystemGroup);
10790 }
10791 }
10792
10793 RefPtr<Document> doc = aItem->GetDocument();
10794 if (doc && doc->IsShowing() == aFireIfShowing) {
10795 doc->OnPageShow(true, aChromeEventHandler, aOnlySystemGroup);
10796 }
10797}
10798
10799/* static */
10800already_AddRefed<nsPIWindowRoot> nsContentUtils::GetWindowRoot(Document* aDoc) {
10801 if (aDoc) {
10802 if (nsPIDOMWindowOuter* win = aDoc->GetWindow()) {
10803 return win->GetTopWindowRoot();
10804 }
10805 }
10806 return nullptr;
10807}
10808
10809/* static */
10810bool nsContentUtils::LinkContextIsURI(const nsAString& aAnchor,
10811 nsIURI* aDocURI) {
10812 if (aAnchor.IsEmpty()) {
10813 // anchor parameter not present or empty -> same document reference
10814 return true;
10815 }
10816
10817 // the document URI might contain a fragment identifier ("#...')
10818 // we want to ignore that because it's invisible to the server
10819 // and just affects the local interpretation in the recipient
10820 nsCOMPtr<nsIURI> contextUri;
10821 nsresult rv = NS_GetURIWithoutRef(aDocURI, getter_AddRefs(contextUri));
10822
10823 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10824 // copying failed
10825 return false;
10826 }
10827
10828 // resolve anchor against context
10829 nsCOMPtr<nsIURI> resolvedUri;
10830 rv = NS_NewURI(getter_AddRefs(resolvedUri), aAnchor, nullptr, contextUri);
10831
10832 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10833 // resolving failed
10834 return false;
10835 }
10836
10837 bool same;
10838 rv = contextUri->Equals(resolvedUri, &same);
10839 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10840 // comparison failed
10841 return false;
10842 }
10843
10844 return same;
10845}
10846
10847/* static */
10848bool nsContentUtils::IsPreloadType(nsContentPolicyType aType) {
10849 return (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD ||
10850 aType == nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD ||
10851 aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD ||
10852 aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD ||
10853 aType == nsIContentPolicy::TYPE_INTERNAL_FONT_PRELOAD ||
10854 aType == nsIContentPolicy::TYPE_INTERNAL_JSON_PRELOAD ||
10855 aType == nsIContentPolicy::TYPE_INTERNAL_TEXT_PRELOAD ||
10856 aType == nsIContentPolicy::TYPE_INTERNAL_FETCH_PRELOAD);
10857}
10858
10859// static
10860bool nsContentUtils::IsImageType(ExtContentPolicy aType) {
10861 return aType == ExtContentPolicy::TYPE_IMAGE ||
10862 aType == ExtContentPolicy::TYPE_IMAGESET;
10863}
10864
10865// static
10866ReferrerPolicy nsContentUtils::GetReferrerPolicyFromChannel(
10867 nsIChannel* aChannel) {
10868 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
10869 if (!httpChannel) {
10870 return ReferrerPolicy::_empty;
10871 }
10872
10873 nsresult rv;
10874 nsAutoCString headerValue;
10875 rv = httpChannel->GetResponseHeader("referrer-policy"_ns, headerValue);
10876 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || headerValue.IsEmpty()) {
10877 return ReferrerPolicy::_empty;
10878 }
10879
10880 return ReferrerInfo::ReferrerPolicyFromHeaderString(
10881 NS_ConvertUTF8toUTF16(headerValue));
10882}
10883
10884// static
10885bool nsContentUtils::HasRelNoReferrer(const Element& aElement) {
10886 // rel=noreferrer is only supported in <a>, <area>, and <form>
10887 if (!aElement.IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area,
10888 nsGkAtoms::form) &&
10889 !aElement.IsSVGElement(nsGkAtoms::a) &&
10890 !(aElement.IsMathMLElement(nsGkAtoms::a) &&
10891 StaticPrefs::mathml_a_element_enabled())) {
10892 return false;
10893 }
10894
10895 nsAutoString rel;
10896 aElement.GetAttr(nsGkAtoms::rel, rel);
10897 nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(rel);
10898
10899 while (tok.hasMoreTokens()) {
10900 const nsAString& token = tok.nextToken();
10901 if (token.LowerCaseEqualsLiteral("noreferrer")) {
10902 return true;
10903 }
10904 }
10905
10906 return false;
10907}
10908
10909// static
10910bool nsContentUtils::IsNonSubresourceRequest(nsIChannel* aChannel) {
10911 nsLoadFlags loadFlags = 0;
10912 aChannel->GetLoadFlags(&loadFlags);
10913 if (loadFlags & nsIChannel::LOAD_DOCUMENT_URI) {
10914 return true;
10915 }
10916
10917 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
10918 nsContentPolicyType type = loadInfo->InternalContentPolicyType();
10919 return IsNonSubresourceInternalPolicyType(type);
10920}
10921
10922// static
10923bool nsContentUtils::IsNonSubresourceInternalPolicyType(
10924 nsContentPolicyType aType) {
10925 return aType == nsIContentPolicy::TYPE_DOCUMENT ||
10926 aType == nsIContentPolicy::TYPE_INTERNAL_IFRAME ||
10927 aType == nsIContentPolicy::TYPE_INTERNAL_FRAME ||
10928 aType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
10929 aType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
10930}
10931
10932// static public
10933bool nsContentUtils::IsThirdPartyTrackingResourceWindow(
10934 nsPIDOMWindowInner* aWindow) {
10935 MOZ_ASSERT(aWindow)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aWindow)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aWindow))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aWindow", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10935); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")"
); do { MOZ_CrashSequence(__null, 10935); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10936
10937 Document* document = aWindow->GetExtantDoc();
10938 if (!document) {
10939 return false;
10940 }
10941
10942 return AntiTrackingUtils::IsThirdPartyTrackingChannel(document->GetChannel());
10943}
10944
10945// static public
10946bool nsContentUtils::IsFirstPartyTrackingResourceWindow(
10947 nsPIDOMWindowInner* aWindow) {
10948 MOZ_ASSERT(aWindow)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aWindow)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aWindow))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aWindow", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10948); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")"
); do { MOZ_CrashSequence(__null, 10948); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10949
10950 Document* document = aWindow->GetExtantDoc();
10951 if (!document) {
10952 return false;
10953 }
10954
10955 return AntiTrackingUtils::IsFirstPartyTrackingChannel(document->GetChannel());
10956}
10957
10958namespace {
10959
10960// We put StringBuilder in the anonymous namespace to prevent anything outside
10961// this file from accidentally being linked against it.
10962class BulkAppender {
10963 using size_type = typename nsAString::size_type;
10964
10965 public:
10966 explicit BulkAppender(BulkWriteHandle<char16_t>&& aHandle)
10967 : mHandle(std::move(aHandle)), mPosition(0) {}
10968 ~BulkAppender() = default;
10969
10970 template <int N>
10971 void AppendLiteral(const char16_t (&aStr)[N]) {
10972 size_t len = N - 1;
10973 MOZ_ASSERT(mPosition + len <= mHandle.Length())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mPosition + len <= mHandle.Length())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mPosition + len <= mHandle.Length()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mPosition + len <= mHandle.Length()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10973); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()" ")"
); do { MOZ_CrashSequence(__null, 10973); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10974 memcpy(mHandle.Elements() + mPosition, aStr, len * sizeof(char16_t));
10975 mPosition += len;
10976 }
10977
10978 void Append(Span<const char16_t> aStr) {
10979 size_t len = aStr.Length();
10980 MOZ_ASSERT(mPosition + len <= mHandle.Length())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mPosition + len <= mHandle.Length())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mPosition + len <= mHandle.Length()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mPosition + len <= mHandle.Length()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10980); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()" ")"
); do { MOZ_CrashSequence(__null, 10980); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10981 // Both mHandle.Elements() and aStr.Elements() are guaranteed
10982 // to be non-null (by the string implementation and by Span,
10983 // respectively), so not checking the pointers for null before
10984 // memcpy does not lead to UB even if len was zero.
10985 memcpy(mHandle.Elements() + mPosition, aStr.Elements(),
10986 len * sizeof(char16_t));
10987 mPosition += len;
10988 }
10989
10990 void Append(Span<const char> aStr) {
10991 size_t len = aStr.Length();
10992 MOZ_ASSERT(mPosition + len <= mHandle.Length())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mPosition + len <= mHandle.Length())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mPosition + len <= mHandle.Length()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mPosition + len <= mHandle.Length()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10992); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()" ")"
); do { MOZ_CrashSequence(__null, 10992); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10993 ConvertLatin1toUtf16(aStr, mHandle.AsSpan().From(mPosition));
10994 mPosition += len;
10995 }
10996
10997 void Finish() { mHandle.Finish(mPosition, false); }
10998
10999 private:
11000 BulkWriteHandle<char16_t> mHandle;
11001 size_type mPosition;
11002};
11003
11004class StringBuilderSIMD {
11005 public:
11006 static const bool SIMD = true;
11007};
11008
11009class StringBuilderALU {
11010 public:
11011 static const bool SIMD = false;
11012};
11013
11014class StringBuilder {
11015 private:
11016 class Unit {
11017 public:
11018 Unit() : mAtom(nullptr) { MOZ_COUNT_CTOR(StringBuilder::Unit)do { static_assert(std::is_class_v<StringBuilder::Unit>
, "Token '" "StringBuilder::Unit" "' is not a class type."); static_assert
(!std::is_base_of_v<nsISupports, StringBuilder::Unit>, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "StringBuilder::Unit"
, sizeof(*this)); } while (0)
; }
11019 ~Unit() {
11020 if (mType == Type::String || mType == Type::StringWithEncode) {
11021 mString.~nsString();
11022 }
11023 MOZ_COUNT_DTOR(StringBuilder::Unit)do { static_assert(std::is_class_v<StringBuilder::Unit>
, "Token '" "StringBuilder::Unit" "' is not a class type."); static_assert
(!std::is_base_of_v<nsISupports, StringBuilder::Unit>, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "StringBuilder::Unit"
, sizeof(*this)); } while (0)
;
11024 }
11025
11026 enum class Type : uint8_t {
11027 Unknown,
11028 Atom,
11029 String,
11030 StringWithEncode,
11031 Literal,
11032 TextFragment,
11033 TextFragmentWithEncode,
11034 };
11035
11036 struct LiteralSpan {
11037 const char16_t* mData;
11038 uint32_t mLength;
11039
11040 Span<const char16_t> AsSpan() { return Span(mData, mLength); }
11041 };
11042
11043 union {
11044 nsAtom* mAtom;
11045 LiteralSpan mLiteral;
11046 nsString mString;
11047 const CharacterDataBuffer* mCharacterDataBuffer;
11048 };
11049 Type mType = Type::Unknown;
11050 };
11051
11052 static_assert(sizeof(void*) != 8 || sizeof(Unit) <= 3 * sizeof(void*),
11053 "Unit should remain small");
11054
11055 public:
11056 // Try to keep the size of StringBuilder close to a jemalloc bucket size
11057 // (the 16kb one in this case).
11058 static constexpr uint32_t TARGET_SIZE = 16 * 1024;
11059
11060 // The number of units we need to remove from the inline buffer so that the
11061 // rest of the builder members fit. A more precise approach would be to
11062 // calculate that extra size and use (TARGET_SIZE - OTHER_SIZE) /
11063 // sizeof(Unit) or so, but this is simpler.
11064 static constexpr uint32_t PADDING_UNITS = sizeof(void*) == 8 ? 1 : 2;
11065
11066 static constexpr uint32_t STRING_BUFFER_UNITS =
11067 TARGET_SIZE / sizeof(Unit) - PADDING_UNITS;
11068
11069 StringBuilder() : mLast(this), mLength(0) { MOZ_COUNT_CTOR(StringBuilder)do { static_assert(std::is_class_v<StringBuilder>, "Token '"
"StringBuilder" "' is not a class type."); static_assert(!std
::is_base_of_v<nsISupports, StringBuilder>, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "StringBuilder",
sizeof(*this)); } while (0)
; }
11070
11071 MOZ_COUNTED_DTOR(StringBuilder)~StringBuilder() { do { static_assert(std::is_class_v<StringBuilder
>, "Token '" "StringBuilder" "' is not a class type."); static_assert
(!std::is_base_of_v<nsISupports, StringBuilder>, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "StringBuilder",
sizeof(*this)); } while (0); }
11072
11073 void Append(nsAtom* aAtom) {
11074 Unit* u = AddUnit();
11075 u->mAtom = aAtom;
11076 u->mType = Unit::Type::Atom;
11077 uint32_t len = aAtom->GetLength();
11078 mLength += len;
11079 }
11080
11081 template <int N>
11082 void Append(const char16_t (&aLiteral)[N]) {
11083 constexpr uint32_t len = N - 1;
11084 Unit* u = AddUnit();
11085 u->mLiteral = {aLiteral, len};
11086 u->mType = Unit::Type::Literal;
11087 mLength += len;
11088 }
11089
11090 void Append(nsString&& aString) {
11091 Unit* u = AddUnit();
11092 uint32_t len = aString.Length();
11093 new (&u->mString) nsString(std::move(aString));
11094 u->mType = Unit::Type::String;
11095 mLength += len;
11096 }
11097
11098 // aLen can be !isValid(), which will get propagated into mLength.
11099 void AppendWithAttrEncode(nsString&& aString, CheckedInt<uint32_t> aLen) {
11100 Unit* u = AddUnit();
11101 new (&u->mString) nsString(std::move(aString));
11102 u->mType = Unit::Type::StringWithEncode;
11103 mLength += aLen;
11104 }
11105
11106 void Append(const CharacterDataBuffer* aCharacterDataBuffer) {
11107 Unit* u = AddUnit();
11108 u->mCharacterDataBuffer = aCharacterDataBuffer;
11109 u->mType = Unit::Type::TextFragment;
11110 uint32_t len = aCharacterDataBuffer->GetLength();
11111 mLength += len;
11112 }
11113
11114 // aLen can be !isValid(), which will get propagated into mLength.
11115 void AppendWithEncode(const CharacterDataBuffer* aCharacterDataBuffer,
11116 CheckedInt<uint32_t> aLen) {
11117 Unit* u = AddUnit();
11118 u->mCharacterDataBuffer = aCharacterDataBuffer;
11119 u->mType = Unit::Type::TextFragmentWithEncode;
11120 mLength += aLen;
11121 }
11122
11123 bool ToString(nsAString& aOut) {
11124 if (!mLength.isValid()) {
11125 return false;
11126 }
11127 auto appenderOrErr = aOut.BulkWrite(mLength.value(), 0, true);
11128 if (appenderOrErr.isErr()) {
11129 return false;
11130 }
11131
11132 BulkAppender appender{appenderOrErr.unwrap()};
11133
11134 // Experiment with moving this higher up the call stack
11135 // after we have experience from
11136 // https://bugzilla.mozilla.org/show_bug.cgi?id=1997255
11137 // on the parser side.
11138 bool simd = mozilla::htmlaccel::htmlaccelEnabled();
11139
11140 for (StringBuilder* current = this; current;
11141 current = current->mNext.get()) {
11142 uint32_t len = current->mUnits.Length();
11143 for (uint32_t i = 0; i < len; ++i) {
11144 Unit& u = current->mUnits[i];
11145 switch (u.mType) {
11146 case Unit::Type::Atom:
11147 appender.Append(*(u.mAtom));
11148 break;
11149 case Unit::Type::String:
11150 appender.Append(u.mString);
11151 break;
11152 case Unit::Type::StringWithEncode:
11153 if (simd) {
11154 EncodeAttrString<StringBuilderSIMD>(u.mString, appender);
11155 } else {
11156 EncodeAttrString<StringBuilderALU>(u.mString, appender);
11157 }
11158 break;
11159 case Unit::Type::Literal:
11160 appender.Append(u.mLiteral.AsSpan());
11161 break;
11162 case Unit::Type::TextFragment:
11163 if (u.mCharacterDataBuffer->Is2b()) {
11164 appender.Append(Span(u.mCharacterDataBuffer->Get2b(),
11165 u.mCharacterDataBuffer->GetLength()));
11166 } else {
11167 appender.Append(Span(u.mCharacterDataBuffer->Get1b(),
11168 u.mCharacterDataBuffer->GetLength()));
11169 }
11170 break;
11171 case Unit::Type::TextFragmentWithEncode:
11172 if (u.mCharacterDataBuffer->Is2b()) {
11173 if (simd) {
11174 EncodeTextFragment<StringBuilderSIMD>(
11175 Span(u.mCharacterDataBuffer->Get2b(),
11176 u.mCharacterDataBuffer->GetLength()),
11177 appender);
11178
11179 } else {
11180 EncodeTextFragment<StringBuilderALU>(
11181 Span(u.mCharacterDataBuffer->Get2b(),
11182 u.mCharacterDataBuffer->GetLength()),
11183 appender);
11184 }
11185 } else {
11186 if (simd) {
11187 EncodeTextFragment<StringBuilderSIMD>(
11188 Span(u.mCharacterDataBuffer->Get1b(),
11189 u.mCharacterDataBuffer->GetLength()),
11190 appender);
11191
11192 } else {
11193 EncodeTextFragment<StringBuilderALU>(
11194 Span(u.mCharacterDataBuffer->Get1b(),
11195 u.mCharacterDataBuffer->GetLength()),
11196 appender);
11197 }
11198 }
11199 break;
11200 default:
11201 MOZ_CRASH("Unknown unit type?")do { do { } while (false); MOZ_ReportCrash("" "Unknown unit type?"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 11201); AnnotateMozCrashReason
("MOZ_CRASH(" "Unknown unit type?" ")"); do { MOZ_CrashSequence
(__null, 11201); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
11202 }
11203 }
11204 }
11205 appender.Finish();
11206 return true;
11207 }
11208
11209 private:
11210 Unit* AddUnit() {
11211 if (mLast->mUnits.Length() == STRING_BUFFER_UNITS) {
11212 new StringBuilder(this);
11213 }
11214 return mLast->mUnits.AppendElement();
11215 }
11216
11217 explicit StringBuilder(StringBuilder* aFirst) : mLast(nullptr), mLength(0) {
11218 MOZ_COUNT_CTOR(StringBuilder)do { static_assert(std::is_class_v<StringBuilder>, "Token '"
"StringBuilder" "' is not a class type."); static_assert(!std
::is_base_of_v<nsISupports, StringBuilder>, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "StringBuilder",
sizeof(*this)); } while (0)
;
11219 aFirst->mLast->mNext = WrapUnique(this);
11220 aFirst->mLast = this;
11221 }
11222
11223 template <class S>
11224 void EncodeAttrString(Span<const char16_t> aStr, BulkAppender& aAppender) {
11225 size_t flushedUntil = 0;
11226 size_t currentPosition = 0;
11227 const char16_t* ptr = aStr.Elements();
11228 const char16_t* end = ptr + aStr.Length();
11229
11230 // continue by label (committee proposal P3568) isn't in C++, yet, so
11231 // goto is used for what's logically continuing an outer loop.
11232 //
11233 // The purpose of two loop levels is to efficiently stay in the inner
11234 // loop when there isn't a full SIMD stride left.
11235 //
11236 // Strange indent thanks to clang-format.
11237 outer:
11238 // Check for having at least a SIMD stride of data to avoid useless
11239 // non-inline function calls when there isn't a full stride left.
11240 // This should become unnecessary if it turns out to be feasible
11241 // to inline the call without triggering
11242 // https://github.com/llvm/llvm-project/issues/160886 .
11243 if (S::SIMD && (end - ptr >= 16)) {
11244 // Need to check ifdef inside here in order to make even non-opt
11245 // build consider `S::SIMD` used.
11246#ifdef MOZ_MAY_HAVE_HTMLACCEL1
11247 size_t skipped =
11248 mozilla::htmlaccel::SkipNonEscapedInAttributeValue(ptr, end);
11249 ptr += skipped;
11250 currentPosition += skipped;
11251#endif
11252 }
11253 while (ptr != end) {
11254 char16_t c = *ptr;
11255 ptr++;
11256 switch (c) {
11257 case '"':
11258 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11259 aAppender.AppendLiteral(u"&quot;");
11260 currentPosition++;
11261 flushedUntil = currentPosition;
11262 goto outer;
11263 case '&':
11264 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11265 aAppender.AppendLiteral(u"&amp;");
11266 currentPosition++;
11267 flushedUntil = currentPosition;
11268 goto outer;
11269 case 0x00A0:
11270 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11271 aAppender.AppendLiteral(u"&nbsp;");
11272 currentPosition++;
11273 flushedUntil = currentPosition;
11274 goto outer;
11275 case '<':
11276 if (StaticPrefs::dom_security_html_serialization_escape_lt_gt()) {
11277 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11278 aAppender.AppendLiteral(u"&lt;");
11279 currentPosition++;
11280 flushedUntil = currentPosition;
11281 } else {
11282 currentPosition++;
11283 }
11284 goto outer;
11285 case '>':
11286 if (StaticPrefs::dom_security_html_serialization_escape_lt_gt()) {
11287 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11288 aAppender.AppendLiteral(u"&gt;");
11289 currentPosition++;
11290 flushedUntil = currentPosition;
11291 } else {
11292 currentPosition++;
11293 }
11294 goto outer;
11295 default:
11296 currentPosition++;
11297 continue;
11298 }
11299 }
11300 // Logically the outer loop ends here.
11301 if (currentPosition > flushedUntil) {
11302 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11303 }
11304 }
11305
11306 template <class S, class T>
11307 void EncodeTextFragment(Span<const T> aStr, BulkAppender& aAppender) {
11308 size_t flushedUntil = 0;
11309 size_t currentPosition = 0;
11310 const T* ptr = aStr.Elements();
11311 const T* end = ptr + aStr.Length();
11312
11313 // continue by label (committee proposal P3568) isn't in C++, yet, so
11314 // goto is used for what's logically continuing an outer loop.
11315 //
11316 // The purpose of two loop levels is to efficiently stay in the inner
11317 // loop when there isn't a full SIMD stride left.
11318 //
11319 // Strange indent thanks to clang-format.
11320 outer:
11321 // Check for having at least a SIMD stride of data to avoid useless
11322 // non-inline function calls when there isn't a full stride left.
11323 // This should become unnecessary if it turns out to be feasible
11324 // to inline the call without triggering
11325 // https://github.com/llvm/llvm-project/issues/160886 .
11326 if (S::SIMD && (end - ptr >= 16)) {
11327 // Need to check ifdef inside here in order to make even non-opt
11328 // build consider `S::SIMD` used.
11329#ifdef MOZ_MAY_HAVE_HTMLACCEL1
11330 size_t skipped = mozilla::htmlaccel::SkipNonEscapedInTextNode(ptr, end);
11331 ptr += skipped;
11332 currentPosition += skipped;
11333#endif
11334 }
11335 while (ptr != end) {
11336 T c = *ptr;
11337 ++ptr;
11338 switch (c) {
11339 case '<':
11340 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11341 aAppender.AppendLiteral(u"&lt;");
11342 currentPosition++;
11343 flushedUntil = currentPosition;
11344 goto outer;
11345 case '>':
11346 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11347 aAppender.AppendLiteral(u"&gt;");
11348 currentPosition++;
11349 flushedUntil = currentPosition;
11350 goto outer;
11351 case '&':
11352 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11353 aAppender.AppendLiteral(u"&amp;");
11354 currentPosition++;
11355 flushedUntil = currentPosition;
11356 goto outer;
11357 case T(0xA0):
11358 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11359 aAppender.AppendLiteral(u"&nbsp;");
11360 currentPosition++;
11361 flushedUntil = currentPosition;
11362 goto outer;
11363 default:
11364 currentPosition++;
11365 continue;
11366 }
11367 }
11368 // Logically the outer loop ends here.
11369 if (currentPosition > flushedUntil) {
11370 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11371 }
11372 }
11373
11374 AutoTArray<Unit, STRING_BUFFER_UNITS> mUnits;
11375 UniquePtr<StringBuilder> mNext;
11376 StringBuilder* mLast;
11377 // mLength is used only in the first StringBuilder object in the linked
11378 // list.
11379 CheckedInt<uint32_t> mLength;
11380};
11381
11382static_assert(sizeof(StringBuilder) <= StringBuilder::TARGET_SIZE,
11383 "StringBuilder should fit in the target bucket");
11384
11385} // namespace
11386
11387static void AppendEncodedCharacters(const CharacterDataBuffer* aText,
11388 StringBuilder& aBuilder) {
11389 uint32_t numEncodedChars = 0;
11390 uint32_t len = aText->GetLength();
11391 if (aText->Is2b()) {
11392 const char16_t* data = aText->Get2b();
11393#ifdef MOZ_MAY_HAVE_HTMLACCEL1
11394 if (mozilla::htmlaccel::htmlaccelEnabled()) {
11395 numEncodedChars =
11396 mozilla::htmlaccel::CountEscapedInTextNode(data, data + len);
11397 } else
11398#endif
11399 {
11400 for (uint32_t i = 0; i < len; ++i) {
11401 const char16_t c = data[i];
11402 switch (c) {
11403 case '<':
11404 case '>':
11405 case '&':
11406 case 0x00A0:
11407 ++numEncodedChars;
11408 break;
11409 default:
11410 break;
11411 }
11412 }
11413 }
11414 } else {
11415 const char* data = aText->Get1b();
11416#ifdef MOZ_MAY_HAVE_HTMLACCEL1
11417 if (mozilla::htmlaccel::htmlaccelEnabled()) {
11418 numEncodedChars =
11419 mozilla::htmlaccel::CountEscapedInTextNode(data, data + len);
11420 } else
11421#endif
11422 {
11423 for (uint32_t i = 0; i < len; ++i) {
11424 const unsigned char c = data[i];
11425 switch (c) {
11426 case '<':
11427 case '>':
11428 case '&':
11429 case 0x00A0:
11430 ++numEncodedChars;
11431 break;
11432 default:
11433 break;
11434 }
11435 }
11436 }
11437 }
11438
11439 if (numEncodedChars) {
11440 // For simplicity, conservatively estimate the size of the string after
11441 // encoding. This will result in reserving more memory than we actually
11442 // need, but that should be fine unless the string has an enormous number
11443 // of eg < in it. We subtract 1 for the null terminator, then 1 more for
11444 // the existing character that will be replaced.
11445 constexpr uint32_t maxCharExtraSpace =
11446 std::max({std::size("&lt;"), std::size("&gt;"), std::size("&amp;"),
11447 std::size("&nbsp;")}) -
11448 2;
11449 static_assert(maxCharExtraSpace < 100, "Possible underflow");
11450 CheckedInt<uint32_t> maxExtraSpace =
11451 CheckedInt<uint32_t>(numEncodedChars) * maxCharExtraSpace;
11452 aBuilder.AppendWithEncode(aText, maxExtraSpace + len);
11453 } else {
11454 aBuilder.Append(aText);
11455 }
11456}
11457
11458static CheckedInt<uint32_t> ExtraSpaceNeededForAttrEncoding(
11459 const nsAString& aValue) {
11460 const char16_t* c = aValue.BeginReading();
11461 const char16_t* end = aValue.EndReading();
11462
11463 uint32_t numEncodedChars = 0;
11464#ifdef MOZ_MAY_HAVE_HTMLACCEL1
11465 if (mozilla::htmlaccel::htmlaccelEnabled()) {
11466 numEncodedChars = mozilla::htmlaccel::CountEscapedInAttributeValue(c, end);
11467 } else
11468#endif
11469 {
11470 while (c < end) {
11471 switch (*c) {
11472 case '"':
11473 case '&':
11474 case 0x00A0: // NO-BREAK SPACE
11475 case '<':
11476 case '>':
11477 ++numEncodedChars;
11478 break;
11479 default:
11480 break;
11481 }
11482 ++c;
11483 }
11484 }
11485
11486 if (!numEncodedChars) {
11487 return 0;
11488 }
11489
11490 // For simplicity, conservatively estimate the size of the string after
11491 // encoding. This will result in reserving more memory than we actually
11492 // need, but that should be fine unless the string has an enormous number of
11493 // & in it. We subtract 1 for the null terminator, then 1 more for the
11494 // existing character that will be replaced.
11495 constexpr uint32_t maxCharExtraSpace =
11496 std::max({std::size("&quot;"), std::size("&amp;"), std::size("&nbsp;"),
11497 std::size("&lt;"), std::size("&gt;")}) -
11498 2;
11499 static_assert(maxCharExtraSpace < 100, "Possible underflow");
11500 return CheckedInt<uint32_t>(numEncodedChars) * maxCharExtraSpace;
11501}
11502
11503static void AppendEncodedAtomAttributeValue(nsAtom* aAtom,
11504 StringBuilder& aBuilder) {
11505 nsDependentAtomString atomStr(aAtom);
11506 auto space = ExtraSpaceNeededForAttrEncoding(atomStr);
11507 if (space.isValid() && !space.value()) {
11508 aBuilder.Append(aAtom);
11509 } else {
11510 aBuilder.AppendWithAttrEncode(nsString(atomStr), space + atomStr.Length());
11511 }
11512}
11513
11514static void AppendEncodedAttributeValue(const nsAttrValue& aValue,
11515 StringBuilder& aBuilder) {
11516 if (nsAtom* atom = aValue.GetStoredAtom()) {
11517 AppendEncodedAtomAttributeValue(atom, aBuilder);
11518 return;
11519 }
11520
11521 // NOTE(emilio): In most cases this will just be a reference to the stored
11522 // nsStringBuffer.
11523 nsString str;
11524 aValue.ToString(str);
11525 auto space = ExtraSpaceNeededForAttrEncoding(str);
11526 if (!space.isValid() || space.value()) {
11527 aBuilder.AppendWithAttrEncode(std::move(str), space + str.Length());
11528 } else {
11529 aBuilder.Append(std::move(str));
11530 }
11531}
11532
11533static void StartElement(Element* aElement, StringBuilder& aBuilder) {
11534 nsAtom* localName = aElement->NodeInfo()->NameAtom();
11535 const int32_t tagNS = aElement->GetNameSpaceID();
11536
11537 aBuilder.Append(u"<");
11538 if (tagNS == kNameSpaceID_XHTML3 || tagNS == kNameSpaceID_SVG9 ||
11539 tagNS == kNameSpaceID_MathML6) {
11540 aBuilder.Append(localName);
11541 } else {
11542 aBuilder.Append(nsString(aElement->NodeName()));
11543 }
11544
11545 if (CustomElementData* ceData = aElement->GetCustomElementData()) {
11546 nsAtom* isAttr = ceData->GetIs(aElement);
11547 if (isAttr && !aElement->HasAttr(nsGkAtoms::is)) {
11548 aBuilder.Append(uR"( is=")");
11549 AppendEncodedAtomAttributeValue(isAttr, aBuilder);
11550 aBuilder.Append(uR"(")");
11551 }
11552 }
11553
11554 uint32_t i = 0;
11555 while (BorrowedAttrInfo info = aElement->GetAttrInfoAt(i++)) {
11556 const nsAttrName* name = info.mName;
11557
11558 int32_t attNs = name->NamespaceID();
11559 nsAtom* attName = name->LocalName();
11560
11561 // Filter out any attribute starting with [-|_]moz
11562 // FIXME(emilio): Do we still need this?
11563 nsDependentAtomString attrNameStr(attName);
11564 if (StringBeginsWith(attrNameStr, u"_moz"_ns) ||
11565 StringBeginsWith(attrNameStr, u"-moz"_ns)) {
11566 continue;
11567 }
11568
11569 aBuilder.Append(u" ");
11570
11571 if (MOZ_LIKELY(attNs == kNameSpaceID_None)(__builtin_expect(!!(attNs == kNameSpaceID_None), 1)) ||
11572 (attNs == kNameSpaceID_XMLNS1 && attName == nsGkAtoms::xmlns)) {
11573 // Nothing else required
11574 } else if (attNs == kNameSpaceID_XML2) {
11575 aBuilder.Append(u"xml:");
11576 } else if (attNs == kNameSpaceID_XMLNS1) {
11577 aBuilder.Append(u"xmlns:");
11578 } else if (attNs == kNameSpaceID_XLink4) {
11579 aBuilder.Append(u"xlink:");
11580 } else if (nsAtom* prefix = name->GetPrefix()) {
11581 aBuilder.Append(prefix);
11582 aBuilder.Append(u":");
11583 }
11584
11585 aBuilder.Append(attName);
11586 aBuilder.Append(uR"(=")");
11587 AppendEncodedAttributeValue(*info.mValue, aBuilder);
11588 aBuilder.Append(uR"(")");
11589 }
11590
11591 aBuilder.Append(u">");
11592
11593 /*
11594 // Per HTML spec we should append one \n if the first child of
11595 // pre/textarea/listing is a textnode and starts with a \n.
11596 // But because browsers haven't traditionally had that behavior,
11597 // we're not changing our behavior either - yet.
11598 if (aContent->IsHTMLElement()) {
11599 if (localName == nsGkAtoms::pre || localName == nsGkAtoms::textarea ||
11600 localName == nsGkAtoms::listing) {
11601 nsIContent* fc = aContent->GetFirstChild();
11602 if (fc &&
11603 (fc->NodeType() == nsINode::TEXT_NODE ||
11604 fc->NodeType() == nsINode::CDATA_SECTION_NODE)) {
11605 const CharacterDataBuffer* text = fc->GetText();
11606 if (text && text->GetLength() && text->CharAt(0) == char16_t('\n')) {
11607 aBuilder.Append("\n");
11608 }
11609 }
11610 }
11611 }*/
11612}
11613
11614static inline bool ShouldEscape(nsIContent* aParent) {
11615 if (!aParent || !aParent->IsHTMLElement()) {
11616 return true;
11617 }
11618
11619 static const nsAtom* nonEscapingElements[] = {
11620 nsGkAtoms::style, nsGkAtoms::script, nsGkAtoms::xmp,
11621 nsGkAtoms::iframe, nsGkAtoms::noembed, nsGkAtoms::noframes,
11622 nsGkAtoms::plaintext, nsGkAtoms::noscript};
11623 static mozilla::BitBloomFilter<12, nsAtom> sFilter;
11624 static bool sInitialized = false;
11625 if (!sInitialized) {
11626 sInitialized = true;
11627 for (auto& nonEscapingElement : nonEscapingElements) {
11628 sFilter.add(nonEscapingElement);
11629 }
11630 }
11631
11632 nsAtom* tag = aParent->NodeInfo()->NameAtom();
11633 if (sFilter.mightContain(tag)) {
11634 for (auto& nonEscapingElement : nonEscapingElements) {
11635 if (tag == nonEscapingElement) {
11636 if (MOZ_UNLIKELY(tag == nsGkAtoms::noscript)(__builtin_expect(!!(tag == nsGkAtoms::noscript), 0)) &&
11637 MOZ_UNLIKELY(!aParent->OwnerDoc()->IsScriptEnabled())(__builtin_expect(!!(!aParent->OwnerDoc()->IsScriptEnabled
()), 0))
) {
11638 return true;
11639 }
11640 return false;
11641 }
11642 }
11643 }
11644 return true;
11645}
11646
11647static inline bool IsVoidTag(Element* aElement) {
11648 if (!aElement->IsHTMLElement()) {
11649 return false;
11650 }
11651 return FragmentOrElement::IsHTMLVoid(aElement->NodeInfo()->NameAtom());
11652}
11653
11654static bool StartSerializingShadowDOM(
11655 nsINode* aNode, StringBuilder& aBuilder, bool aSerializableShadowRoots,
11656 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
11657 ShadowRoot* shadow = aNode->GetShadowRoot();
11658 if (!shadow || ((!aSerializableShadowRoots || !shadow->Serializable()) &&
11659 !aShadowRoots.Contains(shadow))) {
11660 return false;
11661 }
11662
11663 // https://html.spec.whatwg.org/#html-fragment-serialisation-algorithm
11664 // steps 4-12
11665
11666 // 4.2.1. Append "<template shadowrootmode="".
11667 aBuilder.Append(u"<template shadowrootmode=\"");
11668
11669 // 4.2.2. If shadow's mode is "open", then append "open". Otherwise, append
11670 // "closed".
11671 // 3. Append U+0022 (").
11672 if (shadow->IsClosed()) {
11673 aBuilder.Append(u"closed\"");
11674 } else {
11675 aBuilder.Append(u"open\"");
11676 }
11677
11678 // 4. If shadow's delegates focus is set, then append "
11679 // shadowrootdelegatesfocus=""".
11680 if (shadow->DelegatesFocus()) {
11681 aBuilder.Append(u" shadowrootdelegatesfocus=\"\"");
11682 }
11683
11684 // 5. If shadow's serializable is set, then append "
11685 // shadowrootserializable=""".
11686 if (shadow->Serializable()) {
11687 aBuilder.Append(u" shadowrootserializable=\"\"");
11688 }
11689
11690 // 6. If shadow's slot assignment is "manual", then append "
11691 // shadowrootslotassignment="manual"".
11692 if (StaticPrefs::dom_shadowdom_shadowRootSlotAssignment_enabled() &&
11693 shadow->SlotAssignment() == SlotAssignmentMode::Manual) {
11694 aBuilder.Append(u" shadowrootslotassignment=\"manual\"");
11695 }
11696
11697 // 7. If shadow's clonable is set, then append " shadowrootclonable=""".
11698 if (shadow->Clonable()) {
11699 aBuilder.Append(u" shadowrootclonable=\"\"");
11700 }
11701
11702 // 8. If shadow's reference target is non-null:
11703 // 8.1. Append " shadowrootreferencetarget="".
11704 // 8.2. Append shadow's reference target.
11705 // 8.3. Append """.
11706 if (StaticPrefs::dom_shadowdom_referenceTarget_enabled() &&
11707 shadow->HasReferenceTarget()) {
11708 aBuilder.Append(u" shadowrootreferencetarget=\"");
11709 aBuilder.Append(shadow->ReferenceTarget());
11710 aBuilder.Append(u"\"");
11711 }
11712
11713 auto isGlobalCustomElementRegistry = [](CustomElementRegistry* registry) {
11714 return registry && !registry->IsScoped();
11715 };
11716
11717 // 9. Let shouldAppendRegistryAttribute be the result of running these steps:
11718 const bool shouldAppendRegistryAttribute = [&]() {
11719 if (!StaticPrefs::dom_scoped_custom_element_registries_enabled()) {
11720 return false;
11721 }
11722
11723 // 9.1. Let documentRegistry be shadow's node document's custom element
11724 // registry.
11725 CustomElementRegistry* documentRegistry =
11726 shadow->OwnerDoc()->GetCustomElementRegistry();
11727 // 9.2. Let shadowRegistry be shadow's custom element registry.
11728 CustomElementRegistry* shadowRegistry = shadow->GetCustomElementRegistry();
11729
11730 // 9.3. If documentRegistry is null and shadowRegistry is null, then return
11731 // false.
11732 if (!documentRegistry && !shadowRegistry) {
11733 return false;
11734 }
11735 // 9.4. If documentRegistry is a global custom element registry and
11736 // shadowRegistry is a global custom element registry, then return
11737 // false.
11738 else if (isGlobalCustomElementRegistry(documentRegistry) &&
11739 isGlobalCustomElementRegistry(shadowRegistry)) {
11740 return false;
11741 }
11742
11743 // 9.5. Return true.
11744 return true;
11745 }();
11746
11747 // 10. If shouldAppendRegistryAttribute is true, then append "
11748 // shadowrootcustomelementregistry=""".
11749 if (shouldAppendRegistryAttribute) {
11750 aBuilder.Append(u" shadowrootcustomelementregistry=\"\"");
11751 }
11752
11753 // 11. Append U+003E (>).
11754 aBuilder.Append(u">");
11755
11756 // 12. Append the value of running the HTML fragment serialization algorithm
11757 // with shadow, serializableShadowRoots, and shadowRoots (thus recursing
11758 // into this algorithm for that element).
11759 // (Returning `true` tells the caller to continue).
11760 if (!shadow->HasChildren()) {
11761 // 13. Append "</template>".
11762 aBuilder.Append(u"</template>");
11763 return false;
11764 }
11765 return true;
11766}
11767
11768template <SerializeShadowRoots ShouldSerializeShadowRoots>
11769static void SerializeNodeToMarkupInternal(
11770 nsINode* aRoot, bool aDescendantsOnly, StringBuilder& aBuilder,
11771 bool aSerializableShadowRoots,
11772 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
11773 nsINode* current =
11774 aDescendantsOnly ? aRoot->GetFirstChildOfTemplateOrNode() : aRoot;
11775 if (!current) {
11776 return;
11777 }
11778
11779 nsIContent* next;
11780 while (true) {
11781 bool isVoid = false;
11782 switch (current->NodeType()) {
11783 case nsINode::ELEMENT_NODE: {
11784 Element* elem = current->AsElement();
11785 StartElement(elem, aBuilder);
11786
11787 if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
11788 if (StartSerializingShadowDOM(
11789 current, aBuilder, aSerializableShadowRoots, aShadowRoots)) {
11790 current = current->GetShadowRoot()->GetFirstChild();
11791 continue;
11792 }
11793 }
11794
11795 isVoid = IsVoidTag(elem);
11796 if (!isVoid && (next = current->GetFirstChildOfTemplateOrNode())) {
11797 current = next;
11798 continue;
11799 }
11800 break;
11801 }
11802
11803 case nsINode::TEXT_NODE:
11804 case nsINode::CDATA_SECTION_NODE: {
11805 const CharacterDataBuffer* characterDataBuffer =
11806 &current->AsText()->DataBuffer();
11807 nsIContent* parent = current->GetParent();
11808 if (ShouldEscape(parent)) {
11809 AppendEncodedCharacters(characterDataBuffer, aBuilder);
11810 } else {
11811 aBuilder.Append(characterDataBuffer);
11812 }
11813 break;
11814 }
11815
11816 case nsINode::COMMENT_NODE: {
11817 aBuilder.Append(u"<!--");
11818 aBuilder.Append(
11819 static_cast<nsIContent*>(current)->GetCharacterDataBuffer());
11820 aBuilder.Append(u"-->");
11821 break;
11822 }
11823
11824 case nsINode::DOCUMENT_TYPE_NODE: {
11825 aBuilder.Append(u"<!DOCTYPE ");
11826 aBuilder.Append(nsString(current->NodeName()));
11827 aBuilder.Append(u">");
11828 break;
11829 }
11830
11831 case nsINode::PROCESSING_INSTRUCTION_NODE: {
11832 aBuilder.Append(u"<?");
11833 aBuilder.Append(nsString(current->NodeName()));
11834 aBuilder.Append(u" ");
11835 aBuilder.Append(
11836 static_cast<nsIContent*>(current)->GetCharacterDataBuffer());
11837 aBuilder.Append(u"?>");
11838 break;
11839 }
11840 }
11841
11842 while (true) {
11843 if (!isVoid && current->NodeType() == nsINode::ELEMENT_NODE) {
11844 aBuilder.Append(u"</");
11845 nsIContent* elem = static_cast<nsIContent*>(current);
11846 if (elem->IsHTMLElement() || elem->IsSVGElement() ||
11847 elem->IsMathMLElement()) {
11848 aBuilder.Append(elem->NodeInfo()->NameAtom());
11849 } else {
11850 aBuilder.Append(nsString(current->NodeName()));
11851 }
11852 aBuilder.Append(u">");
11853 }
11854 isVoid = false;
11855
11856 if (current == aRoot) {
11857 return;
11858 }
11859
11860 if ((next = current->GetNextSibling())) {
11861 current = next;
11862 break;
11863 }
11864
11865 if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
11866 // If the current node is a shadow root, then we must go to its host.
11867 // Since shadow DOMs are serialized declaratively as template
11868 // elements, we serialize the end tag of the template before going
11869 // back to serializing the shadow host.
11870 if (current->IsShadowRoot()) {
11871 current = current->GetContainingShadowHost();
11872 aBuilder.Append(u"</template>");
11873
11874 if (current->HasChildren()) {
11875 current = current->GetFirstChildOfTemplateOrNode();
11876 break;
11877 }
11878 continue;
11879 }
11880 }
11881
11882 current = current->GetParentNode();
11883
11884 // Handle template element. If the parent is a template's content,
11885 // then adjust the parent to be the template element.
11886 if (current != aRoot &&
11887 current->NodeType() == nsINode::DOCUMENT_FRAGMENT_NODE) {
11888 DocumentFragment* frag = static_cast<DocumentFragment*>(current);
11889 nsIContent* fragHost = frag->GetHost();
11890 if (fragHost && fragHost->IsTemplateElement()) {
11891 current = fragHost;
11892 }
11893 }
11894
11895 if (aDescendantsOnly && current == aRoot) {
11896 return;
11897 }
11898 }
11899 }
11900}
11901
11902template <SerializeShadowRoots ShouldSerializeShadowRoots>
11903bool nsContentUtils::SerializeNodeToMarkup(
11904 nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
11905 bool aSerializableShadowRoots,
11906 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
11907 // If you pass in a DOCUMENT_NODE, you must pass aDescendentsOnly as true
11908 MOZ_ASSERT(aDescendantsOnly || aRoot->NodeType() != nsINode::DOCUMENT_NODE)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDescendantsOnly || aRoot->NodeType() != nsINode::
DOCUMENT_NODE)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aDescendantsOnly || aRoot->NodeType
() != nsINode::DOCUMENT_NODE))), 0))) { do { } while (false);
MOZ_ReportAssertionFailure("aDescendantsOnly || aRoot->NodeType() != nsINode::DOCUMENT_NODE"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 11908); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aDescendantsOnly || aRoot->NodeType() != nsINode::DOCUMENT_NODE"
")"); do { MOZ_CrashSequence(__null, 11908); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11909
11910 StringBuilder builder;
11911 if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
11912 if (aDescendantsOnly &&
11913 StartSerializingShadowDOM(aRoot, builder, aSerializableShadowRoots,
11914 aShadowRoots)) {
11915 SerializeNodeToMarkupInternal<SerializeShadowRoots::Yes>(
11916 aRoot->GetShadowRoot(), true, builder, aSerializableShadowRoots,
11917 aShadowRoots);
11918 // The template tag is opened in StartSerializingShadowDOM, so we need
11919 // to close it here before serializing any children of aRoot.
11920 builder.Append(u"</template>");
11921 }
11922 }
11923
11924 SerializeNodeToMarkupInternal<ShouldSerializeShadowRoots>(
11925 aRoot, aDescendantsOnly, builder, aSerializableShadowRoots, aShadowRoots);
11926 return builder.ToString(aOut);
11927}
11928
11929template bool nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::No>(
11930 nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
11931 bool aSerializableShadowRoots,
11932 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots);
11933template bool nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::Yes>(
11934 nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
11935 bool aSerializableShadowRoots,
11936 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots);
11937
11938bool nsContentUtils::IsSpecificAboutPage(JSObject* aGlobal, const char* aUri) {
11939 // aUri must start with about: or this isn't the right function to be using.
11940 MOZ_ASSERT(strncmp(aUri, "about:", 6) == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(strncmp(aUri, "about:", 6) == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(strncmp(aUri, "about:", 6) ==
0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("strncmp(aUri, \"about:\", 6) == 0", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 11940); AnnotateMozCrashReason("MOZ_ASSERT" "(" "strncmp(aUri, \"about:\", 6) == 0"
")"); do { MOZ_CrashSequence(__null, 11940); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11941
11942 // Make sure the global is a window
11943 MOZ_DIAGNOSTIC_ASSERT(JS_IsGlobalObject(aGlobal))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(JS_IsGlobalObject(aGlobal))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(JS_IsGlobalObject(aGlobal)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("JS_IsGlobalObject(aGlobal)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 11943); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "JS_IsGlobalObject(aGlobal)" ")"
); do { MOZ_CrashSequence(__null, 11943); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11944 nsGlobalWindowInner* win = xpc::WindowOrNull(aGlobal);
11945 if (!win) {
11946 return false;
11947 }
11948
11949 nsCOMPtr<nsIPrincipal> principal = win->GetPrincipal();
11950 NS_ENSURE_TRUE(principal, false)do { if ((__builtin_expect(!!(!(principal)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "principal" ") failed", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 11950); return
false; } } while (false)
;
11951
11952 // First check the scheme to avoid getting long specs in the common case.
11953 if (!principal->SchemeIs("about")) {
11954 return false;
11955 }
11956
11957 nsAutoCString spec;
11958 principal->GetAsciiSpec(spec);
11959
11960 return spec.EqualsASCII(aUri);
11961}
11962
11963/* static */
11964nsIDocShell* nsContentUtils::GetDocShellForEventTarget(EventTarget* aTarget) {
11965 if (!aTarget) {
11966 return nullptr;
11967 }
11968
11969 nsCOMPtr<nsPIDOMWindowInner> innerWindow;
11970 if (nsCOMPtr<nsINode> node = nsINode::FromEventTarget(aTarget)) {
11971 bool ignore;
11972 innerWindow =
11973 do_QueryInterface(node->OwnerDoc()->GetScriptHandlingObject(ignore));
11974 } else if ((innerWindow = nsPIDOMWindowInner::FromEventTarget(aTarget))) {
11975 // Nothing else to do
11976 } else if (nsCOMPtr<DOMEventTargetHelper> helper =
11977 do_QueryInterface(aTarget)) {
11978 innerWindow = helper->GetOwnerWindow();
11979 }
11980
11981 if (innerWindow) {
11982 return innerWindow->GetDocShell();
11983 }
11984
11985 return nullptr;
11986}
11987
11988/*
11989 * Note: this function only relates to figuring out HTTPS state, which is an
11990 * input to the Secure Context algorithm. We are not actually implementing
11991 * any part of the Secure Context algorithm itself here.
11992 *
11993 * This is a bit of a hack. Ideally we'd propagate HTTPS state through
11994 * nsIChannel as described in the Fetch and HTML specs, but making channels
11995 * know about whether they should inherit HTTPS state, propagating information
11996 * about who the channel's "client" is, exposing GetHttpsState API on channels
11997 * and modifying the various cache implementations to store and retrieve HTTPS
11998 * state involves a huge amount of code (see bug 1220687). We avoid that for
11999 * now using this function.
12000 *
12001 * This function takes advantage of the observation that we can return true if
12002 * nsIContentSecurityManager::IsOriginPotentiallyTrustworthy returns true for
12003 * the document's origin (e.g. the origin has a scheme of 'https' or host
12004 * 'localhost' etc.). Since we generally propagate a creator document's
12005 * origin onto data:, blob:, etc. documents, this works for them too.
12006 *
12007 * The scenario where this observation breaks down is sandboxing without the
12008 * 'allow-same-origin' flag, since in this case a document is given a unique
12009 * origin (IsOriginPotentiallyTrustworthy would return false). We handle that
12010 * by using the origin that the document would have had had it not been
12011 * sandboxed.
12012 *
12013 * DEFICIENCIES: Note that this function uses nsIScriptSecurityManager's
12014 * getChannelResultPrincipalIfNotSandboxed, and that method's ignoring of
12015 * sandboxing is limited to the immediate sandbox. In the case that aDocument
12016 * should inherit its origin (e.g. data: URI) but its parent has ended up
12017 * with a unique origin due to sandboxing further up the parent chain we may
12018 * end up returning false when we would ideally return true (since we will
12019 * examine the parent's origin for 'https' and not finding it.) This means
12020 * that we may restrict the privileges of some pages unnecessarily in this
12021 * edge case.
12022 */
12023/* static */
12024bool nsContentUtils::HttpsStateIsModern(Document* aDocument) {
12025 if (!aDocument) {
12026 return false;
12027 }
12028
12029 nsCOMPtr<nsIPrincipal> principal = aDocument->NodePrincipal();
12030
12031 if (principal->IsSystemPrincipal()) {
12032 return true;
12033 }
12034
12035 // If aDocument is sandboxed, try and get the principal that it would have
12036 // been given had it not been sandboxed:
12037 if (principal->GetIsNullPrincipal() &&
12038 (aDocument->GetSandboxFlags() & SANDBOXED_ORIGIN)) {
12039 nsIChannel* channel = aDocument->GetChannel();
12040 if (channel) {
12041 nsCOMPtr<nsIScriptSecurityManager> ssm =
12042 nsContentUtils::GetSecurityManager();
12043 nsresult rv = ssm->GetChannelResultPrincipalIfNotSandboxed(
12044 channel, getter_AddRefs(principal));
12045 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12046 return false;
12047 }
12048 if (principal->IsSystemPrincipal()) {
12049 // If a document with the system principal is sandboxing a subdocument
12050 // that would normally inherit the embedding element's principal (e.g.
12051 // a srcdoc document) then the embedding document does not trust the
12052 // content that is written to the embedded document. Unlike when the
12053 // embedding document is https, in this case we have no indication as
12054 // to whether the embedded document's contents are delivered securely
12055 // or not, and the sandboxing would possibly indicate that they were
12056 // not. To play it safe we return false here. (See bug 1162772
12057 // comment 73-80.)
12058 return false;
12059 }
12060 }
12061 }
12062
12063 if (principal->GetIsNullPrincipal()) {
12064 return false;
12065 }
12066
12067 MOZ_ASSERT(principal->GetIsContentPrincipal())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(principal->GetIsContentPrincipal())>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(principal->GetIsContentPrincipal()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("principal->GetIsContentPrincipal()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12067); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "principal->GetIsContentPrincipal()" ")"
); do { MOZ_CrashSequence(__null, 12067); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12068
12069 return principal->GetIsOriginPotentiallyTrustworthy();
12070}
12071
12072/* static */
12073bool nsContentUtils::ComputeIsSecureContext(nsIChannel* aChannel) {
12074 MOZ_ASSERT(aChannel)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aChannel)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aChannel))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aChannel", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12074); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChannel" ")"
); do { MOZ_CrashSequence(__null, 12074); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12075
12076 nsCOMPtr<nsIScriptSecurityManager> ssm = nsContentUtils::GetSecurityManager();
12077 nsCOMPtr<nsIPrincipal> principal;
12078 nsresult rv = ssm->GetChannelResultPrincipalIfNotSandboxed(
12079 aChannel, getter_AddRefs(principal));
12080 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12081 return false;
12082 }
12083
12084 const RefPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
12085
12086 if (principal->IsSystemPrincipal()) {
12087 // If the load would've been sandboxed, treat this load as an untrusted
12088 // load, as system code considers sandboxed resources insecure.
12089 return !loadInfo->GetLoadingSandboxed();
12090 }
12091
12092 if (principal->GetIsNullPrincipal()) {
12093 return false;
12094 }
12095
12096 if (const RefPtr<WindowContext> windowContext =
12097 WindowContext::GetById(loadInfo->GetInnerWindowID())) {
12098 if (!windowContext->GetIsSecureContext()) {
12099 return false;
12100 }
12101 }
12102
12103 return principal->GetIsOriginPotentiallyTrustworthy();
12104}
12105
12106/* https://html.spec.whatwg.org/#concept-try-upgrade */
12107void nsContentUtils::TryToUpgradeElement(Element* aElement) {
12108 // 1. "Let definition be the result of looking up a custom element definition
12109 // given element's custom element registry, element's namespace, element's
12110 // local name, and element's is value."
12111 NodeInfo* nodeInfo = aElement->NodeInfo();
12112 RefPtr<nsAtom> typeAtom =
12113 aElement->GetCustomElementData()->GetCustomElementType();
12114
12115 MOZ_ASSERT(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12115); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())"
")"); do { MOZ_CrashSequence(__null, 12115); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12116
12117 // When scoped custom element registries are enabled, look up the element's
12118 // own custom element registry (which may be a scoped registry, null, or the
12119 // document's global registry as fallback).
12120 CustomElementRegistry* registry = nullptr;
12121 if (StaticPrefs::dom_scoped_custom_element_registries_enabled()) {
12122 registry = aElement->GetCustomElementRegistry();
12123 if (!registry) {
12124 return;
12125 }
12126 }
12127
12128 CustomElementDefinition* definition = nullptr;
12129 if (registry) {
12130 definition = registry->LookupCustomElementDefinition(
12131 nodeInfo->NameAtom(), nodeInfo->NamespaceID(), typeAtom);
12132 } else {
12133 MOZ_ASSERT(!StaticPrefs::dom_scoped_custom_element_registries_enabled())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!StaticPrefs::dom_scoped_custom_element_registries_enabled
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!StaticPrefs::dom_scoped_custom_element_registries_enabled
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!StaticPrefs::dom_scoped_custom_element_registries_enabled()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12133); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!StaticPrefs::dom_scoped_custom_element_registries_enabled()"
")"); do { MOZ_CrashSequence(__null, 12133); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12134 definition = nsContentUtils::LookupCustomElementDefinition(
12135 nodeInfo->GetDocument(), nodeInfo->NameAtom(), nodeInfo->NamespaceID(),
12136 typeAtom);
12137 }
12138
12139 // 2. "If definition is not null, then enqueue a custom element upgrade
12140 // reaction given element and definition."
12141 if (definition) {
12142 nsContentUtils::EnqueueUpgradeReaction(aElement, definition);
12143 } else if (registry) {
12144 registry->RegisterUnresolvedElement(aElement, typeAtom);
12145 } else {
12146 MOZ_ASSERT(!StaticPrefs::dom_scoped_custom_element_registries_enabled())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!StaticPrefs::dom_scoped_custom_element_registries_enabled
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!StaticPrefs::dom_scoped_custom_element_registries_enabled
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!StaticPrefs::dom_scoped_custom_element_registries_enabled()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12146); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!StaticPrefs::dom_scoped_custom_element_registries_enabled()"
")"); do { MOZ_CrashSequence(__null, 12146); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12147 // XXX: Not in spec. Add an unresolved custom element that is a candidate
12148 // for upgrade when a custom element is connected to the document.
12149 nsContentUtils::RegisterUnresolvedElement(aElement, typeAtom);
12150 }
12151}
12152
12153MOZ_CAN_RUN_SCRIPT
12154static void DoCustomElementCreate(Element** aElement, JSContext* aCx,
12155 Document* aDoc, NodeInfo* aNodeInfo,
12156 CustomElementConstructor* aConstructor,
12157 ErrorResult& aRv, FromParser aFromParser) {
12158 JS::Rooted<JS::Value> constructResult(aCx);
12159 aConstructor->Construct(&constructResult, aRv, "Custom Element Create",
12160 CallbackFunction::eRethrowExceptions);
12161 if (aRv.Failed()) {
12162 return;
12163 }
12164
12165 RefPtr<Element> element;
12166 // constructResult is an ObjectValue because construction with a callback
12167 // always forms the return value from a JSObject.
12168 UNWRAP_OBJECT(Element, &constructResult, element)mozilla::dom::binding_detail::UnwrapObjectWithCrossOriginAsserts
< mozilla::dom::prototypes::id::Element, mozilla::dom::Element_Binding
::NativeType>(&constructResult, element)
;
12169 if (aNodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
12170 if (!element || !element->IsHTMLElement()) {
12171 aRv.ThrowTypeError<MSG_DOES_NOT_IMPLEMENT_INTERFACE>("\"this\"",
12172 "HTMLElement");
12173 return;
12174 }
12175 } else {
12176 if (!element || !element->IsXULElement()) {
12177 aRv.ThrowTypeError<MSG_DOES_NOT_IMPLEMENT_INTERFACE>("\"this\"",
12178 "XULElement");
12179 return;
12180 }
12181 }
12182
12183 nsAtom* localName = aNodeInfo->NameAtom();
12184
12185 if (aDoc != element->OwnerDoc() || element->GetParentNode() ||
12186 element->HasChildren() || element->GetAttrCount() ||
12187 element->NodeInfo()->NameAtom() != localName) {
12188 aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
12189 return;
12190 }
12191
12192 if (element->IsHTMLElement()) {
12193 static_cast<HTMLElement*>(&*element)->InhibitRestoration(
12194 !(aFromParser & FROM_PARSER_NETWORK));
12195 }
12196
12197 element.forget(aElement);
12198}
12199
12200/* https://dom.spec.whatwg.org/#concept-create-element */
12201nsresult nsContentUtils::NewXULOrHTMLElement(
12202 Element** aResult, mozilla::dom::NodeInfo* aNodeInfo,
12203 FromParser aFromParser, nsAtom* aIsAtom,
12204 mozilla::dom::CustomElementDefinition* aDefinition,
12205 Maybe<RefPtr<CustomElementRegistry>> aCustomElementRegistry) {
12206 RefPtr<mozilla::dom::NodeInfo> nodeInfo = aNodeInfo;
12207 MOZ_ASSERT(nodeInfo->NamespaceEquals(kNameSpaceID_XHTML) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals
(8))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals
(8)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
" (" "Can only create XUL or XHTML elements." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12209); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
") (" "Can only create XUL or XHTML elements." ")"); do { MOZ_CrashSequence
(__null, 12209); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1
Taking false branch
2
Loop condition is false. Exiting loop
12208 nodeInfo->NamespaceEquals(kNameSpaceID_XUL),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals
(8))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals
(8)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
" (" "Can only create XUL or XHTML elements." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12209); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
") (" "Can only create XUL or XHTML elements." ")"); do { MOZ_CrashSequence
(__null, 12209); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
12209 "Can only create XUL or XHTML elements.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals
(8))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals
(8)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
" (" "Can only create XUL or XHTML elements." ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12209); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
") (" "Can only create XUL or XHTML elements." ")"); do { MOZ_CrashSequence
(__null, 12209); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12210
12211 nsAtom* name = nodeInfo->NameAtom();
12212 bool isCustomElementName = false;
12213 const Maybe<const nsHTMLTag>& tag = nodeInfo->HTMLTag();
12214 if (tag.isSome()) {
3
Assuming the condition is false
4
Taking false branch
12215 MOZ_ASSERT(nodeInfo->NamespaceEquals(kNameSpaceID_XHTML))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nodeInfo->NamespaceEquals(3))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nodeInfo->NamespaceEquals
(3)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("nodeInfo->NamespaceEquals(3)", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12215); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3)"
")"); do { MOZ_CrashSequence(__null, 12215); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12216 isCustomElementName =
12217 (*tag == eHTMLTag_userdefined &&
12218 nsContentUtils::IsCustomElementName(name, kNameSpaceID_XHTML3));
12219 } else {
12220 MOZ_ASSERT(nodeInfo->NamespaceEquals(kNameSpaceID_XUL))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nodeInfo->NamespaceEquals(8))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nodeInfo->NamespaceEquals
(8)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("nodeInfo->NamespaceEquals(8)", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12220); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(8)"
")"); do { MOZ_CrashSequence(__null, 12220); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
5
Taking false branch
6
Loop condition is false. Exiting loop
12221 if (aIsAtom) {
7
Assuming 'aIsAtom' is null
8
Taking false branch
12222 // Make sure the customized built-in element to be constructed confirms
12223 // to our naming requirement, i.e. [is] must be a dashed name and
12224 // the tag name must not.
12225 // if so, set isCustomElementName to false to kick off all the logics
12226 // that pick up aIsAtom.
12227 if (nsContentUtils::IsNameWithDash(aIsAtom) &&
12228 !nsContentUtils::IsNameWithDash(name)) {
12229 isCustomElementName = false;
12230 } else {
12231 isCustomElementName =
12232 nsContentUtils::IsCustomElementName(name, kNameSpaceID_XUL8);
12233 }
12234 } else {
12235 isCustomElementName =
12236 nsContentUtils::IsCustomElementName(name, kNameSpaceID_XUL8);
12237 }
12238 }
12239
12240 nsAtom* tagAtom = nodeInfo->NameAtom();
12241 nsAtom* typeAtom = nullptr;
12242 bool isCustomElement = isCustomElementName
8.1
'isCustomElementName' is true
8.1
'isCustomElementName' is true
|| aIsAtom;
12243 if (isCustomElement
8.2
'isCustomElement' is true
8.2
'isCustomElement' is true
) {
12244 typeAtom = isCustomElementName
9.1
'isCustomElementName' is true
9.1
'isCustomElementName' is true
? tagAtom : aIsAtom;
9
Taking true branch
10
'?' condition is true
12245 }
12246
12247 MOZ_ASSERT_IF(aDefinition, isCustomElement)do { if (aDefinition) { do { static_assert( mozilla::detail::
AssertionConditionType<decltype(isCustomElement)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(isCustomElement))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("isCustomElement", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12247); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isCustomElement"
")"); do { MOZ_CrashSequence(__null, 12247); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
11
Assuming 'aDefinition' is non-null
12
Taking true branch
13
Taking false branch
14
Loop condition is false. Exiting loop
15
Loop condition is false. Exiting loop
12248
12249 // 3. "Let definition be the result of looking up a custom element definition
12250 // given registry, namespace, localName, and is."
12251 RefPtr<CustomElementDefinition> definition = aDefinition;
12252 if (isCustomElement
15.1
'isCustomElement' is true
15.1
'isCustomElement' is true
&& !definition) {
12253 MOZ_ASSERT(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12253); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())"
")"); do { MOZ_CrashSequence(__null, 12253); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12254 // When a custom element registry is provided (e.g. from fragment parsing
12255 // with a scoped registry), use it for definition lookup.
12256 if (aCustomElementRegistry.isSome()) {
12257 if (RefPtr<CustomElementRegistry> registry =
12258 aCustomElementRegistry.value()) {
12259 definition = registry->LookupCustomElementDefinition(
12260 nodeInfo->NameAtom(), nodeInfo->NamespaceID(), typeAtom);
12261 }
12262 // If registry is explicitly null, definition stays null (no upgrade).
12263 } else {
12264 definition = nsContentUtils::LookupCustomElementDefinition(
12265 nodeInfo->GetDocument(), nodeInfo->NameAtom(),
12266 nodeInfo->NamespaceID(), typeAtom);
12267 }
12268 }
12269
12270 /*
12271 * Synchronous custom elements flag is determined by 3 places in spec,
12272 * 1) create an element for a token, the flag is determined by
12273 * "will execute script" which is not originally created
12274 * for the HTML fragment parsing algorithm.
12275 * 2) createElement and createElementNS, the flag is the same as
12276 * NOT_FROM_PARSER.
12277 * 3) clone a node, our implementation will not go into this function.
12278 * For the unset case which is non-synchronous only applied for
12279 * inner/outerHTML.
12280 */
12281 bool synchronousCustomElements =
12282 definition && aFromParser != dom::FROM_PARSER_FRAGMENT;
16
Assuming 'aFromParser' is not equal to FROM_PARSER_FRAGMENT
12283 auto setRegistryOnExit = MakeScopeExit([&]() {
17
Calling 'MakeScopeExit<(lambda at /root/firefox-clang/dom/base/nsContentUtils.cpp:12283:42)>'
19
Returning from 'MakeScopeExit<(lambda at /root/firefox-clang/dom/base/nsContentUtils.cpp:12283:42)>'
12284 if (!*aResult ||
12285 !StaticPrefs::dom_scoped_custom_element_registries_enabled() ||
12286 synchronousCustomElements) {
12287 return;
12288 }
12289 if (aCustomElementRegistry.isSome()) {
12290 RefPtr<CustomElementRegistry> registry = aCustomElementRegistry.value();
12291 if (registry) {
12292 (*aResult)->SetCustomElementRegistry(registry);
12293 } else {
12294 (*aResult)->SetNullCustomElementRegistry();
12295 }
12296 } else {
12297 Document* doc = (*aResult)->OwnerDoc();
12298 if (CustomElementRegistry* globalRegistry =
12299 doc->GetEffectiveGlobalCustomElementRegistry()) {
12300 (*aResult)->SetCustomElementRegistry(globalRegistry);
12301 }
12302 }
12303 });
12304
12305 // It might be a problem that parser synchronously calls constructor, so
12306 // filed bug 1378079 to figure out what we should do for parser case.
12307 if (definition) {
20
Taking true branch
12308 // Per discussion in https://github.com/w3c/webcomponents/issues/635,
12309 // use entry global in those places that are called from JS APIs and use
12310 // the node document's global object if it is called from parser.
12311 nsIGlobalObject* global;
12312 if (aFromParser == dom::NOT_FROM_PARSER) {
21
Assuming 'aFromParser' is equal to NOT_FROM_PARSER
22
Taking true branch
12313 global = GetEntryGlobal();
12314
12315 // Documents created from the PrototypeDocumentSink always use
12316 // NOT_FROM_PARSER for non-XUL elements. We can get the global from the
12317 // document in that case.
12318 if (!global) {
23
Assuming 'global' is non-null
24
Taking false branch
12319 Document* doc = nodeInfo->GetDocument();
12320 if (doc && doc->LoadedFromPrototype()) {
12321 global = doc->GetScopeObject();
12322 }
12323 }
12324 } else {
12325 global = nodeInfo->GetDocument()->GetScopeObject();
12326 }
12327 if (!global
24.1
'global' is non-null
24.1
'global' is non-null
) {
25
Taking false branch
12328 // In browser chrome code, one may have access to a document which
12329 // doesn't have scope object anymore.
12330 return NS_ERROR_FAILURE;
12331 }
12332
12333 AutoAllowLegacyScriptExecution exemption;
12334 AutoEntryScript aes(global, "create custom elements");
12335 JSContext* cx = aes.cx();
12336 ErrorResult rv;
12337
12338 // 4. "If definition is non-null, and definition's name is not equal to its
12339 // local name (i.e., definition represents a customized built-in
12340 // element):"
12341 if (definition->IsCustomBuiltIn()) {
26
Taking false branch
12342 // 4.2. "Set result to the result of creating an element internal..."
12343 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
12344 *aResult =
12345 CreateHTMLElement(*tag, nodeInfo.forget(), aFromParser).take();
12346 } else {
12347 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
12348 }
12349 (*aResult)->SetCustomElementData(
12350 std::make_unique<CustomElementData>(typeAtom));
12351 if (synchronousCustomElements) {
12352 // 4.3. "If synchronousCustomElements is true, then run this step while
12353 // catching any exceptions: Upgrade result using definition."
12354 CustomElementRegistry::Upgrade(*aResult, definition, rv);
12355 if (rv.MaybeSetPendingException(cx)) {
12356 aes.ReportException();
12357 }
12358 } else {
12359 // 4.4. "Otherwise, enqueue a custom element upgrade reaction given
12360 // result and definition."
12361 nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
12362 }
12363
12364 return NS_OK;
12365 }
12366
12367 // 5. "Otherwise, if definition is non-null:"
12368 // 5.1. "If synchronousCustomElements is true:"
12369 if (synchronousCustomElements
26.1
'synchronousCustomElements' is true
26.1
'synchronousCustomElements' is true
) {
27
Taking true branch
12370 {
12371 // 5.1.1. "Let C be definition's constructor."
12372 CustomElementConstructor* constructor = definition->mConstructor;
12373
12374 RefPtr<Document> doc = nodeInfo->GetDocument();
12375 DocGroup* docGroup = doc->GetDocGroup();
12376
12377 // XXX: https://github.com/whatwg/dom/pull/1494
12378 // 5.1.2. Let previousRegistry be the surrounding agent's active
12379 // custom element constructor map[C] with default null.
12380 // 5.1.3. Set the surrounding agent's active custom element constructor
12381 // map[C] to registry.
12382 Maybe<DocGroup::AutoActiveConstructorRegistry>
12383 activeConstructorRegistry;
12384 if (StaticPrefs::dom_scoped_custom_element_registries_enabled() &&
28
Assuming the condition is false
12385 constructor->CallableOrNull() && docGroup) {
12386 if (aCustomElementRegistry.isSome()) {
12387 activeConstructorRegistry.emplace(docGroup, constructor,
12388 aCustomElementRegistry.ref());
12389 } else {
12390 activeConstructorRegistry.emplace(
12391 docGroup, constructor,
12392 doc->GetEffectiveGlobalCustomElementRegistry());
12393 }
12394 }
12395
12396 // 5.1.4. "Run these steps while catching any exceptions:
12397 DoCustomElementCreate(aResult, cx, doc, nodeInfo,
12398 MOZ_KnownLive(definition->mConstructor)(definition->mConstructor), rv,
12399 aFromParser);
12400
12401 // 5.1.5. If previousRegistry is null, then remove the surrounding
12402 // agent's active custom element constructor map[C]. Otherwise,
12403 // set it back to previousRegistry.
12404 // 5.1.6. Otherwise, set the surrounding agent ’s active custom element
12405 // constructor map[C] to previousRegistry.
12406 // (Handled by `activeRegistry`'s destructor during scope exit).
12407 }
12408
12409 if (rv.MaybeSetPendingException(cx)) {
29
Taking true branch
12410 // "If any of these steps threw an exception: ... Set result to the
12411 // result of creating an element internal given document,
12412 // HTMLUnknownElement..."
12413 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
30
Taking false branch
12414 NS_IF_ADDREF(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget(),ns_if_addref(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget
(), aFromParser))
12415 aFromParser))ns_if_addref(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget
(), aFromParser))
;
12416 } else {
12417 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
31
Assigning value
12418 }
12419 (*aResult)->SetDefined(false);
32
Called C++ object pointer is null
12420 // Set the fallback element's registry even on failure.
12421 if (StaticPrefs::dom_scoped_custom_element_registries_enabled()) {
12422 if (aCustomElementRegistry.isSome()) {
12423 if (CustomElementRegistry* registry =
12424 aCustomElementRegistry.ref()) {
12425 (*aResult)->SetCustomElementRegistry(registry);
12426 } else {
12427 (*aResult)->SetNullCustomElementRegistry();
12428 }
12429 }
12430 }
12431 } else if (*aResult && nodeInfo->GetPrefixAtom()) {
12432 // 5.1.3.9. Set result's namespace prefix to prefix.
12433 (*aResult)->SetNamespacePrefix(nodeInfo->GetPrefixAtom());
12434 }
12435 return NS_OK;
12436 }
12437
12438 // 5.2. "Otherwise:"
12439 // 5.2.1. "Set result to the result of creating an element internal given
12440 // document, HTMLElement, localName..."
12441 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
12442 NS_IF_ADDREF(*aResult =ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
12443 NS_NewHTMLElement(nodeInfo.forget(), aFromParser))ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
;
12444 } else {
12445 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
12446 }
12447 (*aResult)->SetCustomElementData(
12448 std::make_unique<CustomElementData>(definition->mType));
12449 // 5.2.2. "Enqueue a custom element upgrade reaction given result and
12450 // definition."
12451 nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
12452 return NS_OK;
12453 }
12454
12455 // 6. "Otherwise:"
12456 // 6.1. "Let interface be the element interface for localName and namespace."
12457 // 6.2. "Set result to the result of creating an element internal..."
12458 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
12459 // Per the Custom Element specification, unknown tags that are valid
12460 // custom element names should be HTMLElement instead of
12461 // HTMLUnknownElement.
12462 if (isCustomElementName) {
12463 NS_IF_ADDREF(*aResult =ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
12464 NS_NewHTMLElement(nodeInfo.forget(), aFromParser))ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
;
12465 } else {
12466 *aResult = CreateHTMLElement(*tag, nodeInfo.forget(), aFromParser).take();
12467 }
12468 } else {
12469 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
12470 }
12471
12472 if (!*aResult) {
12473 return NS_ERROR_OUT_OF_MEMORY;
12474 }
12475
12476 // 6.3. "If namespace is the HTML namespace, and either localName is a valid
12477 // custom element name or is is non-null, then set result's custom
12478 // element state to "undefined"."
12479 if (isCustomElement) {
12480 (*aResult)->SetCustomElementData(
12481 std::make_unique<CustomElementData>(typeAtom));
12482 if (aCustomElementRegistry.isSome()) {
12483 // When an explicit custom element registry is provided, register for
12484 // upgrade on that registry (if non-null), not the document's.
12485 if (CustomElementRegistry* registry = aCustomElementRegistry.ref()) {
12486 registry->RegisterCallbackUpgradeElement(*aResult, typeAtom);
12487 }
12488 } else {
12489 nsContentUtils::RegisterCallbackUpgradeElement(*aResult, typeAtom);
12490 }
12491 }
12492
12493 // 7. "Return result."
12494 return NS_OK;
12495}
12496
12497// https://html.spec.whatwg.org/#look-up-a-custom-element-registry
12498Maybe<RefPtr<CustomElementRegistry>> nsContentUtils::GetCustomElementRegistry(
12499 nsINode* aNode) {
12500 if (!aNode || !StaticPrefs::dom_scoped_custom_element_registries_enabled()) {
12501 return Nothing();
12502 }
12503 // 1. If node is an Element object, then return node's custom element
12504 // registry.
12505 // 2. If node is a ShadowRoot object, then return node's custom element
12506 // registry.
12507 // 3. If node is a Document object, then return node's custom element
12508 // registry.
12509 // A node specifies its own registry only when its state is not Global (i.e.
12510 // scoped, or explicitly null). A Global-state node inherits the global
12511 // registry, which we report as Nothing() so callers can fall back to a
12512 // context registry when parsing into the node.
12513 CustomElementRegistryState state = CustomElementRegistryState::Global;
12514 if (aNode->IsElement()) {
12515 state = aNode->AsElement()->GetCustomElementRegistryState();
12516 } else if (ShadowRoot* shadowRoot = ShadowRoot::FromNode(aNode)) {
12517 state = shadowRoot->GetCustomElementRegistryState();
12518 } else if (aNode->IsDocument()) {
12519 if (!aNode->AsDocument()->HasScopedCustomElementRegistry()) {
12520 // 4. Return null (reported as Nothing(): inherit the global registry).
12521 return Nothing();
12522 }
12523 state = CustomElementRegistryState::Scoped;
12524 } else {
12525 // 4. Return null.
12526 return Nothing();
12527 }
12528 if (state == CustomElementRegistryState::Global) {
12529 return Nothing();
12530 }
12531 RefPtr<CustomElementRegistry> registry;
12532 if (aNode->IsElement()) {
12533 registry = aNode->AsElement()->GetCustomElementRegistry();
12534 } else if (ShadowRoot* shadowRoot = ShadowRoot::FromNode(aNode)) {
12535 registry = shadowRoot->GetCustomElementRegistry();
12536 } else {
12537 registry = aNode->AsDocument()->GetCustomElementRegistry();
12538 }
12539 return Some(std::move(registry));
12540}
12541
12542/* https://html.spec.whatwg.org/#look-up-a-custom-element-definition */
12543CustomElementDefinition* nsContentUtils::LookupCustomElementDefinition(
12544 DocumentOrShadowRoot* aDoc, nsAtom* aNameAtom, uint32_t aNameSpaceID,
12545 nsAtom* aTypeAtom) {
12546 // 2. If namespace is not the HTML namespace, then return null.
12547 if (aNameSpaceID != kNameSpaceID_XUL8 && aNameSpaceID != kNameSpaceID_XHTML3) {
12548 return nullptr;
12549 }
12550
12551 // 1. If registry is null, then return null.
12552 // TODO(keithamus): re-order for Scoped Registries
12553 RefPtr<CustomElementRegistry> registry = aDoc->GetCustomElementRegistry();
12554 if (!registry) {
12555 return nullptr;
12556 }
12557
12558 // XXX: Steps 3-5 performed by
12559 // CustomElementRegistry::LookupCustomElementDefinition:
12560 // 3. If registry's custom element definition set contains an item with name
12561 // and local name both equal to localName, then return that item.
12562 // 4. If registry's custom element definition set contains an item with name
12563 // equal to is and local name equal to localName, then return that item.
12564 // 5. Return null.
12565 return registry->LookupCustomElementDefinition(aNameAtom, aNameSpaceID,
12566 aTypeAtom);
12567}
12568
12569/* static */
12570void nsContentUtils::RegisterCallbackUpgradeElement(Element* aElement,
12571 nsAtom* aTypeName) {
12572 MOZ_ASSERT(aElement)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElement))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aElement", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12572); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 12572); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12573
12574 CustomElementRegistry* registry = aElement->GetCustomElementRegistry();
12575 if (registry) {
12576 registry->RegisterCallbackUpgradeElement(aElement, aTypeName);
12577 }
12578}
12579
12580/* static */
12581void nsContentUtils::RegisterUnresolvedElement(Element* aElement,
12582 nsAtom* aTypeName) {
12583 MOZ_ASSERT(aElement)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElement))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aElement", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12583); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 12583); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12584
12585 CustomElementRegistry* registry = aElement->GetCustomElementRegistry();
12586 if (registry) {
12587 registry->RegisterUnresolvedElement(aElement, aTypeName);
12588 }
12589}
12590
12591/* static */
12592void nsContentUtils::UnregisterUnresolvedElement(Element* aElement) {
12593 MOZ_ASSERT(aElement)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElement))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aElement", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12593); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 12593); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12594
12595 nsAtom* typeAtom = aElement->GetCustomElementData()->GetCustomElementType();
12596 CustomElementRegistry* registry = aElement->GetCustomElementRegistry();
12597 if (registry) {
12598 registry->UnregisterUnresolvedElement(aElement, typeAtom);
12599 }
12600}
12601
12602/* static */
12603void nsContentUtils::EnqueueUpgradeReaction(
12604 Element* aElement, CustomElementDefinition* aDefinition) {
12605 MOZ_ASSERT(aElement)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElement)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aElement))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aElement", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12605); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 12605); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12606
12607 Document* doc = aElement->OwnerDoc();
12608
12609 // No DocGroup means no custom element reactions stack.
12610 if (!doc->GetDocGroup()) {
12611 return;
12612 }
12613
12614 CustomElementReactionsStack* stack =
12615 doc->GetDocGroup()->CustomElementReactionsStack();
12616 stack->EnqueueUpgradeReaction(aElement, aDefinition);
12617}
12618
12619/* static */
12620void nsContentUtils::EnqueueLifecycleCallback(
12621 ElementCallbackType aType, Element* aCustomElement,
12622 const LifecycleCallbackArgs& aArgs, CustomElementDefinition* aDefinition) {
12623 // No DocGroup means no custom element reactions stack.
12624 if (!aCustomElement->OwnerDoc()->GetDocGroup()) {
12625 return;
12626 }
12627
12628 CustomElementRegistry::EnqueueLifecycleCallback(aType, aCustomElement, aArgs,
12629 aDefinition);
12630}
12631
12632/* static */
12633CustomElementFormValue nsContentUtils::ConvertToCustomElementFormValue(
12634 const Nullable<OwningFileOrUSVStringOrFormData>& aState) {
12635 if (aState.IsNull()) {
12636 return void_t{};
12637 }
12638 const auto& state = aState.Value();
12639 if (state.IsFile()) {
12640 RefPtr<BlobImpl> impl = state.GetAsFile()->Impl();
12641 return {std::move(impl)};
12642 }
12643 if (state.IsUSVString()) {
12644 return state.GetAsUSVString();
12645 }
12646 return state.GetAsFormData()->ConvertToCustomElementFormValue();
12647}
12648
12649/* static */
12650Nullable<OwningFileOrUSVStringOrFormData>
12651nsContentUtils::ExtractFormAssociatedCustomElementValue(
12652 nsIGlobalObject* aGlobal,
12653 const mozilla::dom::CustomElementFormValue& aCEValue) {
12654 MOZ_ASSERT(aGlobal)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aGlobal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aGlobal))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aGlobal", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12654); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aGlobal" ")"
); do { MOZ_CrashSequence(__null, 12654); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12655
12656 OwningFileOrUSVStringOrFormData value;
12657 switch (aCEValue.type()) {
12658 case CustomElementFormValue::TBlobImpl: {
12659 RefPtr<File> file = File::Create(aGlobal, aCEValue.get_BlobImpl());
12660 if (NS_WARN_IF(!file)NS_warn_if_impl(!file, "!file", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12660)
) {
12661 return {};
12662 }
12663 value.SetAsFile() = file;
12664 } break;
12665
12666 case CustomElementFormValue::TnsString:
12667 value.SetAsUSVString() = aCEValue.get_nsString();
12668 break;
12669
12670 case CustomElementFormValue::TArrayOfFormDataTuple: {
12671 const auto& array = aCEValue.get_ArrayOfFormDataTuple();
12672 auto formData = MakeRefPtr<FormData>();
12673
12674 for (auto i = 0ul; i < array.Length(); ++i) {
12675 const auto& item = array.ElementAt(i);
12676 switch (item.value().type()) {
12677 case IPCFormDataValue::TnsString:
12678 formData->AddNameValuePair(item.name(),
12679 item.value().get_nsString());
12680 break;
12681
12682 case IPCFormDataValue::TBlobImpl: {
12683 auto blobImpl = item.value().get_BlobImpl();
12684 RefPtr<Blob> blob = Blob::Create(aGlobal, blobImpl);
12685 formData->AddNameBlobPair(item.name(), blob);
12686 } break;
12687
12688 default:
12689 continue;
12690 }
12691 }
12692
12693 value.SetAsFormData() = formData;
12694 } break;
12695 case CustomElementFormValue::Tvoid_t:
12696 return {};
12697 default:
12698 NS_WARNING("Invalid CustomElementContentData type!")NS_DebugBreak(NS_DEBUG_WARNING, "Invalid CustomElementContentData type!"
, nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp",
12698)
;
12699 return {};
12700 }
12701 return value;
12702}
12703
12704/* static */
12705void nsContentUtils::AppendDocumentLevelNativeAnonymousContentTo(
12706 Document* aDocument, nsTArray<nsIContent*>& aElements) {
12707 MOZ_ASSERT(aDocument)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDocument)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDocument))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aDocument", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument"
")"); do { MOZ_CrashSequence(__null, 12707); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12708#ifdef DEBUG1
12709 size_t oldLength = aElements.Length();
12710#endif
12711
12712 if (PresShell* presShell = aDocument->GetPresShell()) {
12713 if (ScrollContainerFrame* rootScrollContainerFrame =
12714 presShell->GetRootScrollContainerFrame()) {
12715 rootScrollContainerFrame->AppendAnonymousContentTo(aElements, 0);
12716 }
12717 if (nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame()) {
12718 canvasFrame->AppendAnonymousContentTo(aElements, 0);
12719 }
12720 }
12721
12722 if (auto* el = aDocument->GetCustomContentContainer()) {
12723 aElements.AppendElement(el);
12724 }
12725
12726#ifdef DEBUG1
12727 for (size_t i = oldLength; i < aElements.Length(); i++) {
12728 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
" (" "Someone here has lied, or missed to flag the node" ")"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12730); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
") (" "Someone here has lied, or missed to flag the node" ")"
); do { MOZ_CrashSequence(__null, 12730); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
12729 aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
" (" "Someone here has lied, or missed to flag the node" ")"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12730); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
") (" "Someone here has lied, or missed to flag the node" ")"
); do { MOZ_CrashSequence(__null, 12730); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
12730 "Someone here has lied, or missed to flag the node")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
" (" "Someone here has lied, or missed to flag the node" ")"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12730); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
") (" "Someone here has lied, or missed to flag the node" ")"
); do { MOZ_CrashSequence(__null, 12730); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12731 }
12732#endif
12733}
12734
12735static void AppendNativeAnonymousChildrenFromFrame(nsIFrame* aFrame,
12736 nsTArray<nsIContent*>& aKids,
12737 uint32_t aFlags) {
12738 if (nsIAnonymousContentCreator* ac = do_QueryFrame(aFrame)) {
12739 ac->AppendAnonymousContentTo(aKids, aFlags);
12740 }
12741}
12742
12743/* static */
12744void nsContentUtils::AppendNativeAnonymousChildren(const nsIContent* aContent,
12745 nsTArray<nsIContent*>& aKids,
12746 uint32_t aFlags) {
12747 if (aContent->MayHaveAnonymousChildren()) {
12748 if (nsIFrame* primaryFrame = aContent->GetPrimaryFrame()) {
12749 // NAC created by the element's primary frame.
12750 AppendNativeAnonymousChildrenFromFrame(primaryFrame, aKids, aFlags);
12751
12752 // NAC created by any other non-primary frames for the element.
12753 AutoTArray<nsIFrame::OwnedAnonBox, 8> ownedAnonBoxes;
12754 primaryFrame->AppendOwnedAnonBoxes(ownedAnonBoxes);
12755 for (nsIFrame::OwnedAnonBox& box : ownedAnonBoxes) {
12756 MOZ_ASSERT(box.mAnonBoxFrame->GetContent() == aContent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(box.mAnonBoxFrame->GetContent() == aContent)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(box.mAnonBoxFrame->GetContent() == aContent))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("box.mAnonBoxFrame->GetContent() == aContent"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12756); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "box.mAnonBoxFrame->GetContent() == aContent"
")"); do { MOZ_CrashSequence(__null, 12756); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12757 AppendNativeAnonymousChildrenFromFrame(box.mAnonBoxFrame, aKids,
12758 aFlags);
12759 }
12760 }
12761
12762 // View transition pseudos.
12763 if (aContent->IsRootElement()) {
12764 if (auto* vt = aContent->OwnerDoc()->GetActiveViewTransition()) {
12765 if (auto* root = vt->GetSnapshotContainingBlock()) {
12766 aKids.AppendElement(root);
12767 }
12768 }
12769 }
12770
12771 // Get manually created NAC (editor resize handles, etc.).
12772 if (auto nac = static_cast<ManualNACArray*>(
12773 aContent->GetProperty(nsGkAtoms::manualNACProperty))) {
12774 aKids.AppendElements(*nac);
12775 }
12776 }
12777
12778 // The root scroll frame is not the primary frame of the root element.
12779 // Detect and handle this case.
12780 if (!(aFlags & nsIContent::eSkipDocumentLevelNativeAnonymousContent) &&
12781 aContent->IsRootElement()) {
12782 AppendDocumentLevelNativeAnonymousContentTo(aContent->OwnerDoc(), aKids);
12783 }
12784}
12785
12786bool nsContentUtils::IsImageAvailable(nsIContent* aLoadingNode, nsIURI* aURI,
12787 nsIPrincipal* aDefaultTriggeringPrincipal,
12788 CORSMode aCORSMode) {
12789 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
12790 QueryTriggeringPrincipal(aLoadingNode, aDefaultTriggeringPrincipal,
12791 getter_AddRefs(triggeringPrincipal));
12792 MOZ_ASSERT(triggeringPrincipal)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(triggeringPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(triggeringPrincipal))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("triggeringPrincipal"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12792); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "triggeringPrincipal" ")"); do { MOZ_CrashSequence
(__null, 12792); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12793
12794 Document* doc = aLoadingNode->OwnerDoc();
12795 return IsImageAvailable(aURI, triggeringPrincipal, aCORSMode, doc);
12796}
12797
12798bool nsContentUtils::IsImageAvailable(nsIURI* aURI,
12799 nsIPrincipal* aTriggeringPrincipal,
12800 CORSMode aCORSMode, Document* aDoc) {
12801 imgLoader* imgLoader = GetImgLoaderForDocument(aDoc);
12802 return imgLoader->IsImageAvailable(aURI, aTriggeringPrincipal, aCORSMode,
12803 aDoc);
12804}
12805
12806/* static */
12807bool nsContentUtils::QueryTriggeringPrincipal(
12808 nsIContent* aLoadingNode, nsIPrincipal* aDefaultPrincipal,
12809 nsIPrincipal** aTriggeringPrincipal) {
12810 MOZ_ASSERT(aLoadingNode)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLoadingNode)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLoadingNode))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aLoadingNode", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingNode"
")"); do { MOZ_CrashSequence(__null, 12810); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12811 MOZ_ASSERT(aTriggeringPrincipal)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTriggeringPrincipal)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aTriggeringPrincipal))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aTriggeringPrincipal"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12811); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aTriggeringPrincipal" ")"); do { MOZ_CrashSequence
(__null, 12811); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12812
12813 bool result = false;
12814 nsCOMPtr<nsIPrincipal> loadingPrincipal = aDefaultPrincipal;
12815 if (!loadingPrincipal) {
12816 loadingPrincipal = aLoadingNode->NodePrincipal();
12817 }
12818
12819 // If aLoadingNode is content, bail out early.
12820 if (!aLoadingNode->NodePrincipal()->IsSystemPrincipal()) {
12821 loadingPrincipal.forget(aTriggeringPrincipal);
12822 return result;
12823 }
12824
12825 nsAutoString loadingStr;
12826 if (aLoadingNode->IsElement()) {
12827 aLoadingNode->AsElement()->GetAttr(
12828 kNameSpaceID_None, nsGkAtoms::triggeringprincipal, loadingStr);
12829 }
12830
12831 // Fall back if 'triggeringprincipal' isn't specified,
12832 if (loadingStr.IsEmpty()) {
12833 loadingPrincipal.forget(aTriggeringPrincipal);
12834 return result;
12835 }
12836
12837 nsCString binary;
12838 nsCOMPtr<nsIPrincipal> serializedPrin =
12839 BasePrincipal::FromJSON(NS_ConvertUTF16toUTF8(loadingStr));
12840 if (serializedPrin) {
12841 result = true;
12842 serializedPrin.forget(aTriggeringPrincipal);
12843 }
12844
12845 if (!result) {
12846 // Fallback if the deserialization is failed.
12847 loadingPrincipal.forget(aTriggeringPrincipal);
12848 }
12849
12850 return result;
12851}
12852
12853/* static */
12854void nsContentUtils::GetContentPolicyTypeForUIImageLoading(
12855 nsIContent* aLoadingNode, nsIPrincipal** aTriggeringPrincipal,
12856 nsContentPolicyType& aContentPolicyType, uint64_t* aRequestContextID) {
12857 MOZ_ASSERT(aRequestContextID)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRequestContextID)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aRequestContextID))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aRequestContextID"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12857); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequestContextID" ")"); do { MOZ_CrashSequence
(__null, 12857); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12858
12859 bool result = QueryTriggeringPrincipal(aLoadingNode, aTriggeringPrincipal);
12860 if (result) {
12861 // Set the content policy type to TYPE_INTERNAL_IMAGE_FAVICON for
12862 // indicating it's a favicon loading.
12863 aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON;
12864
12865 nsAutoString requestContextID;
12866 if (aLoadingNode->IsElement()) {
12867 aLoadingNode->AsElement()->GetAttr(
12868 kNameSpaceID_None, nsGkAtoms::requestcontextid, requestContextID);
12869 }
12870 nsresult rv;
12871 int64_t val = requestContextID.ToInteger64(&rv);
12872 *aRequestContextID = NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) ? val : 0;
12873 } else {
12874 aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE;
12875 }
12876}
12877
12878/* static */
12879nsresult nsContentUtils::CreateJSValueFromSequenceOfObject(
12880 JSContext* aCx, const Sequence<JSObject*>& aTransfer,
12881 JS::MutableHandle<JS::Value> aValue) {
12882 if (aTransfer.IsEmpty()) {
12883 return NS_OK;
12884 }
12885
12886 JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, aTransfer.Length()));
12887 if (!array) {
12888 return NS_ERROR_OUT_OF_MEMORY;
12889 }
12890
12891 for (uint32_t i = 0; i < aTransfer.Length(); ++i) {
12892 JS::Rooted<JSObject*> object(aCx, aTransfer[i]);
12893 if (!object) {
12894 continue;
12895 }
12896
12897 if (NS_WARN_IF(NS_warn_if_impl(!JS_DefineElement(aCx, array, i, object, JSPROP_ENUMERATE
), "!JS_DefineElement(aCx, array, i, object, JSPROP_ENUMERATE)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12898)
12898 !JS_DefineElement(aCx, array, i, object, JSPROP_ENUMERATE))NS_warn_if_impl(!JS_DefineElement(aCx, array, i, object, JSPROP_ENUMERATE
), "!JS_DefineElement(aCx, array, i, object, JSPROP_ENUMERATE)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 12898)
) {
12899 return NS_ERROR_OUT_OF_MEMORY;
12900 }
12901 }
12902
12903 aValue.setObject(*array);
12904 return NS_OK;
12905}
12906
12907/* static */
12908void nsContentUtils::StructuredClone(JSContext* aCx, nsIGlobalObject* aGlobal,
12909 JS::Handle<JS::Value> aValue,
12910 const StructuredSerializeOptions& aOptions,
12911 JS::MutableHandle<JS::Value> aRetval,
12912 ErrorResult& aError) {
12913 JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
12914 aError = nsContentUtils::CreateJSValueFromSequenceOfObject(
12915 aCx, aOptions.mTransfer, &transferArray);
12916 if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12916)
) {
12917 return;
12918 }
12919
12920 JS::CloneDataPolicy clonePolicy;
12921 // We are definitely staying in the same agent cluster.
12922 clonePolicy.allowIntraClusterClonableSharedObjects();
12923 if (aGlobal->IsSharedMemoryAllowed()) {
12924 clonePolicy.allowSharedMemoryObjects();
12925 }
12926
12927 // 2.7.10 Structured cloning API
12928 // Step 1: Let serialized be
12929 // ? StructuredSerializeWithTransfer(value, options["transfer"])
12930 StructuredCloneHolder holder(StructuredCloneHolder::CloningSupported,
12931 StructuredCloneHolder::TransferringSupported,
12932 JS::StructuredCloneScope::SameProcess);
12933 holder.Write(aCx, aValue, transferArray, clonePolicy, aError);
12934 if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12934)
) {
12935 return;
12936 }
12937
12938 // Step 2: Let deserializeRecord be
12939 // ? StructuredDeserializeWithTransfer(serialized, this's relevant realm).
12940 JSAutoRealm ar(aCx, aGlobal->GetGlobalJSObject());
12941 holder.Read(aCx, aRetval, clonePolicy, aError);
12942 if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12942)
) {
12943 return;
12944 }
12945
12946 // Step 3: Return deserializeRecord.[[Deserialized]].
12947 // (discarding deserializeRecord.[[TransferredValues]])
12948 nsTArray<RefPtr<MessagePort>> ports = holder.TakeTransferredPorts();
12949 (void)ports;
12950}
12951
12952/* static */
12953bool nsContentUtils::ShouldBlockReservedKeys(WidgetKeyboardEvent* aKeyEvent) {
12954 nsCOMPtr<nsIPrincipal> principal;
12955 RefPtr<Element> targetElement =
12956 Element::FromEventTargetOrNull(aKeyEvent->mOriginalTarget);
12957 nsCOMPtr<nsIBrowser> targetBrowser;
12958 if (targetElement) {
12959 targetBrowser = targetElement->AsBrowser();
12960 }
12961 bool isRemoteBrowser = false;
12962 if (targetBrowser) {
12963 targetBrowser->GetIsRemoteBrowser(&isRemoteBrowser);
12964 }
12965
12966 if (isRemoteBrowser) {
12967 targetBrowser->GetContentPrincipal(getter_AddRefs(principal));
12968 return principal ? nsContentUtils::IsSitePermDeny(principal, "shortcuts"_ns)
12969 : false;
12970 }
12971
12972 if (targetElement) {
12973 Document* doc = targetElement->GetUncomposedDoc();
12974 if (doc) {
12975 RefPtr<WindowContext> wc = doc->GetWindowContext();
12976 if (wc) {
12977 return wc->TopWindowContext()->GetShortcutsPermission() ==
12978 nsIPermissionManager::DENY_ACTION;
12979 }
12980 }
12981 }
12982
12983 return false;
12984}
12985
12986/**
12987 * Checks whether the given type is a supported document type for
12988 * loading within the nsObjectLoadingContent specified by aContent.
12989 *
12990 * NOTE Helper method for nsContentUtils::HtmlObjectContentTypeForMIMEType.
12991 * NOTE Does not take content policy or capabilities into account
12992 */
12993static bool HtmlObjectContentSupportsDocument(const nsCString& aMimeType) {
12994 nsCOMPtr<nsIWebNavigationInfo> info(
12995 do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID"@mozilla.org/webnavigation-info;1"));
12996 if (!info) {
12997 return false;
12998 }
12999
13000 uint32_t supported;
13001 nsresult rv = info->IsTypeSupported(aMimeType, &supported);
13002
13003 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
13004 return false;
13005 }
13006
13007 if (supported != nsIWebNavigationInfo::UNSUPPORTED) {
13008 return true;
13009 }
13010
13011 // Try a stream converter
13012 // NOTE: We treat any type we can convert from as a supported type. If a
13013 // type is not actually supported, the URI loader will detect that and
13014 // return an error, and we'll fallback.
13015 nsCOMPtr<nsIStreamConverterService> convServ =
13016 do_GetService("@mozilla.org/streamConverters;1");
13017 bool canConvert = false;
13018 if (convServ) {
13019 rv = convServ->CanConvert(aMimeType.get(), "*/*", &canConvert);
13020 }
13021 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && canConvert;
13022}
13023
13024/* static */
13025uint32_t nsContentUtils::HtmlObjectContentTypeForMIMEType(
13026 const nsCString& aMIMEType, bool aIsSandboxed) {
13027 if (aMIMEType.IsEmpty()) {
13028 return nsIObjectLoadingContent::TYPE_FALLBACK;
13029 }
13030
13031 if (imgLoader::SupportImageWithMimeType(aMIMEType)) {
13032 return nsIObjectLoadingContent::TYPE_DOCUMENT;
13033 }
13034
13035 // Faking support of the PDF content as a document for EMBED tags when the
13036 // internal PDF viewer or the embedded PDF fallback is enabled.
13037 if (aMIMEType.LowerCaseEqualsLiteral(APPLICATION_PDF"application/pdf") &&
13038 (IsPDFJSEnabled() || StaticPrefs::pdfjs_embedFallback())) {
13039 // Sandboxed iframes are just never allowed to display plugins. In the
13040 // modern world, this just means "application/pdf".
13041 return aIsSandboxed ? nsIObjectLoadingContent::TYPE_FALLBACK
13042 : nsIObjectLoadingContent::TYPE_DOCUMENT;
13043 }
13044
13045 if (HtmlObjectContentSupportsDocument(aMIMEType)) {
13046 return nsIObjectLoadingContent::TYPE_DOCUMENT;
13047 }
13048
13049 return nsIObjectLoadingContent::TYPE_FALLBACK;
13050}
13051
13052/* static */
13053bool nsContentUtils::IsLocalRefURL(const nsAString& aString) {
13054 return !aString.IsEmpty() && aString[0] == '#';
13055}
13056
13057// We use only 53 bits for the ID so that it can be converted to and from a JS
13058// value without loss of precision. The upper bits of the ID hold the process
13059// ID. The lower bits identify the object itself.
13060static constexpr uint64_t kIdTotalBits = 53;
13061static constexpr uint64_t kIdProcessBits = 22;
13062static constexpr uint64_t kIdBits = kIdTotalBits - kIdProcessBits;
13063
13064/* static */
13065uint64_t nsContentUtils::GenerateProcessSpecificId(uint64_t aId) {
13066 uint64_t processId = XRE_GetChildID();
13067
13068 MOZ_RELEASE_ASSERT(processId < (uint64_t(1) << kIdProcessBits))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(processId < (uint64_t(1) << kIdProcessBits)
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(processId < (uint64_t(1) << kIdProcessBits)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"processId < (uint64_t(1) << kIdProcessBits)", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13068); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "processId < (uint64_t(1) << kIdProcessBits)"
")"); do { MOZ_CrashSequence(__null, 13068); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13069 uint64_t processBits = processId & ((uint64_t(1) << kIdProcessBits) - 1);
13070
13071 uint64_t id = aId;
13072 MOZ_RELEASE_ASSERT(id < (uint64_t(1) << kIdBits))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(id < (uint64_t(1) << kIdBits))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(id < (uint64_t(1) << kIdBits)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("id < (uint64_t(1) << kIdBits)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13072); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "id < (uint64_t(1) << kIdBits)"
")"); do { MOZ_CrashSequence(__null, 13072); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13073 uint64_t bits = id & ((uint64_t(1) << kIdBits) - 1);
13074
13075 return (processBits << kIdBits) | bits;
13076}
13077
13078/* static */
13079std::tuple<GeckoChildID, uint64_t> nsContentUtils::SplitProcessSpecificId(
13080 uint64_t aId) {
13081 return {GeckoChildID(aId >> kIdBits), aId & ((uint64_t(1) << kIdBits) - 1)};
13082}
13083
13084/* static */
13085bool nsContentUtils::IsProcessSpecificIdFrom(uint64_t aId,
13086 GeckoChildID aChildID) {
13087 return (aId >> kIdBits) == static_cast<uint64_t>(aChildID);
13088}
13089
13090// Next process-local Tab ID.
13091static uint64_t gNextTabId = 0;
13092
13093/* static */
13094uint64_t nsContentUtils::GenerateTabId() {
13095 return GenerateProcessSpecificId(++gNextTabId);
13096}
13097
13098// Next process-local Browser ID.
13099static uint64_t gNextBrowserId = 0;
13100
13101/* static */
13102uint64_t nsContentUtils::GenerateBrowserId() {
13103 return GenerateProcessSpecificId(++gNextBrowserId);
13104}
13105
13106// Next process-local Browsing Context ID.
13107static uint64_t gNextBrowsingContextId = 0;
13108
13109/* static */
13110uint64_t nsContentUtils::GenerateBrowsingContextId() {
13111 return GenerateProcessSpecificId(++gNextBrowsingContextId);
13112}
13113
13114// Next process-local Window ID.
13115static uint64_t gNextWindowId = 0;
13116
13117/* static */
13118uint64_t nsContentUtils::GenerateWindowId() {
13119 return GenerateProcessSpecificId(++gNextWindowId);
13120}
13121
13122// Next process-local load.
13123static Atomic<uint64_t> gNextLoadIdentifier(0);
13124
13125/* static */
13126uint64_t nsContentUtils::GenerateLoadIdentifier() {
13127 return GenerateProcessSpecificId(++gNextLoadIdentifier);
13128}
13129
13130/* static */
13131bool nsContentUtils::GetUserIsInteracting() {
13132 return UserInteractionObserver::sUserActive;
13133}
13134
13135/* static */
13136bool nsContentUtils::GetSourceMapURL(nsIHttpChannel* aChannel,
13137 nsACString& aResult) {
13138 nsresult rv = aChannel->GetResponseHeader("SourceMap"_ns, aResult);
13139 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
13140 rv = aChannel->GetResponseHeader("X-SourceMap"_ns, aResult);
13141 }
13142 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)));
13143}
13144
13145/* static */
13146bool nsContentUtils::IsMessageInputEvent(const IPC::Message& aMsg) {
13147 if ((aMsg.type() & mozilla::dom::PBrowser::PBrowserStart) ==
13148 mozilla::dom::PBrowser::PBrowserStart) {
13149 switch (aMsg.type()) {
13150 case mozilla::dom::PBrowser::Msg_RealMouseMoveEvent__ID:
13151 case mozilla::dom::PBrowser::Msg_RealMouseButtonEvent__ID:
13152 case mozilla::dom::PBrowser::Msg_RealMouseEnterExitWidgetEvent__ID:
13153 case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID:
13154 case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID:
13155 case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID:
13156 case mozilla::dom::PBrowser::Msg_RealTouchMoveEvent__ID:
13157 case mozilla::dom::PBrowser::Msg_RealDragEvent__ID:
13158 case mozilla::dom::PBrowser::Msg_UpdateDimensions__ID:
13159 return true;
13160 }
13161 }
13162 return false;
13163}
13164
13165/* static */
13166bool nsContentUtils::IsMessageCriticalInputEvent(const IPC::Message& aMsg) {
13167 if ((aMsg.type() & mozilla::dom::PBrowser::PBrowserStart) ==
13168 mozilla::dom::PBrowser::PBrowserStart) {
13169 switch (aMsg.type()) {
13170 case mozilla::dom::PBrowser::Msg_RealMouseButtonEvent__ID:
13171 case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID:
13172 case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID:
13173 case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID:
13174 case mozilla::dom::PBrowser::Msg_RealDragEvent__ID:
13175 return true;
13176 }
13177 }
13178 return false;
13179}
13180
13181static const char* kUserInteractionInactive = "user-interaction-inactive";
13182static const char* kUserInteractionActive = "user-interaction-active";
13183
13184void nsContentUtils::UserInteractionObserver::Init() {
13185 // Listen for the observer messages from EventStateManager which are telling
13186 // us whether or not the user is interacting.
13187 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
13188 obs->AddObserver(this, kUserInteractionInactive, false);
13189 obs->AddObserver(this, kUserInteractionActive, false);
13190
13191 // We can't register ourselves as an annotator yet, as the
13192 // BackgroundHangMonitor hasn't started yet. It will have started by the
13193 // time we have the chance to spin the event loop.
13194 RefPtr<UserInteractionObserver> self = this;
13195 NS_DispatchToMainThread(NS_NewRunnableFunction(
13196 "nsContentUtils::UserInteractionObserver::Init",
13197 [=]() { BackgroundHangMonitor::RegisterAnnotator(*self); }));
13198}
13199
13200void nsContentUtils::UserInteractionObserver::Shutdown() {
13201 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
13202 if (obs) {
13203 obs->RemoveObserver(this, kUserInteractionInactive);
13204 obs->RemoveObserver(this, kUserInteractionActive);
13205 }
13206
13207 BackgroundHangMonitor::UnregisterAnnotator(*this);
13208}
13209
13210/**
13211 * NB: This function is always called by the BackgroundHangMonitor thread.
13212 * Plan accordingly
13213 */
13214void nsContentUtils::UserInteractionObserver::AnnotateHang(
13215 BackgroundHangAnnotations& aAnnotations) {
13216 // NOTE: Only annotate the hang report if the user is known to be interacting.
13217 if (sUserActive) {
13218 aAnnotations.AddAnnotation(u"UserInteracting"_ns, true);
13219 }
13220}
13221
13222NS_IMETHODIMPnsresult
13223nsContentUtils::UserInteractionObserver::Observe(nsISupports* aSubject,
13224 const char* aTopic,
13225 const char16_t* aData) {
13226 if (!strcmp(aTopic, kUserInteractionInactive)) {
13227 if (sUserActive && XRE_IsParentProcess()) {
13228 glean::RecordPowerMetrics();
13229 }
13230 sUserActive = false;
13231 } else if (!strcmp(aTopic, kUserInteractionActive)) {
13232 if (!sUserActive && XRE_IsParentProcess()) {
13233 glean::RecordPowerMetrics();
13234
13235 nsCOMPtr<nsIUserIdleServiceInternal> idleService =
13236 do_GetService("@mozilla.org/widget/useridleservice;1");
13237 if (idleService) {
13238 idleService->ResetIdleTimeOut(0);
13239 }
13240 }
13241
13242 sUserActive = true;
13243 } else {
13244 NS_WARNING("Unexpected observer notification")NS_DebugBreak(NS_DEBUG_WARNING, "Unexpected observer notification"
, nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp",
13244)
;
13245 }
13246 return NS_OK;
13247}
13248
13249Atomic<bool> nsContentUtils::UserInteractionObserver::sUserActive(false);
13250NS_IMPL_ISUPPORTS(nsContentUtils::UserInteractionObserver, nsIObserver)MozExternalRefCountType nsContentUtils::UserInteractionObserver
::AddRef(void) { static_assert(!std::is_destructible_v<nsContentUtils
::UserInteractionObserver>, "Reference-counted class " "nsContentUtils::UserInteractionObserver"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13250); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 13250
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsContentUtils::UserInteractionObserver" != nullptr
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsContentUtils::UserInteractionObserver" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsContentUtils::UserInteractionObserver\" != nullptr" " ("
"Must specify a name" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13250); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsContentUtils::UserInteractionObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 13250); __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsContentUtils::UserInteractionObserver" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"nsContentUtils::UserInteractionObserver"), (uint32_t)(sizeof
(*this))); return count; } MozExternalRefCountType nsContentUtils
::UserInteractionObserver::Release(void) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13250); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 13250
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsContentUtils::UserInteractionObserver" != nullptr
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsContentUtils::UserInteractionObserver" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsContentUtils::UserInteractionObserver\" != nullptr" " ("
"Must specify a name" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13250); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsContentUtils::UserInteractionObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 13250); __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsContentUtils::UserInteractionObserver" " not thread-safe"
); const char* const nametmp = "nsContentUtils::UserInteractionObserver"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult nsContentUtils::UserInteractionObserver
::QueryInterface(const nsIID& aIID, void** aInstancePtr) {
do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13250); MOZ_PretendNoReturn
(); } } while (0); nsresult rv = NS_ERROR_FAILURE; static_assert
(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"); static
const QITableEntry table[] = { {&mozilla::detail::kImplementedIID
<nsContentUtils::UserInteractionObserver, nsIObserver>,
int32_t( reinterpret_cast<char*>(static_cast<nsIObserver
*>((nsContentUtils::UserInteractionObserver*)0x1000)) - reinterpret_cast
<char*>((nsContentUtils::UserInteractionObserver*)0x1000
))}, {&mozilla::detail::kImplementedIID<nsContentUtils
::UserInteractionObserver, nsISupports>, int32_t(reinterpret_cast
<char*>(static_cast<nsISupports*>( static_cast<
nsIObserver*>((nsContentUtils::UserInteractionObserver*)0x1000
))) - reinterpret_cast<char*>((nsContentUtils::UserInteractionObserver
*)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table
) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
13251
13252/* static */
13253bool nsContentUtils::IsSpecialName(const nsAString& aName) {
13254 return aName.LowerCaseEqualsLiteral("_blank") ||
13255 aName.LowerCaseEqualsLiteral("_top") ||
13256 aName.LowerCaseEqualsLiteral("_parent") ||
13257 aName.LowerCaseEqualsLiteral("_self");
13258}
13259
13260/* static */
13261bool nsContentUtils::IsOverridingWindowName(const nsAString& aName) {
13262 return !aName.IsEmpty() && !IsSpecialName(aName);
13263}
13264
13265// Unfortunately, we can't unwrap an IDL object using only a concrete type.
13266// We need to calculate type data based on the IDL typename. Which means
13267// wrapping our templated function in a macro.
13268#define EXTRACT_EXN_VALUES(T, ...) \
13269 ExtractExceptionValuesImpl<mozilla::dom::prototypes::id::T, \
13270 T##_Binding::NativeType, T>(__VA_ARGS__) \
13271 .isOk()
13272
13273template <prototypes::ID PrototypeID, class NativeType, typename T>
13274static Result<Ok, nsresult> ExtractExceptionValuesImpl(
13275 JSContext* aCx, JS::Handle<JSObject*> aObj, nsACString& aFilename,
13276 uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) {
13277 AssertStaticUnwrapOK<PrototypeID>();
13278 RefPtr<T> exn;
13279 MOZ_TRY((UnwrapObject<PrototypeID, NativeType>(aObj, exn, nullptr)))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
((UnwrapObject<PrototypeID, NativeType>(aObj, exn, nullptr
))); if ((__builtin_expect(!!(mozTryVarTempResult.isErr()), 0
))) { return mozTryVarTempResult.propagateErr(); } mozTryVarTempResult
.unwrap(); })
;
13280
13281 if (nsCOMPtr<nsIStackFrame> location = exn->GetLocation()) {
13282 location->GetFilename(aCx, aFilename);
13283 *aLineOut = location->GetLineNumber(aCx);
13284 *aColumnOut = location->GetColumnNumber(aCx);
13285 } else {
13286 aFilename.Truncate();
13287 *aLineOut = 0;
13288 *aColumnOut = 0;
13289 }
13290
13291 exn->GetName(aMessageOut);
13292 aMessageOut.AppendLiteral(": ");
13293
13294 nsAutoString message;
13295 exn->GetMessageMoz(message);
13296 aMessageOut.Append(message);
13297 return Ok();
13298}
13299
13300/* static */
13301bool nsContentUtils::ExtractExceptionValues(
13302 JSContext* aCx, JS::Handle<JSObject*> aObj, nsACString& aFilename,
13303 uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) {
13304 return EXTRACT_EXN_VALUES(DOMException, aCx, aObj, aFilename, aLineOut,
13305 aColumnOut, aMessageOut) ||
13306 EXTRACT_EXN_VALUES(Exception, aCx, aObj, aFilename, aLineOut,
13307 aColumnOut, aMessageOut);
13308}
13309
13310/* static */
13311void nsContentUtils::ExtractErrorValues(
13312 JSContext* aCx, JS::Handle<JS::Value> aValue, nsACString& aSourceSpecOut,
13313 uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) {
13314 MOZ_ASSERT(aLineOut)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aLineOut)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aLineOut))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aLineOut", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13314); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLineOut" ")"
); do { MOZ_CrashSequence(__null, 13314); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13315 MOZ_ASSERT(aColumnOut)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aColumnOut)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aColumnOut))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aColumnOut", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aColumnOut"
")"); do { MOZ_CrashSequence(__null, 13315); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13316
13317 if (aValue.isObject()) {
13318 JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
13319
13320 // Try to process as an Error object. Use the file/line/column values
13321 // from the Error as they will be more specific to the root cause of
13322 // the problem.
13323 JS::BorrowedErrorReport err(aCx);
13324 if (JS_ErrorFromException(aCx, obj, err)) {
13325 // Use xpc to extract the error message only. We don't actually send
13326 // this report anywhere.
13327 RefPtr<xpc::ErrorReport> report = new xpc::ErrorReport();
13328 report->Init(err.get(),
13329 nullptr, // toString result
13330 false, // chrome
13331 0); // window ID
13332
13333 if (!report->mFileName.IsEmpty()) {
13334 aSourceSpecOut = report->mFileName;
13335 *aLineOut = report->mLineNumber;
13336 *aColumnOut = report->mColumn;
13337 }
13338 aMessageOut.Assign(report->mErrorMsg);
13339 }
13340
13341 // Next, try to unwrap the rejection value as a (DOM)Exception.
13342 else if (ExtractExceptionValues(aCx, obj, aSourceSpecOut, aLineOut,
13343 aColumnOut, aMessageOut)) {
13344 return;
13345 }
13346 }
13347
13348 // If we could not unwrap a specific error type, then perform default safe
13349 // string conversions on primitives. Objects will result in "[Object]"
13350 // unfortunately.
13351 if (aMessageOut.IsEmpty()) {
13352 nsAutoJSString jsString;
13353 if (jsString.init(aCx, aValue)) {
13354 aMessageOut = jsString;
13355 } else {
13356 JS_ClearPendingException(aCx);
13357 }
13358 }
13359}
13360
13361#undef EXTRACT_EXN_VALUES
13362
13363/* static */
13364bool nsContentUtils::ContentIsLink(nsIContent* aContent) {
13365 if (!aContent || !aContent->IsElement()) {
13366 return false;
13367 }
13368
13369 if (aContent->IsHTMLElement(nsGkAtoms::a)) {
13370 return true;
13371 }
13372
13373 return aContent->AsElement()->AttrValueIs(kNameSpaceID_XLink4, nsGkAtoms::type,
13374 nsGkAtoms::simple, eCaseMatters);
13375}
13376
13377/* static */
13378already_AddRefed<ContentFrameMessageManager>
13379nsContentUtils::TryGetBrowserChildGlobal(nsISupports* aFrom) {
13380 RefPtr<nsFrameLoaderOwner> frameLoaderOwner = do_QueryObject(aFrom);
13381 if (!frameLoaderOwner) {
13382 return nullptr;
13383 }
13384
13385 RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
13386 if (!frameLoader) {
13387 return nullptr;
13388 }
13389
13390 RefPtr<ContentFrameMessageManager> manager =
13391 frameLoader->GetBrowserChildMessageManager();
13392 return manager.forget();
13393}
13394
13395/* static */
13396Document* nsContentUtils::TryGetDocumentFromWindowGlobal(nsISupports* aFrom) {
13397 nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aFrom);
13398 MOZ_DIAGNOSTIC_ASSERT(window, "Expected a window global")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(window)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(window))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("window" " (" "Expected a window global"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13398
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "window"
") (" "Expected a window global" ")"); do { MOZ_CrashSequence
(__null, 13398); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13399 if (!window) {
13400 return nullptr;
13401 }
13402 return window->GetExtantDoc();
13403}
13404
13405/* static */
13406uint32_t nsContentUtils::InnerOrOuterWindowCreated() {
13407 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13407); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 13407); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13408 ++sInnerOrOuterWindowCount;
13409 return ++sInnerOrOuterWindowSerialCounter;
13410}
13411
13412/* static */
13413void nsContentUtils::InnerOrOuterWindowDestroyed() {
13414 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13414); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 13414); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13415 MOZ_ASSERT(sInnerOrOuterWindowCount > 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(sInnerOrOuterWindowCount > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(sInnerOrOuterWindowCount >
0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("sInnerOrOuterWindowCount > 0", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13415); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sInnerOrOuterWindowCount > 0"
")"); do { MOZ_CrashSequence(__null, 13415); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13416 --sInnerOrOuterWindowCount;
13417}
13418
13419static bool JSONCreator(const char16_t* aBuf, uint32_t aLen, void* aData) {
13420 nsAString* result = static_cast<nsAString*>(aData);
13421 return result->Append(aBuf, aLen, fallible);
13422}
13423
13424/* static */
13425bool nsContentUtils::StringifyJSON(JSContext* aCx, JS::Handle<JS::Value> aValue,
13426 nsAString& aOutStr, JSONBehavior aBehavior) {
13427 MOZ_ASSERT(aCx)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aCx)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aCx))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aCx", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13427); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aCx" ")");
do { MOZ_CrashSequence(__null, 13427); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13428 switch (aBehavior) {
13429 case UndefinedIsNullStringLiteral: {
13430 aOutStr.Truncate();
13431 JS::Rooted<JS::Value> value(aCx, aValue);
13432 return JS_Stringify(aCx, &value, nullptr, JS::NullHandleValue,
13433 JSONCreator, &aOutStr);
13434 }
13435 case UndefinedIsVoidString: {
13436 aOutStr.SetIsVoid(true);
13437 return JS::ToJSON(aCx, aValue, nullptr, JS::NullHandleValue, JSONCreator,
13438 &aOutStr);
13439 }
13440 default:
13441 MOZ_ASSERT_UNREACHABLE("Invalid value for aBehavior")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: "
"Invalid value for aBehavior" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13441); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Invalid value for aBehavior" ")"
); do { MOZ_CrashSequence(__null, 13441); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13442 return false;
13443 }
13444}
13445
13446/* static */
13447bool nsContentUtils::
13448 HighPriorityEventPendingForTopLevelDocumentBeforeContentfulPaint(
13449 Document* aDocument) {
13450 MOZ_ASSERT(XRE_IsContentProcess(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsContentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsContentProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsContentProcess()"
" (" "This function only makes sense in content processes" ")"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13451); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "XRE_IsContentProcess()" ") (" "This function only makes sense in content processes"
")"); do { MOZ_CrashSequence(__null, 13451); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13451 "This function only makes sense in content processes")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsContentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsContentProcess()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsContentProcess()"
" (" "This function only makes sense in content processes" ")"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13451); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "XRE_IsContentProcess()" ") (" "This function only makes sense in content processes"
")"); do { MOZ_CrashSequence(__null, 13451); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13452
13453 if (aDocument && !aDocument->IsLoadedAsData()) {
13454 if (nsPresContext* presContext = FindPresContextForDocument(aDocument)) {
13455 MOZ_ASSERT(!presContext->IsChrome(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!presContext->IsChrome())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!presContext->IsChrome())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!presContext->IsChrome()"
" (" "Should never have a chrome PresContext in a content process"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13456
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!presContext->IsChrome()"
") (" "Should never have a chrome PresContext in a content process"
")"); do { MOZ_CrashSequence(__null, 13456); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13456 "Should never have a chrome PresContext in a content process")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!presContext->IsChrome())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!presContext->IsChrome())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!presContext->IsChrome()"
" (" "Should never have a chrome PresContext in a content process"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13456
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!presContext->IsChrome()"
") (" "Should never have a chrome PresContext in a content process"
")"); do { MOZ_CrashSequence(__null, 13456); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13457
13458 return !presContext->GetInProcessRootContentDocumentPresContext()
13459 ->HadFirstContentfulPaint() &&
13460 nsThreadManager::MainThreadHasPendingHighPriorityEvents();
13461 }
13462 }
13463 return false;
13464}
13465
13466static nsGlobalWindowInner* GetInnerWindowForGlobal(nsIGlobalObject* aGlobal) {
13467 NS_ENSURE_TRUE(aGlobal, nullptr)do { if ((__builtin_expect(!!(!(aGlobal)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aGlobal" ") failed", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13467); return
nullptr; } } while (false)
;
13468
13469 if (auto* window = aGlobal->GetAsInnerWindow()) {
13470 return nsGlobalWindowInner::Cast(window);
13471 }
13472
13473 // When Extensions run content scripts inside a sandbox, it uses
13474 // sandboxPrototype to make them appear as though they're running in the
13475 // scope of the page. So when a content script invokes postMessage, it expects
13476 // the |source| of the received message to be the window set as the
13477 // sandboxPrototype. This used to work incidentally for unrelated reasons, but
13478 // now we need to do some special handling to support it.
13479 JS::Rooted<JSObject*> scope(RootingCx(), aGlobal->GetGlobalJSObject());
13480 NS_ENSURE_TRUE(scope, nullptr)do { if ((__builtin_expect(!!(!(scope)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "scope" ") failed", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13480); return
nullptr; } } while (false)
;
13481
13482 if (xpc::IsSandbox(scope)) {
13483 AutoJSAPI jsapi;
13484 MOZ_ALWAYS_TRUE(jsapi.Init(scope))do { if ((__builtin_expect(!!(jsapi.Init(scope)), 1))) { } else
{ do { do { } while (false); MOZ_ReportCrash("" "jsapi.Init(scope)"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13484); AnnotateMozCrashReason
("MOZ_CRASH(" "jsapi.Init(scope)" ")"); do { MOZ_CrashSequence
(__null, 13484); __attribute__((nomerge)) ::abort(); } while (
false); } while (false); } } while (false)
;
13485 JSContext* cx = jsapi.cx();
13486 // Our current Realm on aCx is the sandbox. Using that for unwrapping
13487 // makes sense: if the sandbox can unwrap the window, we can use it.
13488 return xpc::SandboxWindowOrNull(scope, cx);
13489 }
13490
13491 // The calling window must be holding a reference, so we can return a weak
13492 // pointer.
13493 return nsGlobalWindowInner::Cast(aGlobal->GetAsInnerWindow());
13494}
13495
13496/* static */
13497nsGlobalWindowInner* nsContentUtils::IncumbentInnerWindow() {
13498 return GetInnerWindowForGlobal(GetIncumbentGlobal());
13499}
13500
13501/* static */
13502nsGlobalWindowInner* nsContentUtils::EntryInnerWindow() {
13503 return GetInnerWindowForGlobal(GetEntryGlobal());
13504}
13505
13506/* static */
13507bool nsContentUtils::IsURIInPrefList(nsIURI* aURI, const char* aPrefName) {
13508 MOZ_ASSERT(aPrefName)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPrefName)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPrefName))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aPrefName", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13508); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrefName"
")"); do { MOZ_CrashSequence(__null, 13508); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13509
13510 nsAutoCString list;
13511 Preferences::GetCString(aPrefName, list);
13512 ToLowerCase(list);
13513 return IsURIInList(aURI, list);
13514}
13515
13516/* static */
13517bool nsContentUtils::IsURIInList(nsIURI* aURI, const nsCString& aList) {
13518#ifdef DEBUG1
13519 nsAutoCString listLowerCase(aList);
13520 ToLowerCase(listLowerCase);
13521 MOZ_ASSERT(listLowerCase.Equals(aList),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(listLowerCase.Equals(aList))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(listLowerCase.Equals(aList))
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("listLowerCase.Equals(aList)"
" (" "The aList argument should be lower-case" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listLowerCase.Equals(aList)"
") (" "The aList argument should be lower-case" ")"); do { MOZ_CrashSequence
(__null, 13522); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
13522 "The aList argument should be lower-case")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(listLowerCase.Equals(aList))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(listLowerCase.Equals(aList))
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("listLowerCase.Equals(aList)"
" (" "The aList argument should be lower-case" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listLowerCase.Equals(aList)"
") (" "The aList argument should be lower-case" ")"); do { MOZ_CrashSequence
(__null, 13522); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13523#endif
13524
13525 if (!aURI) {
13526 return false;
13527 }
13528
13529 if (aList.IsEmpty()) {
13530 return false;
13531 }
13532
13533 nsAutoCString scheme;
13534 aURI->GetScheme(scheme);
13535 if (!scheme.EqualsLiteral("http") && !scheme.EqualsLiteral("https")) {
13536 return false;
13537 }
13538
13539 // The list is comma separated domain list. Each item may start with "*.".
13540 // If starts with "*.", it matches any sub-domains.
13541
13542 nsCCharSeparatedTokenizer tokenizer(aList, ',');
13543 while (tokenizer.hasMoreTokens()) {
13544 const nsCString token(tokenizer.nextToken());
13545
13546 nsAutoCString host;
13547 aURI->GetHost(host);
13548 if (host.IsEmpty()) {
13549 return false;
13550 }
13551 ToLowerCase(host);
13552
13553 for (;;) {
13554 int32_t index = token.Find(host);
13555 if (index >= 0 &&
13556 static_cast<uint32_t>(index) + host.Length() <= token.Length()) {
13557 // If we found a full match, return true.
13558 size_t indexAfterHost = index + host.Length();
13559 if (index == 0 && indexAfterHost == token.Length()) {
13560 return true;
13561 }
13562 // If next character is '/', we need to check the path too.
13563 // We assume the path in the list means "/foo" + "*".
13564 if (token[indexAfterHost] == '/') {
13565 nsDependentCSubstring pathInList(
13566 token, indexAfterHost,
13567 static_cast<nsDependentCSubstring::size_type>(-1));
13568 nsAutoCString filePath;
13569 aURI->GetFilePath(filePath);
13570 ToLowerCase(filePath);
13571 if (StringBeginsWith(filePath, pathInList) &&
13572 (filePath.Length() == pathInList.Length() ||
13573 pathInList.EqualsLiteral("/") ||
13574 filePath[pathInList.Length() - 1] == '/' ||
13575 filePath[pathInList.Length() - 1] == '?' ||
13576 filePath[pathInList.Length() - 1] == '#')) {
13577 return true;
13578 }
13579 }
13580 }
13581 int32_t startIndexOfCurrentLevel = host[0] == '*' ? 1 : 0;
13582 int32_t startIndexOfNextLevel =
13583 host.Find(".", startIndexOfCurrentLevel + 1);
13584 if (startIndexOfNextLevel <= 0) {
13585 break;
13586 }
13587 host.ReplaceLiteral(0, startIndexOfNextLevel, "*");
13588 }
13589 }
13590
13591 return false;
13592}
13593
13594/* static */
13595LayoutDeviceIntMargin nsContentUtils::GetWindowSafeAreaInsets(
13596 nsIScreen* aScreen, const LayoutDeviceIntMargin& aSafeAreaInsets,
13597 const LayoutDeviceIntRect& aWindowRect) {
13598 // This calculates safe area insets of window from screen rectangle, window
13599 // rectangle and safe area insets of screen.
13600 //
13601 // +----------------------------------------+ <-- screen
13602 // | +-------------------------------+ <------- window
13603 // | | window's safe area inset top) | |
13604 // +--+-------------------------------+--+ |
13605 // | | | |<------ safe area rectangle of
13606 // | | | | | screen
13607 // +--+-------------------------------+--+ |
13608 // | |window's safe area inset bottom| |
13609 // | +-------------------------------+ |
13610 // +----------------------------------------+
13611 //
13612 LayoutDeviceIntMargin windowSafeAreaInsets;
13613 if (windowSafeAreaInsets == aSafeAreaInsets) {
13614 // no safe area insets.
13615 return windowSafeAreaInsets;
13616 }
13617
13618 const LayoutDeviceIntRect screenRect = aScreen->GetRect();
13619 LayoutDeviceIntRect safeAreaRect = screenRect;
13620 safeAreaRect.Deflate(aSafeAreaInsets);
13621
13622 // FIXME(bug 1754323): This can trigger because the screen rect is not
13623 // orientation-aware.
13624 // MOZ_ASSERT(screenRect.Contains(windowRect),
13625 // "Screen doesn't contain window rect? Something seems off");
13626
13627 // window's rect of safe area
13628 safeAreaRect = safeAreaRect.Intersect(aWindowRect);
13629
13630 windowSafeAreaInsets.top = safeAreaRect.y - aWindowRect.y;
13631 windowSafeAreaInsets.left = safeAreaRect.x - aWindowRect.x;
13632 windowSafeAreaInsets.right =
13633 aWindowRect.x + aWindowRect.width - (safeAreaRect.x + safeAreaRect.width);
13634 windowSafeAreaInsets.bottom = aWindowRect.y + aWindowRect.height -
13635 (safeAreaRect.y + safeAreaRect.height);
13636
13637 windowSafeAreaInsets.EnsureAtLeast(LayoutDeviceIntMargin());
13638 // This shouldn't be needed, but it wallpapers orientation issues, see bug
13639 // 1754323.
13640 windowSafeAreaInsets.EnsureAtMost(aSafeAreaInsets);
13641
13642 return windowSafeAreaInsets;
13643}
13644
13645/* static */
13646nsContentUtils::SubresourceCacheValidationInfo
13647nsContentUtils::GetSubresourceCacheValidationInfo(nsIRequest* aRequest,
13648 nsIURI* aURI) {
13649 SubresourceCacheValidationInfo info;
13650 if (nsCOMPtr<nsICacheInfoChannel> cache = do_QueryInterface(aRequest)) {
13651 uint32_t value = 0;
13652 if (NS_SUCCEEDED(cache->GetCacheTokenExpirationTime(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cache->GetCacheTokenExpirationTime
(&value))), 1)))
) {
13653 // NOTE: If the cache doesn't expire, the value should be
13654 // nsICacheEntry::NO_EXPIRATION_TIME.
13655 info.mExpirationTime.emplace(CacheExpirationTime::ExpireAt(value));
13656 }
13657 }
13658
13659 // Determine whether the cache entry must be revalidated when we try to use
13660 // it. Currently, only HTTP specifies this information...
13661 if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest)) {
13662 (void)httpChannel->IsNoStoreResponse(&info.mMustRevalidate);
13663
13664 if (!info.mMustRevalidate) {
13665 (void)httpChannel->IsNoCacheResponse(&info.mMustRevalidate);
13666 }
13667
13668 if (!info.mMustRevalidate) {
13669 nsAutoCString vary;
13670 (void)httpChannel->GetResponseHeader("vary"_ns, vary);
13671 info.mMustRevalidate = [&] {
13672 for (const nsACString& token :
13673 nsCCharSeparatedTokenizer(vary, ',').ToRange()) {
13674 if (token.EqualsLiteral("*")) {
13675 return true;
13676 }
13677 if (token.EqualsIgnoreCase("cookie")) {
13678 return true;
13679 }
13680 }
13681 return false;
13682 }();
13683 }
13684 }
13685
13686 // data: URIs are safe to cache across documents under any circumstance, so we
13687 // special-case them here even though the channel itself doesn't have any
13688 // caching policy. Same for chrome:// uris.
13689 //
13690 // TODO(emilio): Figure out which other schemes that don't have caching
13691 // policies are safe to cache. Blobs should be...
13692 const bool knownCacheable = [&] {
13693 if (!aURI) {
13694 return false;
13695 }
13696 if (aURI->SchemeIs("data") || aURI->SchemeIs("moz-page-thumb") ||
13697 aURI->SchemeIs("moz-newtab-wallpaper") ||
13698 aURI->SchemeIs("moz-extension")) {
13699 return true;
13700 }
13701 if (aURI->SchemeIs("chrome") || aURI->SchemeIs("resource")) {
13702 return !StaticPrefs::nglayout_debug_disable_xul_cache();
13703 }
13704 return false;
13705 }();
13706
13707 if (knownCacheable) {
13708 MOZ_ASSERT(!info.mExpirationTime)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!info.mExpirationTime)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!info.mExpirationTime))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!info.mExpirationTime"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13708); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!info.mExpirationTime" ")"); do { MOZ_CrashSequence
(__null, 13708); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13709 MOZ_ASSERT(!info.mMustRevalidate)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!info.mMustRevalidate)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!info.mMustRevalidate))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!info.mMustRevalidate"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13709); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!info.mMustRevalidate" ")"); do { MOZ_CrashSequence
(__null, 13709); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13710 info.mExpirationTime = Some(CacheExpirationTime::Never());
13711 }
13712
13713 return info;
13714}
13715
13716CacheExpirationTime nsContentUtils::GetSubresourceCacheExpirationTime(
13717 nsIRequest* aRequest, nsIURI* aURI) {
13718 auto info = GetSubresourceCacheValidationInfo(aRequest, aURI);
13719
13720 // For now, we never cache entries that we have to revalidate, or whose
13721 // channel don't support caching.
13722 if (info.mMustRevalidate || !info.mExpirationTime) {
13723 return CacheExpirationTime::AlreadyExpired();
13724 }
13725 return *info.mExpirationTime;
13726}
13727
13728/* static */
13729bool nsContentUtils::ShouldBypassSubResourceCache(Document* aDoc) {
13730 RefPtr<nsILoadGroup> lg = aDoc->GetDocumentLoadGroup();
13731 if (!lg) {
13732 return false;
13733 }
13734 nsLoadFlags flags;
13735 if (NS_FAILED(lg->GetLoadFlags(&flags))((bool)(__builtin_expect(!!(NS_FAILED_impl(lg->GetLoadFlags
(&flags))), 0)))
) {
13736 return false;
13737 }
13738 return flags & (nsIRequest::LOAD_BYPASS_CACHE |
13739 nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE);
13740}
13741
13742nsCString nsContentUtils::TruncatedURLForDisplay(nsIURI* aURL, size_t aMaxLen) {
13743 nsCString spec;
13744 if (aURL) {
13745 aURL->GetSpec(spec);
13746 spec.Truncate(std::min(aMaxLen, spec.Length()));
13747 }
13748 return spec;
13749}
13750
13751/* static */
13752nsresult nsContentUtils::AnonymizeId(nsAString& aId,
13753 const nsACString& aOriginKey,
13754 OriginFormat aFormat) {
13755 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13755); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 13755); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13756
13757 nsresult rv;
13758 nsCString rawKey;
13759 if (aFormat == OriginFormat::Base64) {
13760 rv = Base64Decode(aOriginKey, rawKey);
13761 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13761); return rv; } } while (false)
;
13762 } else {
13763 rawKey = aOriginKey;
13764 }
13765
13766 HMAC hmac;
13767 rv = hmac.Begin(
13768 SEC_OID_SHA256,
13769 Span(reinterpret_cast<const uint8_t*>(rawKey.get()), rawKey.Length()));
13770 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13770); return rv; } } while (false)
;
13771
13772 NS_ConvertUTF16toUTF8 id(aId);
13773 rv = hmac.Update(reinterpret_cast<const uint8_t*>(id.get()), id.Length());
13774 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13774); return rv; } } while (false)
;
13775
13776 nsTArray<uint8_t> macBytes;
13777 rv = hmac.End(macBytes);
13778 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13778); return rv; } } while (false)
;
13779
13780 nsCString macBase64;
13781 rv = Base64Encode(
13782 nsDependentCSubstring(reinterpret_cast<const char*>(macBytes.Elements()),
13783 macBytes.Length()),
13784 macBase64);
13785 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13785); return rv; } } while (false)
;
13786
13787 CopyUTF8toUTF16(macBase64, aId);
13788 return NS_OK;
13789}
13790
13791void nsContentUtils::RequestGeckoTaskBurst() {
13792 nsCOMPtr<nsIAppShell> appShell = do_GetService(NS_APPSHELL_CID{0x2d96b3df, 0xc051, 0x11d1, {0xa8, 0x27, 0x00, 0x40, 0x95, 0x9a
, 0x28, 0xc9}}
);
13793 if (appShell) {
13794 appShell->GeckoTaskBurst();
13795 }
13796}
13797
13798nsIContent* nsContentUtils::GetClosestLinkInFlatTree(nsIContent* aContent) {
13799 for (nsIContent* content = aContent; content;
13800 content = content->GetFlattenedTreeParent()) {
13801 if (nsContentUtils::IsDraggableLink(content)) {
13802 return content;
13803 }
13804 }
13805 return nullptr;
13806}
13807
13808template <TreeKind aKind>
13809MOZ_ALWAYS_INLINEinline const nsINode* GetParent(const nsINode* aNode) {
13810 if constexpr (aKind == TreeKind::DOM) {
13811 return aNode->GetParentNode();
13812 } else if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
13813 return aNode->GetParentOrShadowHostNode();
13814 } else if constexpr (aKind == TreeKind::FlatForSelection) {
13815 return aNode->GetFlattenedTreeParentNodeForSelection();
13816 } else if constexpr (aKind == TreeKind::Flat) {
13817 return aNode->GetFlattenedTreeParentNode();
13818 } else {
13819 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Handle the new TreeKind value")do { 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: "
"Handle the new TreeKind value" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13819); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Handle the new TreeKind value" ")"
); do { MOZ_CrashSequence(__null, 13819); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); __builtin_unreachable
(); } while (false)
;
13820 }
13821}
13822
13823template <TreeKind aKind>
13824Maybe<int32_t> nsContentUtils::GetIndexInParent(
13825 const nsINode* aParent, const nsIContent* aPossibleChild) {
13826 const Maybe<uint32_t> idx = [&]() {
13827 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
13828 return aParent->ComputeIndexOf(aPossibleChild);
13829 } else {
13830 return aParent->ComputeIndexOf<aKind>(aPossibleChild);
13831 }
13832 }();
13833 if (idx) {
13834 return idx.map([](auto i) { return AssertedCast<int32_t>(i); });
13835 }
13836
13837 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
13838 if (const auto* sr = ShadowRoot::FromNode(aPossibleChild)) {
13839 return sr->GetHost() == aParent ? Some(-1) : Nothing();
13840 }
13841 }
13842
13843 // Handle pseudo-element and anonymous node ordering:
13844 // ::backdrop -> ::marker -> ::checkmark -> ::before -> regular siblings ->
13845 // all other NAC -> ::after -> ::picker-icon
13846 // This matches the order of AllChildrenIterator.
13847 if (NS_WARN_IF(!aPossibleChild->IsRootOfNativeAnonymousSubtree())NS_warn_if_impl(!aPossibleChild->IsRootOfNativeAnonymousSubtree
(), "!aPossibleChild->IsRootOfNativeAnonymousSubtree()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13847)
) {
13848 // If aNode is mid unbind, we can reach this.
13849 return Nothing();
13850 }
13851
13852 if (NS_WARN_IF(aPossibleChild->GetParentNode() != aParent)NS_warn_if_impl(aPossibleChild->GetParentNode() != aParent
, "aPossibleChild->GetParentNode() != aParent", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13852)
) {
13853 // We can't be an anon child if not correctly parented.
13854 return Nothing();
13855 }
13856
13857 if (aPossibleChild->IsGeneratedContentContainerForBackdrop()) {
13858 return Some(-5);
13859 }
13860
13861 if (aPossibleChild->IsGeneratedContentContainerForMarker()) {
13862 return Some(-4);
13863 }
13864
13865 if (aPossibleChild->IsGeneratedContentContainerForCheckmark()) {
13866 return Some(-3);
13867 }
13868
13869 if (aPossibleChild->IsGeneratedContentContainerForBefore()) {
13870 return Some(-2);
13871 }
13872
13873 AutoTArray<nsIContent*, 8> anonKids;
13874
13875 // Regular children are indexed via ComputeIndexOf (range [0, GetChildCount))
13876 // for both DOM and ShadowIncludingDOM above; only the flat tree indexes them
13877 // via the flattened iterator. Trailing NAC must be based at the matching
13878 // count so it lands after the regular children in the same index space.
13879 const int32_t siblingCount = [&]() -> uint32_t {
13880 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
13881 return aParent->GetChildCount();
13882 } else {
13883 return aParent->GetChildCount<aKind>();
13884 }
13885 }();
13886
13887 MOZ_ASSERT(aParent->MayHaveAnonymousChildren())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParent->MayHaveAnonymousChildren())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aParent->MayHaveAnonymousChildren()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aParent->MayHaveAnonymousChildren()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13887); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aParent->MayHaveAnonymousChildren()" ")"
); do { MOZ_CrashSequence(__null, 13887); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13888 MOZ_ASSERT(aParent->IsContent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aParent->IsContent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aParent->IsContent()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aParent->IsContent()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13888); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aParent->IsContent()" ")"); do { MOZ_CrashSequence
(__null, 13888); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13889 nsContentUtils::AppendNativeAnonymousChildren(aParent->AsContent(), anonKids,
13890 nsIContent::eAllChildren);
13891
13892 if (aPossibleChild->IsGeneratedContentContainerForAfter()) {
13893 return Some(int32_t(siblingCount + anonKids.Length()));
13894 }
13895
13896 if (aPossibleChild->IsGeneratedContentContainerForPickerIcon()) {
13897 return Some(int32_t(siblingCount + anonKids.Length()) + 1);
13898 }
13899
13900 auto index = anonKids.IndexOf(aPossibleChild);
13901 if (index == decltype(anonKids)::NoIndex) {
13902 MOZ_ASSERT_UNREACHABLE(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: "
"Missing parent -> child link somehow?" "Potentially unstable ordering"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13904
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
"Missing parent -> child link somehow?" "Potentially unstable ordering"
")"); do { MOZ_CrashSequence(__null, 13904); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13903 "Missing parent -> child link somehow?"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: "
"Missing parent -> child link somehow?" "Potentially unstable ordering"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13904
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
"Missing parent -> child link somehow?" "Potentially unstable ordering"
")"); do { MOZ_CrashSequence(__null, 13904); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13904 "Potentially unstable ordering")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: "
"Missing parent -> child link somehow?" "Potentially unstable ordering"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13904
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
"Missing parent -> child link somehow?" "Potentially unstable ordering"
")"); do { MOZ_CrashSequence(__null, 13904); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13905 return Nothing();
13906 }
13907 return Some(siblingCount + int32_t(index));
13908}
13909
13910template <TreeKind aTreeKind>
13911int32_t nsContentUtils::CompareTreePosition(const nsINode* aNode1,
13912 const nsINode* aNode2,
13913 const nsINode* aCommonAncestor,
13914 NodeIndexCache* aCache) {
13915 MOZ_ASSERT(aNode1, "aNode1 must not be null")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNode1)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aNode1))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aNode1" " (" "aNode1 must not be null"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13915
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ") (" "aNode1 must not be null"
")"); do { MOZ_CrashSequence(__null, 13915); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13916 MOZ_ASSERT(aNode2, "aNode2 must not be null")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aNode2)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(aNode2))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aNode2" " (" "aNode2 must not be null"
")", "/root/firefox-clang/dom/base/nsContentUtils.cpp", 13916
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ") (" "aNode2 must not be null"
")"); do { MOZ_CrashSequence(__null, 13916); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13917
13918 if (NS_WARN_IF(aNode1 == aNode2)NS_warn_if_impl(aNode1 == aNode2, "aNode1 == aNode2", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13918)
) {
13919 return 0;
13920 }
13921
13922 // TODO: Maybe handle flat tree too or other common cases?
13923 if constexpr (aTreeKind == TreeKind::DOM ||
13924 aTreeKind == TreeKind::ShadowIncludingDOM) {
13925 if (aNode1->GetNextSibling() == aNode2) {
13926 return -1;
13927 }
13928 if (aNode1->GetPreviousSibling() == aNode2) {
13929 return 1;
13930 }
13931 }
13932
13933 AutoTArray<const nsINode*, 32> node1Ancestors;
13934 const nsINode* c1;
13935 for (c1 = aNode1; c1 && c1 != aCommonAncestor;
13936 c1 = GetParent<aTreeKind>(c1)) {
13937 node1Ancestors.AppendElement(c1);
13938 }
13939 if (!c1 && aCommonAncestor) {
13940 // So, it turns out aCommonAncestor was not an ancestor of c1. Oops.
13941 // Never mind. We can continue as if aCommonAncestor was null.
13942 aCommonAncestor = nullptr;
13943 }
13944
13945 AutoTArray<const nsINode*, 32> node2Ancestors;
13946 const nsINode* c2;
13947 for (c2 = aNode2; c2 && c2 != aCommonAncestor;
13948 c2 = GetParent<aTreeKind>(c2)) {
13949 node2Ancestors.AppendElement(c2);
13950 }
13951 if (!c2 && aCommonAncestor) {
13952 // So, it turns out aCommonAncestor was not an ancestor of c2.
13953 // We need to retry with no common ancestor hint.
13954 return CompareTreePosition<aTreeKind>(aNode1, aNode2, nullptr, aCache);
13955 }
13956
13957 // FIXME: Looks like that some of this can be rewritten with CommonAncestors.
13958 int last1 = node1Ancestors.Length() - 1;
13959 int last2 = node2Ancestors.Length() - 1;
13960 const nsINode* node1Ancestor = nullptr;
13961 const nsINode* node2Ancestor = nullptr;
13962 while (last1 >= 0 && last2 >= 0 &&
13963 ((node1Ancestor = node1Ancestors.ElementAt(last1)) ==
13964 (node2Ancestor = node2Ancestors.ElementAt(last2)))) {
13965 last1--;
13966 last2--;
13967 }
13968
13969 if (last1 < 0) {
13970 if (last2 < 0) {
13971 NS_ASSERTION(aNode1 == aNode2, "internal error?")do { if (!(aNode1 == aNode2)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "internal error?", "aNode1 == aNode2", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13971); MOZ_PretendNoReturn(); } } while (0)
;
13972 return 0;
13973 }
13974 // aContent1 is an ancestor of aContent2
13975 return -1;
13976 }
13977
13978 if (last2 < 0) {
13979 // aContent2 is an ancestor of aContent1
13980 return 1;
13981 }
13982 // node1Ancestor != node2Ancestor, so they must be siblings with the
13983 // same parent
13984 const nsINode* parent = GetParent<aTreeKind>(node1Ancestor);
13985 if (NS_WARN_IF(!parent)NS_warn_if_impl(!parent, "!parent", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13985)
) { // different documents??
13986 return 0;
13987 }
13988 MOZ_ASSERT(node1Ancestor)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node1Ancestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(node1Ancestor))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("node1Ancestor",
"/root/firefox-clang/dom/base/nsContentUtils.cpp", 13988); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "node1Ancestor" ")"); do { MOZ_CrashSequence
(__null, 13988); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13989 MOZ_ASSERT(node2Ancestor)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node2Ancestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(node2Ancestor))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("node2Ancestor",
"/root/firefox-clang/dom/base/nsContentUtils.cpp", 13989); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "node2Ancestor" ")"); do { MOZ_CrashSequence
(__null, 13989); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13990 Maybe<int32_t> index1;
13991 Maybe<int32_t> index2;
13992 // node1Ancestor and node2Ancestor must be children of parent so that they
13993 // must be content nodes if we can get the indices.
13994 MOZ_DIAGNOSTIC_ASSERT(node1Ancestor->IsContent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node1Ancestor->IsContent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(node1Ancestor->IsContent(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("node1Ancestor->IsContent()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13994); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "node1Ancestor->IsContent()"
")"); do { MOZ_CrashSequence(__null, 13994); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13995 MOZ_DIAGNOSTIC_ASSERT(node2Ancestor->IsContent())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(node2Ancestor->IsContent())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(node2Ancestor->IsContent(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("node2Ancestor->IsContent()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13995); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "node2Ancestor->IsContent()"
")"); do { MOZ_CrashSequence(__null, 13995); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13996 if (aCache) {
13997 aCache->ComputeIndicesOf<aTreeKind>(parent, node1Ancestor->AsContent(),
13998 node2Ancestor->AsContent(), index1,
13999 index2);
14000 } else {
14001 index1 = GetIndexInParent<aTreeKind>(parent, node1Ancestor->AsContent());
14002 index2 = GetIndexInParent<aTreeKind>(parent, node2Ancestor->AsContent());
14003 }
14004 if (NS_WARN_IF(index1.isNothing())NS_warn_if_impl(index1.isNothing(), "index1.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 14004)
|| NS_WARN_IF(index2.isNothing())NS_warn_if_impl(index2.isNothing(), "index2.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 14004)
) {
14005 // This should generally never happen, but can happen mid-unbind or in other
14006 // edge cases, deal with it somewhat reasonably.
14007 return 0;
14008 }
14009 return static_cast<int32_t>(static_cast<int64_t>(*index1) - *index2);
14010}
14011
14012nsIContent* nsContentUtils::AttachDeclarativeShadowRoot(
14013 nsIContent* aHost, ShadowRootMode aMode, bool aIsClonable,
14014 bool aIsSerializable, bool aDelegatesFocus, bool aCustomElementRegistry,
14015 SlotAssignmentMode aSlotAssignment, const nsAString& aReferenceTarget) {
14016 RefPtr<Element> host = mozilla::dom::Element::FromNodeOrNull(aHost);
14017 if (!host || host->GetShadowRoot()) {
14018 // https://html.spec.whatwg.org/#parsing-main-inhead:shadow-host
14019 return nullptr;
14020 }
14021
14022 ShadowRootInit init;
14023 init.mMode = aMode;
14024 init.mDelegatesFocus = aDelegatesFocus;
14025 init.mSlotAssignment = aSlotAssignment;
14026 init.mClonable = aIsClonable;
14027 init.mSerializable = aIsSerializable;
14028 // https://html.spec.whatwg.org/#current-template-insertion-mode
14029 // "Let registry be null if templateStartTag has a
14030 // shadowrootcustomelementregistry attribute; otherwise
14031 // declarativeShadowHostElement's node document's custom element registry."
14032 if (StaticPrefs::dom_scoped_custom_element_registries_enabled()) {
14033 if (aCustomElementRegistry) {
14034 init.mCustomElementRegistry.Construct(nullptr);
14035 } else {
14036 init.mCustomElementRegistry.Construct(
14037 host->OwnerDoc()->GetCustomElementRegistry());
14038 }
14039 }
14040
14041 RefPtr shadowRoot = host->AttachShadow(init, IgnoreErrors());
14042 if (shadowRoot) {
14043 shadowRoot->SetIsDeclarative(
14044 nsGenericHTMLFormControlElement::ShadowRootDeclarative::Yes);
14045 // https://html.spec.whatwg.org/#parsing-main-inhead
14046 // 7. If templateStartTag has a shadowrootcustomelementregistry attribute,
14047 // set shadow's keep custom element registry null to true.
14048 if (StaticPrefs::dom_scoped_custom_element_registries_enabled() &&
14049 aCustomElementRegistry) {
14050 shadowRoot->SetKeepCustomElementRegistryNull();
14051 }
14052 // https://html.spec.whatwg.org/#parsing-main-inhead:available-to-element-internals
14053 shadowRoot->SetAvailableToElementInternals();
14054 shadowRoot->SetReferenceTarget(aReferenceTarget);
14055 }
14056 return shadowRoot;
14057}
14058
14059// https://html.spec.whatwg.org/#the-navigation-must-be-a-replace
14060/* static */ bool nsContentUtils::NavigationMustBeAReplace(
14061 nsIURI& aURI, const Document& aDocument) {
14062 // The navigation must be a replace, given a URL url and a Document document,
14063 // if any of the following are true:
14064 // - url's scheme is "javascript"; or
14065 // - document's is initial about:blank is true.
14066 return aURI.SchemeIs("javascript") ||
14067 (NS_IsAboutBlank(aDocument.GetDocumentURI()) &&
14068 aDocument.IsInitialDocument());
14069}
14070
14071template int32_t nsContentUtils::CompareTreePosition<TreeKind::DOM>(
14072 const nsINode*, const nsINode*, const nsINode*, NodeIndexCache*);
14073template int32_t
14074nsContentUtils::CompareTreePosition<TreeKind::ShadowIncludingDOM>(
14075 const nsINode*, const nsINode*, const nsINode*, NodeIndexCache*);
14076template int32_t
14077nsContentUtils::CompareTreePosition<TreeKind::FlatForSelection>(
14078 const nsINode*, const nsINode*, const nsINode*, NodeIndexCache*);
14079template int32_t nsContentUtils::CompareTreePosition<TreeKind::Flat>(
14080 const nsINode*, const nsINode*, const nsINode*, NodeIndexCache*);

←

/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/ScopeExit.h

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/* RAII class for executing arbitrary actions at scope end. */
6
7#ifndef mozilla_ScopeExit_h
8#define mozilla_ScopeExit_h
9
10/*
11 * See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4189.pdf for a
12 * standards-track version of this.
13 *
14 * Error handling can be complex when various actions need to be performed that
15 * need to be undone if an error occurs midway. This can be handled with a
16 * collection of boolean state variables and gotos, which can get clunky and
17 * error-prone:
18 *
19 * {
20 * if (!a.setup())
21 * goto fail;
22 * isASetup = true;
23 *
24 * if (!b.setup())
25 * goto fail;
26 * isBSetup = true;
27 *
28 * ...
29 * return true;
30 *
31 * fail:
32 * if (isASetup)
33 * a.teardown();
34 * if (isBSetup)
35 * b.teardown();
36 * return false;
37 * }
38 *
39 * ScopeExit is a mechanism to simplify this pattern by keeping an RAII guard
40 * class that will perform the teardown on destruction, unless released. So the
41 * above would become:
42 *
43 * {
44 * if (!a.setup()) {
45 * return false;
46 * }
47 * auto guardA = MakeScopeExit([&] {
48 * a.teardown();
49 * });
50 *
51 * if (!b.setup()) {
52 * return false;
53 * }
54 * auto guardB = MakeScopeExit([&] {
55 * b.teardown();
56 * });
57 *
58 * ...
59 * guardA.release();
60 * guardB.release();
61 * return true;
62 * }
63 *
64 * This header provides:
65 *
66 * - |ScopeExit| - a container for a cleanup call, automically called at the
67 * end of the scope;
68 * - |MakeScopeExit| - a convenience function for constructing a |ScopeExit|
69 * with a given cleanup routine, commonly used with a lambda function.
70 *
71 * Note that the RAII classes defined in this header do _not_ perform any form
72 * of reference-counting or garbage-collection. These classes have exactly two
73 * behaviors:
74 *
75 * - if |release()| has not been called, the cleanup is always performed at
76 * the end of the scope;
77 * - if |release()| has been called, nothing will happen at the end of the
78 * scope.
79 */
80
81#include <utility>
82
83#include "mozilla/Attributes.h"
84
85namespace mozilla {
86
87template <typename ExitFunction>
88class MOZ_STACK_CLASS ScopeExit {
89 ExitFunction mExitFunction;
90 bool mExecuteOnDestruction;
91
92 public:
93 explicit ScopeExit(ExitFunction&& cleanup)
94 : mExitFunction(std::move(cleanup)), mExecuteOnDestruction(true) {}
95
96 ScopeExit(ScopeExit&& rhs)
97 : mExitFunction(std::move(rhs.mExitFunction)),
98 mExecuteOnDestruction(rhs.mExecuteOnDestruction) {
99 rhs.release();
100 }
101
102 ~ScopeExit() {
103 if (mExecuteOnDestruction) {
104 mExitFunction();
105 }
106 }
107
108 void release() { mExecuteOnDestruction = false; }
109
110 explicit ScopeExit(const ScopeExit&) = delete;
111 ScopeExit& operator=(const ScopeExit&) = delete;
112 ScopeExit& operator=(ScopeExit&&) = delete;
113};
114
115template <typename ExitFunction>
116 requires(std::is_rvalue_reference_v<ExitFunction &&>)
117[[nodiscard]] ScopeExit<ExitFunction> MakeScopeExit(
118 ExitFunction&& exitFunction) {
119 return ScopeExit<ExitFunction>(std::forward<ExitFunction>(exitFunction));
18
Returning without writing to 'exitFunction.', which participates in a condition later
120}
121
122} /* namespace mozilla */
123
124#endif /* mozilla_ScopeExit_h */