Bug Summary

File:root/firefox-clang/dom/base/nsContentUtils.cpp
Warning:line 12331, column 7
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-10-17-231001-351276-1 -x c++ /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/ArrayIterator.h"
62#include "mozilla/AsyncEventDispatcher.h"
63#include "mozilla/AtomArray.h"
64#include "mozilla/Atomics.h"
65#include "mozilla/Attributes.h"
66#include "mozilla/AutoRestore.h"
67#include "mozilla/BackgroundHangMonitor.h"
68#include "mozilla/Base64.h"
69#include "mozilla/BasePrincipal.h"
70#include "mozilla/BasicEvents.h"
71#include "mozilla/BloomFilter.h"
72#include "mozilla/CORSMode.h"
73#include "mozilla/CallState.h"
74#include "mozilla/CheckedInt.h"
75#include "mozilla/ClearOnShutdown.h"
76#include "mozilla/Components.h"
77#include "mozilla/ContentBlockingAllowList.h"
78#include "mozilla/CycleCollectedJSContext.h"
79#include "mozilla/DOMEventTargetHelper.h"
80#include "mozilla/DebugOnly.h"
81#include "mozilla/ErrorResult.h"
82#include "mozilla/EventDispatcher.h"
83#include "mozilla/EventListenerManager.h"
84#include "mozilla/EventQueue.h"
85#include "mozilla/EventStateManager.h"
86#include "mozilla/FOGIPC.h"
87#include "mozilla/FlowMarkers.h"
88#include "mozilla/FlushType.h"
89#include "mozilla/HTMLEditor.h"
90#include "mozilla/HangAnnotations.h"
91#include "mozilla/IMEStateManager.h"
92#include "mozilla/InputEventOptions.h"
93#include "mozilla/Latin1.h"
94#include "mozilla/Likely.h"
95#include "mozilla/LoadInfo.h"
96#include "mozilla/Logging.h"
97#include "mozilla/ManualNAC.h"
98#include "mozilla/Maybe.h"
99#include "mozilla/MediaFeatureChange.h"
100#include "mozilla/MouseEvents.h"
101#include "mozilla/NullPrincipal.h"
102#include "mozilla/OriginAttributes.h"
103#include "mozilla/Preferences.h"
104#include "mozilla/PresShell.h"
105#include "mozilla/ProfilerRunnable.h"
106#include "mozilla/RangeBoundary.h"
107#include "mozilla/RefPtr.h"
108#include "mozilla/Result.h"
109#include "mozilla/ScopeExit.h"
110#include "mozilla/ScrollContainerFrame.h"
111#include "mozilla/ShutdownPhase.h"
112#include "mozilla/Span.h"
113#include "mozilla/StaticAnalysisFunctions.h"
114#include "mozilla/StaticPrefs_browser.h"
115#include "mozilla/StaticPrefs_clipboard.h"
116#include "mozilla/StaticPrefs_dom.h"
117#include "mozilla/StaticPrefs_network.h"
118#include "mozilla/StaticPrefs_pdfjs.h"
119#include "mozilla/dom/ReportDeliver.h"
120#include "mozilla/extensions/WebExtensionPolicy.h"
121#include "nsIOService.h"
122#include "nsMenuPopupFrame.h"
123#include "nsObjectLoadingContent.h"
124#ifdef FUZZING
125# include "mozilla/StaticPrefs_fuzzing.h"
126#endif
127#include "mozilla/StaticPrefs_mathml.h"
128#include "mozilla/StaticPrefs_nglayout.h"
129#include "mozilla/StaticPrefs_privacy.h"
130#include "mozilla/StaticPrefs_test.h"
131#include "mozilla/StaticPrefs_ui.h"
132#include "mozilla/StaticPtr.h"
133#include "mozilla/TextControlState.h"
134#include "mozilla/TextEditor.h"
135#include "mozilla/TextEvents.h"
136#include "mozilla/TextUtils.h"
137#include "mozilla/Tokenizer.h"
138#include "mozilla/UniquePtr.h"
139#include "mozilla/ViewportUtils.h"
140#include "mozilla/dom/AncestorIterator.h"
141#include "mozilla/dom/AutoEntryScript.h"
142#include "mozilla/dom/AutoSuppressEventHandlingAndSuspend.h"
143#include "mozilla/dom/AutocompleteInfoBinding.h"
144#include "mozilla/dom/BindingDeclarations.h"
145#include "mozilla/dom/BindingUtils.h"
146#include "mozilla/dom/BlobImpl.h"
147#include "mozilla/dom/BlobURLProtocolHandler.h"
148#include "mozilla/dom/BorrowedAttrInfo.h"
149#include "mozilla/dom/BrowserBridgeParent.h"
150#include "mozilla/dom/BrowserParent.h"
151#include "mozilla/dom/BrowsingContext.h"
152#include "mozilla/dom/BrowsingContextGroup.h"
153#include "mozilla/dom/CacheExpirationTime.h"
154#include "mozilla/dom/CallbackFunction.h"
155#include "mozilla/dom/CallbackObject.h"
156#include "mozilla/dom/ChildIterator.h"
157#include "mozilla/dom/ChromeMessageBroadcaster.h"
158#include "mozilla/dom/ContentChild.h"
159#include "mozilla/dom/ContentFrameMessageManager.h"
160#include "mozilla/dom/ContentParent.h"
161#include "mozilla/dom/CustomElementRegistry.h"
162#include "mozilla/dom/CustomElementRegistryBinding.h"
163#include "mozilla/dom/CustomElementTypes.h"
164#include "mozilla/dom/DOMArena.h"
165#include "mozilla/dom/DOMException.h"
166#include "mozilla/dom/DOMExceptionBinding.h"
167#include "mozilla/dom/DOMSecurityMonitor.h"
168#include "mozilla/dom/DOMTypes.h"
169#include "mozilla/dom/DataTransfer.h"
170#include "mozilla/dom/DeprecationReportBody.h"
171#include "mozilla/dom/DocGroup.h"
172#include "mozilla/dom/Document.h"
173#include "mozilla/dom/DocumentFragment.h"
174#include "mozilla/dom/DocumentInlines.h"
175#include "mozilla/dom/DocumentOrShadowRoot.h"
176#include "mozilla/dom/Element.h"
177#include "mozilla/dom/ElementBinding.h"
178#include "mozilla/dom/ElementInlines.h"
179#include "mozilla/dom/Event.h"
180#include "mozilla/dom/EventTarget.h"
181#include "mozilla/dom/FileBlobImpl.h"
182#include "mozilla/dom/FileSystemSecurity.h"
183#include "mozilla/dom/FilteredNodeIterator.h"
184#include "mozilla/dom/FormData.h"
185#include "mozilla/dom/FragmentOrElement.h"
186#include "mozilla/dom/FromParser.h"
187#include "mozilla/dom/FunctionBinding.h"
188#include "mozilla/dom/HTMLElement.h"
189#include "mozilla/dom/HTMLFormElement.h"
190#include "mozilla/dom/HTMLImageElement.h"
191#include "mozilla/dom/HTMLInputElement.h"
192#include "mozilla/dom/HTMLTemplateElement.h"
193#include "mozilla/dom/HTMLTextAreaElement.h"
194#include "mozilla/dom/IPCBlob.h"
195#include "mozilla/dom/IPCBlobUtils.h"
196#include "mozilla/dom/MessageBroadcaster.h"
197#include "mozilla/dom/MessageListenerManager.h"
198#include "mozilla/dom/MessagePort.h"
199#include "mozilla/dom/MimeType.h"
200#include "mozilla/dom/MouseEventBinding.h"
201#include "mozilla/dom/MutationObservers.h"
202#include "mozilla/dom/NameSpaceConstants.h"
203#include "mozilla/dom/NodeBinding.h"
204#include "mozilla/dom/NodeInfo.h"
205#include "mozilla/dom/PBrowser.h"
206#include "mozilla/dom/PContentChild.h"
207#include "mozilla/dom/PrototypeList.h"
208#include "mozilla/dom/Range.h"
209#include "mozilla/dom/ReferrerPolicyBinding.h"
210#include "mozilla/dom/ReportingUtils.h"
211#include "mozilla/dom/Sanitizer.h"
212#include "mozilla/dom/ScriptLoader.h"
213#include "mozilla/dom/ScriptSettings.h"
214#include "mozilla/dom/Selection.h"
215#include "mozilla/dom/ShadowRoot.h"
216#include "mozilla/dom/Text.h"
217#include "mozilla/dom/TrustedHTML.h"
218#include "mozilla/dom/TrustedTypeUtils.h"
219#include "mozilla/dom/TrustedTypesConstants.h"
220#include "mozilla/dom/UserActivation.h"
221#include "mozilla/dom/ViewTransition.h"
222#include "mozilla/dom/WindowBinding.h"
223#include "mozilla/dom/WindowContext.h"
224#include "mozilla/dom/WindowGlobalChild.h"
225#include "mozilla/dom/WindowGlobalParent.h"
226#include "mozilla/dom/WorkerCommon.h"
227#include "mozilla/dom/WorkerPrivate.h"
228#include "mozilla/dom/WorkerRunnable.h"
229#include "mozilla/dom/XULCommandEvent.h"
230#include "mozilla/fallible.h"
231#include "mozilla/gfx/2D.h"
232#include "mozilla/gfx/BaseMargin.h"
233#include "mozilla/gfx/BasePoint.h"
234#include "mozilla/gfx/BaseSize.h"
235#include "mozilla/gfx/DataSurfaceHelpers.h"
236#include "mozilla/gfx/Point.h"
237#include "mozilla/gfx/Rect.h"
238#include "mozilla/gfx/Types.h"
239#include "mozilla/glean/GleanPings.h"
240#include "mozilla/htmlaccel/htmlaccelEnabled.h"
241#ifdef MOZ_MAY_HAVE_HTMLACCEL1
242# include "mozilla/htmlaccel/htmlaccelNotInline.h"
243#endif
244#include "mozilla/dom/ContentList.h"
245#include "mozilla/intl/LocaleService.h"
246#include "mozilla/ipc/ProtocolUtils.h"
247#include "mozilla/net/ChannelClassifierUtils.h"
248#include "mozilla/widget/IMEData.h"
249#include "nsAboutProtocolUtils.h"
250#include "nsArrayUtils.h"
251#include "nsAtomHashKeys.h"
252#include "nsAttrName.h"
253#include "nsAttrValue.h"
254#include "nsAttrValueInlines.h"
255#include "nsBaseHashtable.h"
256#include "nsCCUncollectableMarker.h"
257#include "nsCOMPtr.h"
258#include "nsCRT.h"
259#include "nsCRTGlue.h"
260#include "nsCanvasFrame.h"
261#include "nsCaseTreatment.h"
262#include "nsCharSeparatedTokenizer.h"
263#include "nsCharTraits.h"
264#include "nsCompatibility.h"
265#include "nsComponentManagerUtils.h"
266#include "nsContainerFrame.h"
267#include "nsContentCreatorFunctions.h"
268#include "nsContentDLF.h"
269#include "nsContentListDeclarations.h"
270#include "nsContentPolicyUtils.h"
271#include "nsCoord.h"
272#include "nsCycleCollectionNoteChild.h"
273#include "nsDOMMutationObserver.h"
274#include "nsDOMString.h"
275#include "nsDebug.h"
276#include "nsDocShell.h"
277#include "nsDocShellCID.h"
278#include "nsError.h"
279#include "nsFocusManager.h"
280#include "nsFrameList.h"
281#include "nsFrameLoader.h"
282#include "nsFrameLoaderOwner.h"
283#include "nsGenericHTMLElement.h"
284#include "nsGkAtoms.h"
285#include "nsGlobalWindowInner.h"
286#include "nsGlobalWindowOuter.h"
287#include "nsHTMLDocument.h"
288#include "nsHTMLTags.h"
289#include "nsHashKeys.h"
290#include "nsHtml5StringParser.h"
291#include "nsIAboutModule.h"
292#include "nsIAnonymousContentCreator.h"
293#include "nsIAppShell.h"
294#include "nsIArray.h"
295#include "nsIAsyncVerifyRedirectCallback.h"
296#include "nsIBidiKeyboard.h"
297#include "nsIBrowser.h"
298#include "nsICacheInfoChannel.h"
299#include "nsICachingChannel.h"
300#include "nsICategoryManager.h"
301#include "nsIChannel.h"
302#include "nsIChannelEventSink.h"
303#include "nsIClassifiedChannel.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 "nsXPCOM.h"
419#include "nsXPCOMCID.h"
420#include "nsXULAppAPI.h"
421#include "nsXULElement.h"
422#include "nsXULPopupManager.h"
423#include "nscore.h"
424#include "prinrval.h"
425#include "xpcprivate.h"
426#include "xpcpublic.h"
427
428#if defined(XP_WIN)
429// Undefine LoadImage to prevent naming conflict with Windows.
430# undef LoadImage
431#endif
432
433extern "C" int MOZ_XMLTranslateEntity(const char* ptr, const char* end,
434 const char** next, char16_t* result);
435extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end, int ns_aware,
436 const char** colon);
437
438using namespace mozilla::dom;
439using namespace mozilla::ipc;
440using namespace mozilla::gfx;
441using namespace mozilla::layers;
442using namespace mozilla::widget;
443using namespace mozilla;
444
445const char kLoadAsData[] = "loadAsData";
446
447nsIXPConnect* nsContentUtils::sXPConnect;
448nsIScriptSecurityManager* nsContentUtils::sSecurityManager;
449nsIPrincipal* nsContentUtils::sSystemPrincipal;
450nsIPrincipal* nsContentUtils::sNullSubjectPrincipal;
451nsIPrincipal* nsContentUtils::sFingerprintingProtectionPrincipal;
452nsIConsoleService* nsContentUtils::sConsoleService;
453
454static nsTHashMap<RefPtr<nsAtom>, EventNameMapping>* sAtomEventTable;
455static nsTHashMap<nsStringHashKey, EventNameMapping>* sStringEventTable;
456static nsTArray<RefPtr<nsAtom>>* sUserDefinedEvents;
457nsIStringBundleService* nsContentUtils::sStringBundleService;
458
459static constexpr size_t kPropertiesFileCount =
460 static_cast<size_t>(PropertiesFile::COUNT);
461
462static StaticRefPtr<nsIStringBundle> sStringBundles[kPropertiesFileCount];
463
464nsIContentPolicy* nsContentUtils::sContentPolicyService;
465bool nsContentUtils::sTriedToGetContentPolicy = false;
466StaticRefPtr<nsIBidiKeyboard> nsContentUtils::sBidiKeyboard;
467uint32_t nsContentUtils::sScriptBlockerCount = 0;
468uint32_t nsContentUtils::sDOMNodeRemovedSuppressCount = 0;
469AutoTArray<nsCOMPtr<nsIRunnable>, 8>* nsContentUtils::sBlockedScriptRunners =
470 nullptr;
471uint32_t nsContentUtils::sRunnersCountAtFirstBlocker = 0;
472nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nullptr;
473
474bool nsContentUtils::sIsHandlingKeyBoardEvent = false;
475
476nsString* nsContentUtils::sShiftText = nullptr;
477nsString* nsContentUtils::sControlText = nullptr;
478nsString* nsContentUtils::sCommandOrWinText = nullptr;
479nsString* nsContentUtils::sAltText = nullptr;
480nsString* nsContentUtils::sModifierSeparator = nullptr;
481
482bool nsContentUtils::sInitialized = false;
483#ifndef RELEASE_OR_BETA
484bool nsContentUtils::sBypassCSSOMOriginCheck = false;
485#endif
486
487nsCString* nsContentUtils::sJSScriptBytecodeMimeType = nullptr;
488nsCString* nsContentUtils::sJSModuleBytecodeMimeType = nullptr;
489
490nsContentUtils::UserInteractionObserver*
491 nsContentUtils::sUserInteractionObserver = nullptr;
492
493nsHtml5StringParser* nsContentUtils::sHTMLFragmentParser = nullptr;
494nsParser* nsContentUtils::sXMLFragmentParser = nullptr;
495nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nullptr;
496bool nsContentUtils::sFragmentParsingActive = false;
497
498mozilla::LazyLogModule nsContentUtils::gResistFingerprintingLog(
499 "nsResistFingerprinting");
500mozilla::LazyLogModule nsContentUtils::sDOMDumpLog("Dump");
501// Log when "input" and "beforeinput" events are dispatched or enqueued with
502// InputEvent:3,sync.
503mozilla::LazyLogModule gInputEventLog("InputEvent");
504
505int32_t nsContentUtils::sInnerOrOuterWindowCount = 0;
506uint32_t nsContentUtils::sInnerOrOuterWindowSerialCounter = 0;
507
508#define INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
509 aResultType, aMethodName, aTreeKind, ...) \
510 template aResultType aMethodName<aTreeKind>(__VA_ARGS__);
511
512#define INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS( \
513 aResultType, aMethodName, aTreeKind, ...) \
514 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
515 aResultType, aMethodName, aTreeKind, const RangeBoundary&, \
516 const RangeBoundary&, __VA_ARGS__) \
517 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
518 aResultType, aMethodName, aTreeKind, const RangeBoundary&, \
519 const RawRangeBoundary&, __VA_ARGS__) \
520 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
521 aResultType, aMethodName, aTreeKind, const RawRangeBoundary&, \
522 const RangeBoundary&, __VA_ARGS__) \
523 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
524 aResultType, aMethodName, aTreeKind, const RawRangeBoundary&, \
525 const RawRangeBoundary&, __VA_ARGS__) \
526 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
527 aResultType, aMethodName, aTreeKind, const ConstRawRangeBoundary&, \
528 const ConstRawRangeBoundary&, __VA_ARGS__) \
529 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
530 aResultType, aMethodName, aTreeKind, const ConstRawRangeBoundary&, \
531 const RangeBoundary&, __VA_ARGS__) \
532 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
533 aResultType, aMethodName, aTreeKind, const ConstRawRangeBoundary&, \
534 const RawRangeBoundary&, __VA_ARGS__) \
535 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
536 aResultType, aMethodName, aTreeKind, const RangeBoundary&, \
537 const ConstRawRangeBoundary&, __VA_ARGS__) \
538 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
539 aResultType, aMethodName, aTreeKind, const RawRangeBoundary&, \
540 const ConstRawRangeBoundary&, __VA_ARGS__)
541
542INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS(Maybe<int32_t>,
543 nsContentUtils::ComparePoints,
544 TreeKind::DOM,
545 NodeIndexCache*);
546INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS(Maybe<int32_t>,
547 nsContentUtils::ComparePoints,
548 TreeKind::ShadowIncludingDOM,
549 NodeIndexCache*);
550INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS(Maybe<int32_t>,
551 nsContentUtils::ComparePoints,
552 TreeKind::Flat,
553 NodeIndexCache*);
554INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS(Maybe<int32_t>,
555 nsContentUtils::ComparePoints,
556 TreeKind::FlatForSelection,
557 NodeIndexCache*);
558
559#undef INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS
560#undef INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM
561
562// Subset of
563// http://www.whatwg.org/specs/web-apps/current-work/#autofill-field-name
564enum AutocompleteUnsupportedFieldName : uint8_t {
565#define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
566 eAutocompleteUnsupportedFieldName_##name_,
567#include "AutocompleteFieldList.h"
568#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
569};
570
571enum AutocompleteNoPersistFieldName : uint8_t {
572#define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \
573 eAutocompleteNoPersistFieldName_##name_,
574#include "AutocompleteFieldList.h"
575#undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME
576};
577
578enum AutocompleteUnsupportFieldContactHint : uint8_t {
579#define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
580 eAutocompleteUnsupportedFieldContactHint_##name_,
581#include "AutocompleteFieldList.h"
582#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
583};
584
585enum AutocompleteFieldName : uint8_t {
586#define AUTOCOMPLETE_FIELD_NAME(name_, value_) eAutocompleteFieldName_##name_,
587#define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
588 AUTOCOMPLETE_FIELD_NAME(name_, value_)
589#include "AutocompleteFieldList.h"
590#undef AUTOCOMPLETE_FIELD_NAME
591#undef AUTOCOMPLETE_CONTACT_FIELD_NAME
592};
593
594enum AutocompleteFieldHint : uint8_t {
595#define AUTOCOMPLETE_FIELD_HINT(name_, value_) eAutocompleteFieldHint_##name_,
596#include "AutocompleteFieldList.h"
597#undef AUTOCOMPLETE_FIELD_HINT
598};
599
600enum AutocompleteFieldContactHint : uint8_t {
601#define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
602 eAutocompleteFieldContactHint_##name_,
603#include "AutocompleteFieldList.h"
604#undef AUTOCOMPLETE_FIELD_CONTACT_HINT
605};
606
607enum AutocompleteCredentialType : uint8_t {
608#define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \
609 eAutocompleteCredentialType_##name_,
610#include "AutocompleteFieldList.h"
611#undef AUTOCOMPLETE_CREDENTIAL_TYPE
612};
613
614enum AutocompleteCategory {
615#define AUTOCOMPLETE_CATEGORY(name_, value_) eAutocompleteCategory_##name_,
616#include "AutocompleteFieldList.h"
617#undef AUTOCOMPLETE_CATEGORY
618};
619
620static constexpr nsAttrValue::EnumTableEntry
621 kAutocompleteUnsupportedFieldNameTable[]{
622#define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
623 {value_, eAutocompleteUnsupportedFieldName_##name_},
624#include "AutocompleteFieldList.h"
625#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
626 };
627
628static constexpr nsAttrValue::EnumTableEntry
629 kAutocompleteNoPersistFieldNameTable[] = {
630#define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \
631 {value_, eAutocompleteNoPersistFieldName_##name_},
632#include "AutocompleteFieldList.h"
633#undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME
634};
635static constexpr nsAttrValue::EnumTableEntry
636 kAutocompleteUnsupportedContactFieldHintTable[] = {
637#define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
638 {value_, eAutocompleteUnsupportedFieldContactHint_##name_},
639#include "AutocompleteFieldList.h"
640#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
641};
642
643static constexpr nsAttrValue::EnumTableEntry kAutocompleteFieldNameTable[] = {
644#define AUTOCOMPLETE_FIELD_NAME(name_, value_) \
645 {value_, eAutocompleteFieldName_##name_},
646#include "AutocompleteFieldList.h"
647#undef AUTOCOMPLETE_FIELD_NAME
648};
649
650static constexpr nsAttrValue::EnumTableEntry
651 kAutocompleteContactFieldNameTable[] = {
652#define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
653 {value_, eAutocompleteFieldName_##name_},
654#include "AutocompleteFieldList.h"
655#undef AUTOCOMPLETE_CONTACT_FIELD_NAME
656};
657
658static constexpr nsAttrValue::EnumTableEntry kAutocompleteFieldHintTable[] = {
659#define AUTOCOMPLETE_FIELD_HINT(name_, value_) \
660 {value_, eAutocompleteFieldHint_##name_},
661#include "AutocompleteFieldList.h"
662#undef AUTOCOMPLETE_FIELD_HINT
663};
664
665static constexpr nsAttrValue::EnumTableEntry
666 kAutocompleteContactFieldHintTable[] = {
667#define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
668 {value_, eAutocompleteFieldContactHint_##name_},
669#include "AutocompleteFieldList.h"
670#undef AUTOCOMPLETE_FIELD_CONTACT_HINT
671};
672
673static constexpr nsAttrValue::EnumTableEntry
674 kAutocompleteCredentialTypeTable[] = {
675#define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \
676 {value_, eAutocompleteCredentialType_##name_},
677#include "AutocompleteFieldList.h"
678#undef AUTOCOMPLETE_CREDENTIAL_TYPE
679};
680
681namespace {
682
683// Non-owning list of the managers nodes store themselves; the managers remove
684// themselves from it when deleted. Documents keep their manager in
685// Document::mListenerManager and are not in this list.
686constinit DoublyLinkedList<EventListenerManager> sNodeEventListenerManagers;
687
688// A global hashtable to for keeping the arena alive for cross docGroup node
689// adoption.
690static nsRefPtrHashtable<nsPtrHashKey<const nsINode>, mozilla::dom::DOMArena>*
691 sDOMArenaHashtable;
692
693class SameOriginCheckerImpl final : public nsIChannelEventSink,
694 public nsIInterfaceRequestor {
695 ~SameOriginCheckerImpl() = default;
696
697 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:
698 NS_DECL_NSICHANNELEVENTSINKvirtual nsresult AsyncOnChannelRedirect(nsIChannel *oldChannel
, nsIChannel *newChannel, uint32_t flags, nsIAsyncVerifyRedirectCallback
*callback) override;
699 NS_DECL_NSIINTERFACEREQUESTORvirtual nsresult GetInterface(const nsIID & uuid, void * *
result) override;
700};
701
702} // namespace
703
704void AutoSuppressEventHandling::SuppressDocument(Document* aDoc) {
705 // Note: Document::SuppressEventHandling will also automatically suppress
706 // event handling for any in-process sub-documents. However, since we need
707 // to deal with cases where remote BrowsingContexts may be interleaved
708 // with in-process ones, we still need to walk the entire tree ourselves.
709 // This may be slightly redundant in some cases, but since event handling
710 // suppressions maintain a count of current blockers, it does not cause
711 // any problems.
712 aDoc->SuppressEventHandling();
713}
714
715void AutoSuppressEventHandling::UnsuppressDocument(Document* aDoc) {
716 aDoc->UnsuppressEventHandlingAndFireEvents(true);
717}
718
719AutoSuppressEventHandling::~AutoSuppressEventHandling() {
720 UnsuppressDocuments();
721}
722
723void AutoSuppressEventHandlingAndSuspend::SuppressDocument(Document* aDoc) {
724 AutoSuppressEventHandling::SuppressDocument(aDoc);
725 if (nsCOMPtr<nsPIDOMWindowInner> win = aDoc->GetInnerWindow()) {
726 win->Suspend();
727 mWindows.AppendElement(win);
728 }
729}
730
731AutoSuppressEventHandlingAndSuspend::~AutoSuppressEventHandlingAndSuspend() {
732 for (const auto& win : mWindows) {
733 win->Resume();
734 }
735}
736
737// The following structs are used by CommonAncestors. They must have:
738// NodeType, Get(), ComputeChildIndex(), GetChildCount() and CanComputeIndex().
739// If CanComputeIndex() returns false, ComputeChildIndex() nor GetChildCount()
740// is not used by CommonAncestors to assert the odd result.
741
742/**
743 * GetParentNodeForComparison is used for implementing
744 * nsContentUtils::ComparePoints and its relatives and helpers.
745 */
746template <TreeKind aKind>
747struct GetParentNodeForComparison {
748 using NodeType = nsINode;
749 static NodeType* Get(const NodeType* aNode) {
750 if constexpr (aKind == TreeKind::DOM) {
751 return aNode->GetParentNode();
752 }
753 // We want to list up ShadowRoot as the parent of a child of ShadowRoot and
754 // its host as the parent of the ShadowRoot. GetFlattenedTreeParentNode()
755 // won't return ShadowRoot so that we cannot use
756 // nsINode::GetParentNode<aKind>() here.
757 if constexpr (ShouldHandleAssignedNodesOnSlot<aKind>()) {
758 if (aNode->IsContent()) {
759 if (HTMLSlotElement* const slot =
760 aNode->AsContent()->GetAssignedSlot<aKind>()) {
761 return slot;
762 }
763 // FIXME: If aNode->GetParentNode()->GetShadowRoot<aKind>() returns
764 // non-nullptr, we should always return nullptr here. However, if aKind
765 // is TreeKind::FlatForSelection, we cannot do that because
766 // GetFlattenedTreeParentNode<nsINode::eForSelection>() returns the
767 // shadow host element as-is. Therefore, we do the strict behavior only
768 // here causes assertion failures with the extant tests. This should
769 // be fixed in bug 2014622.
770 if constexpr (aKind != TreeKind::FlatForSelection) {
771 // If we're handling a flattened tree, we should return nullptr if the
772 // node is not part of a flattened tree.
773 if (nsINode* const parentNode = aNode->GetParentNode()) {
774 if (parentNode->GetShadowRoot<aKind>()) {
775 return nullptr;
776 }
777 }
778 }
779 }
780 }
781 return aNode->GetParentOrShadowHostNode();
782 }
783 static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent,
784 const nsIContent* aPossibleChild) {
785 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
786 return aParent->ComputeIndexOf(aPossibleChild);
787 } else {
788 return aParent->ComputeIndexOf<aKind>(aPossibleChild);
789 }
790 }
791 static uint32_t GetChildCount(const NodeType* aParent) {
792 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
793 return aParent->GetChildCount();
794 } else {
795 return aParent->GetChildCount<aKind>();
796 }
797 }
798 constexpr static bool CanComputeIndex() {
799 // The helpers of nsContentUtils::ComparePoints() and relatives require
800 // ComputeChildIndex() and GetChildCount(). Therefore, we implement them and
801 // return true.
802 return true;
803 }
804};
805
806/**
807 * GetParentNode is used for implementing
808 * nsContentUtils::GetClosestCommonInclusiveAncestor().
809 */
810using GetParentNode = GetParentNodeForComparison<TreeKind::DOM>;
811
812/**
813 * GetParentOrShadowHostNode is used for implementing
814 * nsContentUtils::GetClosestCommonShadowIncludingInclusiveAncestor().
815 */
816struct GetParentOrShadowHostNode {
817 using NodeType = nsINode;
818 static NodeType* Get(const NodeType* aNode) {
819 return aNode->GetParentOrShadowHostNode();
820 }
821 static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent,
822 const nsIContent* aPossibleChild) {
823 return aParent->ComputeIndexOf(aPossibleChild);
824 }
825 static uint32_t GetChildCount(const NodeType* aParent) {
826 return aParent->GetChildCount();
827 }
828 constexpr static bool CanComputeIndex() {
829 // Neither ComputeChildIndex() nor GetChildCount() is required by
830 // nsContentUtils::GetClosestCommonShadowIncludingInclusiveAncestor(), but
831 // let's implement them to make CommonAncestors asserts the odd situations
832 // so that return true.
833 return true;
834 }
835};
836
837/**
838 * GetFlattenedTreeParent is used for implementing
839 * nsContentUtils::GetCommonFlattenedTreeAncestor().
840 */
841struct GetFlattenedTreeParent {
842 using NodeType = nsIContent;
843 static NodeType* Get(const NodeType* aContent) {
844 return aContent->GetFlattenedTreeParent();
845 }
846 static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent,
847 const nsIContent* aPossibleChild) {
848 return aParent->ComputeFlatTreeIndexOf(aPossibleChild);
849 }
850 static uint32_t GetChildCount(const NodeType* aParent) {
851 return aParent->GetFlatTreeChildCount();
852 }
853 constexpr static bool CanComputeIndex() {
854 // Neither ComputeChildIndex() nor GetChildCount() is required by
855 // nsContentUtils::GetCommonFlattenedTreeAncestor(), but let's implement
856 // them to make CommonAncestors asserts the odd situations so that return
857 // true.
858 return true;
859 }
860};
861
862/**
863 * GetFlattenedTreeParentNodeForSelection is used for implementing
864 * nsContentUtils::GetCommonFlattenedTreeAncestorForSelection().
865 */
866struct GetFlattenedTreeParentNodeForSelection {
867 using NodeType = nsINode;
868 static NodeType* Get(const NodeType* aNode) {
869 return aNode->GetFlattenedTreeParentNodeForSelection();
870 }
871 static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent,
872 const nsIContent* aPossibleChild) {
873 return aParent->ComputeFlatTreeForSelectionIndexOf(aPossibleChild);
874 }
875 static uint32_t GetChildCount(const NodeType* aParent) {
876 return aParent->GetFlatTreeForSelectionChildCount();
877 }
878 constexpr static bool CanComputeIndex() {
879 // Neither ComputeChildIndex() nor GetChildCount() is required by
880 // nsContentUtils::GetCommonFlattenedTreeAncestorForSelection(), but let's
881 // implement them to make CommonAncestors asserts the odd situations so that
882 // return true.
883 return true;
884 }
885};
886
887/**
888 * GetFlattenedTreeParentElementForStyle is used for implementing
889 * nsContentUtils::GetCommonFlattenedTreeAncestorForStyle().
890 */
891struct GetFlattenedTreeParentElementForStyle {
892 using NodeType = Element;
893 static NodeType* Get(const NodeType* aElement) {
894 return aElement->GetFlattenedTreeParentElementForStyle();
895 }
896 static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent,
897 const nsIContent* aPossibleChild) {
898 return Nothing();
899 }
900 static uint32_t GetChildCount(const NodeType* aParent) {
901 return 0; // This should be called only when CanComputeIndex() returns true
902 }
903 constexpr static bool CanComputeIndex() {
904 // Neither ComputeChildIndex() nor GetChildCount() is required by
905 // nsContentUtils::GetCommonFlattenedTreeAncestorForStyle() and there is no
906 // API to get child count nor compute index of a child in the flattened tree
907 // for style. Therefore, we don't implement them so that return false.
908 return false;
909 }
910};
911
912/**
913 * GetParentBrowserParent is used for implementing
914 * nsContentUtils::GetCommonBrowserParentAncestor().
915 */
916struct GetParentBrowserParent {
917 using NodeType = BrowserParent;
918 static NodeType* Get(const NodeType* aBrowserParent) {
919 return aBrowserParent->GetBrowserBridgeParent()
920 ? aBrowserParent->GetBrowserBridgeParent()->Manager()
921 : nullptr;
922 }
923 static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent,
924 const nsIContent* aPossibleChild) {
925 return Nothing();
926 }
927 static uint32_t GetChildCount(const NodeType* aParent) {
928 return 0; // This should be called only when CanComputeIndex() returns true
929 }
930 constexpr static bool CanComputeIndex() {
931 // Neither ComputeChildIndex() nor GetChildCount() is required by
932 // nsContentUtils::GetCommonBrowserParentAncestor() and there is no API to
933 // get child count of a BrowserParent nor compute index of a child of
934 // BrowserParent. Therefore, we don't implement them so that return false.
935 return false;
936 }
937};
938
939template <TreeKind aKind>
940static bool ChildNodeIsInShadowDOMHostedByParent(const nsINode* aParent,
941 const nsINode* aChild) {
942 ShadowRoot* const shadowRoot = aParent->GetShadowRoot<aKind>();
943 if (!shadowRoot) {
944 return false;
945 }
946 // We already checked whether aChild is in a shadow in the tree kind.
947 // Therefore, we don't need to use GetContainingShadowForSelection() here.
948 return shadowRoot == aChild->GetContainingShadow();
949}
950
951// If we're comparing 2 DOM points in TreeKind::ShadowIncludingDOM mode, we want
952// to compare the direct children of the parent node even if the parent is a
953// shadow host. So, we want to compare them as TreeKind::DOM.
954template <TreeKind aKind>
955constexpr TreeKind TreeKindToCompareChildren() {
956 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
957 return TreeKind::DOM;
958 } else {
959 return aKind;
960 }
961}
962
963template <class GetParentStruct>
964class MOZ_STACK_CLASS CommonAncestors final {
965 public:
966 using NodeType = GetParentStruct::NodeType;
967
968 /**
969 * @param aNode1 A DOM node or something which may have ancestors.
970 * @param aNode2 Another DOM node or something.
971 * @param aGetParentStruct A struct containing static GetParent(),
972 * ComputeChildIndex(), GetChildCount() and CanComputeIndex(). If
973 * CanComputeIndex() returns false, ComputeChildIndex() nor GetChildCount() is
974 * never used.
975 */
976 CommonAncestors(const NodeType& aNode1, const NodeType& aNode2) {
977#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1
978 mAssertNoGC.emplace();
979#endif // #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
980
981 AppendInclusiveAncestors(const_cast<NodeType*>(&aNode1),
982 mInclusiveAncestors1);
983 AppendInclusiveAncestors(const_cast<NodeType*>(&aNode2),
984 mInclusiveAncestors2);
985
986 // Find where the parent chain differs
987 size_t depth1 = mInclusiveAncestors1.Length();
988 size_t depth2 = mInclusiveAncestors2.Length();
989 const size_t shorterLength = std::min(depth1, depth2);
990 NodeType** const inclusiveAncestors1 = mInclusiveAncestors1.Elements();
991 NodeType** const inclusiveAncestors2 = mInclusiveAncestors2.Elements();
992 for ([[maybe_unused]] const size_t unused : IntegerRange(shorterLength)) {
993 NodeType* const inclusiveAncestor1 = inclusiveAncestors1[--depth1];
994 NodeType* const inclusiveAncestor2 = inclusiveAncestors2[--depth2];
995 if (inclusiveAncestor1 != inclusiveAncestor2) {
996 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"
, 997); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inclusiveAncestor1 == GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 997); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
997 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"
, 997); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inclusiveAncestor1 == GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 997); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
998 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"
, 999); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inclusiveAncestor2 == GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 999); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
999 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"
, 999); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inclusiveAncestor2 == GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 999); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1000 return;
1001 }
1002 mNumberOfCommonAncestors++;
1003 mClosestCommonAncestor = inclusiveAncestor1;
1004 }
1005 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", 1005); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mClosestCommonAncestor" ")"); do { MOZ_CrashSequence
(__null, 1005); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1006 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", 1006); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mNumberOfCommonAncestors" ")"); do { MOZ_CrashSequence
(__null, 1006); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1007 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", 1007); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!depth1 || !depth2" ")"); do { MOZ_CrashSequence
(__null, 1007); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1008 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", 1008); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!GetClosestCommonAncestorChild1()" ")"); do
{ MOZ_CrashSequence(__null, 1008); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); } } while (false
)
;
1009 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"
, 1009); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 1009); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1010 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", 1010); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!GetClosestCommonAncestorChild2()" ")"); do
{ MOZ_CrashSequence(__null, 1010); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); } } while (false
)
;
1011 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"
, 1011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 1011); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1012 }
1013
1014#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1
1015 ~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", 1015); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "!mMutationGuard.Mutated(0)" ")"
); do { MOZ_CrashSequence(__null, 1015); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; }
1016#endif // #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1017
1018 [[nodiscard]] NodeType* GetClosestCommonAncestor() const {
1019 return mClosestCommonAncestor;
1020 }
1021 [[nodiscard]] NodeType* GetClosestCommonAncestorChild1() const {
1022 return GetClosestCommonAncestorChild(mInclusiveAncestors1);
1023 }
1024 [[nodiscard]] NodeType* GetClosestCommonAncestorChild2() const {
1025 return GetClosestCommonAncestorChild(mInclusiveAncestors2);
1026 }
1027
1028 template <TreeKind aKind>
1029 void WarnIfClosestCommonAncestorChildrenAreNotInChildList() const {
1030 WarnIfClosestCommonAncestorChildIsNotInChildList<aKind>(
1031 mInclusiveAncestors1);
1032 WarnIfClosestCommonAncestorChildIsNotInChildList<aKind>(
1033 mInclusiveAncestors2);
1034 }
1035
1036 private:
1037 static void AppendInclusiveAncestors(NodeType* aNode,
1038 nsTArray<NodeType*>& aArrayOfParents) {
1039 NodeType* node = aNode;
1040 while (node) {
1041 aArrayOfParents.AppendElement(node);
1042 node = GetParentStruct::Get(node);
1043 }
1044 }
1045
1046 Maybe<size_t> GetClosestCommonAncestorChildIndex(
1047 const nsTArray<NodeType*>& aInclusiveAncestors) const {
1048 if (!mClosestCommonAncestor ||
1049 aInclusiveAncestors.Length() <= mNumberOfCommonAncestors) {
1050 return Nothing();
1051 }
1052 return Some((aInclusiveAncestors.Length() - 1) // last index
1053 - mNumberOfCommonAncestors); // before closest common ancestor
1054 }
1055
1056 [[nodiscard]] NodeType* GetClosestCommonAncestorChild(
1057 const nsTArray<NodeType*>& aInclusiveAncestors) const {
1058 const Maybe<size_t> index =
1059 GetClosestCommonAncestorChildIndex(aInclusiveAncestors);
1060 if (index.isNothing()) {
1061 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", 1062); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aInclusiveAncestors.Length() == mNumberOfCommonAncestors"
")"); do { MOZ_CrashSequence(__null, 1062); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1062 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", 1062); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aInclusiveAncestors.Length() == mNumberOfCommonAncestors"
")"); do { MOZ_CrashSequence(__null, 1062); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1063 return nullptr;
1064 }
1065 NodeType* const child = aInclusiveAncestors[*index];
1066 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"
, 1066); AnnotateMozCrashReason("MOZ_ASSERT" "(" "child" ")")
; do { MOZ_CrashSequence(__null, 1066); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1067 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"
, 1067); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetParentStruct::Get(child) == mClosestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 1067); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1068 return child;
1069 }
1070
1071 template <TreeKind aKind>
1072 void WarnIfClosestCommonAncestorChildIsNotInChildList(
1073 const nsTArray<NodeType*>& aInclusiveAncestors) const {
1074#ifdef DEBUG1
1075 if constexpr (std::is_base_of_v<nsINode, NodeType>) {
1076 if (!GetParentStruct::CanComputeIndex()) {
1077 return;
1078 }
1079 const nsIContent* const child = nsIContent::FromNodeOrNull(
1080 GetClosestCommonAncestorChild(aInclusiveAncestors));
1081 if (!child) {
1082 return;
1083 }
1084
1085 if (child->IsShadowRoot() ||
1086 (ShouldHandleAssignedNodesOnSlot<aKind>() &&
1087 child->GetAssignedSlot<aKind>() &&
1088 mClosestCommonAncestor != child->GetAssignedSlot<aKind>())) {
1089 return;
1090 }
1091
1092 if (MOZ_LIKELY((__builtin_expect(!!(GetParentStruct::ComputeChildIndex(mClosestCommonAncestor
, child) .isSome()), 1))
1093 GetParentStruct::ComputeChildIndex(mClosestCommonAncestor, child)(__builtin_expect(!!(GetParentStruct::ComputeChildIndex(mClosestCommonAncestor
, child) .isSome()), 1))
1094 .isSome())(__builtin_expect(!!(GetParentStruct::ComputeChildIndex(mClosestCommonAncestor
, child) .isSome()), 1))
) {
1095 return;
1096 }
1097 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
1098 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"
, 1098)
;
1099 const nsINode* const parentOrShadowHostNode =
1100 child->GetParentOrShadowHostNode();
1101 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"
, 1111)
1102 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"
, 1111)
1103 "\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"
, 1111)
1104 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"
, 1111)
1105 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"
, 1111)
1106 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"
, 1111)
1107 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"
, 1111)
1108 ? 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"
, 1111)
1109 : 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"
, 1111)
1110 .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"
, 1111)
1111 .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"
, 1111)
;
1112 } else if constexpr (aKind == TreeKind::FlatForSelection) {
1113 if (child->GetParentNode() == mClosestCommonAncestor) {
1114 // It's okay to compare the non-assigned children of a shadow host
1115 // with the shadow root or another non-assigned child if we're
1116 // handling the flattened tree for selection.
1117 if (mClosestCommonAncestor->GetShadowRootForSelection()) {
1118 return;
1119 }
1120 // It's okay to compare the fallback content of a <slot> which has
1121 // some assigned nodes and a parent of the flattened tree if we're
1122 // handling the flattened tree for selection.
1123 if (mClosestCommonAncestor
1124 ->GetAsHTMLSlotElementIfFilledForSelection()) {
1125 return;
1126 }
1127 }
1128 }
1129 const Maybe<size_t> index =
1130 GetClosestCommonAncestorChildIndex(aInclusiveAncestors);
1131 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"
, 1143)
1132 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"
, 1143)
1133 "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"
, 1143)
1134 "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"
, 1143)
1135 "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"
, 1143)
1136 " {}\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"
, 1143)
1137 " + {}\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"
, 1143)
1138 "{}", // 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"
, 1143)
1139 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"
, 1143)
1140 *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"
, 1143)
1141 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"
, 1143)
1142 : "")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"
, 1143)
1143 .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"
, 1143)
;
1144 }
1145#endif
1146 }
1147
1148 AutoTArray<NodeType*, 30> mInclusiveAncestors1;
1149 AutoTArray<NodeType*, 30> mInclusiveAncestors2;
1150 NodeType* mClosestCommonAncestor = nullptr;
1151 uint32_t mNumberOfCommonAncestors = 0;
1152
1153#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1
1154 nsMutationGuard mMutationGuard;
1155 Maybe<JS::AutoAssertNoGC> mAssertNoGC;
1156#endif
1157};
1158
1159/**
1160 * This class is used to determine whether or not the user is currently
1161 * interacting with the browser. It listens to observer events to toggle the
1162 * value of the sUserActive static.
1163 *
1164 * This class is an internal implementation detail.
1165 * nsContentUtils::GetUserIsInteracting() should be used to access current
1166 * user interaction status.
1167 */
1168class nsContentUtils::UserInteractionObserver final
1169 : public nsIObserver,
1170 public BackgroundHangAnnotator {
1171 public:
1172 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:
1173 NS_DECL_NSIOBSERVERvirtual nsresult Observe(nsISupports *aSubject, const char * aTopic
, const char16_t * aData) override;
1174
1175 void Init();
1176 void Shutdown();
1177 void AnnotateHang(BackgroundHangAnnotations& aAnnotations) override;
1178
1179 static Atomic<bool> sUserActive;
1180
1181 private:
1182 ~UserInteractionObserver() = default;
1183};
1184
1185static constexpr nsLiteralCString kRfpPrefs[] = {
1186 "privacy.resistFingerprinting"_ns,
1187 "privacy.resistFingerprinting.pbmode"_ns,
1188 "privacy.fingerprintingProtection"_ns,
1189 "privacy.fingerprintingProtection.pbmode"_ns,
1190 "privacy.fingerprintingProtection.overrides"_ns,
1191 "privacy.baselineFingerprintingProtection"_ns,
1192 "privacy.baselineFingerprintingProtection.overrides"_ns,
1193};
1194
1195static void RecomputeResistFingerprintingAllDocs(const char*, void*) {
1196 AutoTArray<RefPtr<Document>, 64> allDocuments;
1197 Document::GetAllInProcessDocuments(allDocuments);
1198 for (auto& doc : allDocuments) {
1199 doc->RecomputeResistFingerprinting(
1200 /* aForceRefreshRTPCallerType= */ true);
1201 if (auto* pc = doc->GetPresContext()) {
1202 pc->MediaFeatureValuesChanged(
1203 {MediaFeatureChangeReason::PreferenceChange},
1204 MediaFeatureChangePropagation::JustThisDocument);
1205 }
1206 }
1207}
1208
1209// static
1210nsresult nsContentUtils::Init() {
1211 if (sInitialized) {
1212 NS_WARNING("Init() called twice")NS_DebugBreak(NS_DEBUG_WARNING, "Init() called twice", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1212)
;
1213
1214 return NS_OK;
1215 }
1216
1217 nsHTMLTags::AddRefTable();
1218
1219 sXPConnect = nsXPConnect::XPConnect();
1220 // We hold a strong ref to sXPConnect to ensure that it does not go away until
1221 // nsLayoutStatics::Shutdown is happening. Otherwise ~nsXPConnect can be
1222 // triggered by xpcModuleDtor late in shutdown and cause crashes due to
1223 // various stuff already being torn down by then. Note that this means that
1224 // we are effectively making sure that if we leak nsLayoutStatics then we also
1225 // leak nsXPConnect.
1226 NS_ADDREF(sXPConnect)(sXPConnect)->AddRef();
1227
1228 sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager();
1229 if (!sSecurityManager) return NS_ERROR_FAILURE;
1230 NS_ADDREF(sSecurityManager)(sSecurityManager)->AddRef();
1231
1232 sSecurityManager->GetSystemPrincipal(&sSystemPrincipal);
1233 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", 1233); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sSystemPrincipal" ")"); do { MOZ_CrashSequence
(__null, 1233); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1234
1235 RefPtr<NullPrincipal> nullPrincipal =
1236 NullPrincipal::CreateWithoutOriginAttributes();
1237 if (!nullPrincipal) {
1238 return NS_ERROR_FAILURE;
1239 }
1240
1241 nullPrincipal.forget(&sNullSubjectPrincipal);
1242
1243 RefPtr<nsIPrincipal> fingerprintingProtectionPrincipal =
1244 BasePrincipal::CreateContentPrincipal(
1245 "about:fingerprintingprotection"_ns);
1246 if (!fingerprintingProtectionPrincipal) {
1247 return NS_ERROR_FAILURE;
1248 }
1249
1250 fingerprintingProtectionPrincipal.forget(&sFingerprintingProtectionPrincipal);
1251
1252 if (!InitializeEventTable()) return NS_ERROR_FAILURE;
1253
1254 sBlockedScriptRunners = new AutoTArray<nsCOMPtr<nsIRunnable>, 8>;
1255
1256#ifndef RELEASE_OR_BETA
1257 sBypassCSSOMOriginCheck = getenv("MOZ_BYPASS_CSSOM_ORIGIN_CHECK");
1258#endif
1259
1260 Element::InitCCCallbacks();
1261
1262 RefPtr<nsRFPService> rfpService = nsRFPService::GetOrCreate();
1263 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"
, 1263); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rfpService"
")"); do { MOZ_CrashSequence(__null, 1263); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1264
1265 if (XRE_IsParentProcess()) {
1266 AsyncPrecreateStringBundles();
1267
1268#if defined(MOZ_WIDGET_ANDROID)
1269 // On Android, at-shutdown ping submission isn't reliable
1270 // (( because, on Android, we usually get killed, not shut down )).
1271 // To have a chance at submitting the ping, aim for idle after startup.
1272 nsresult rv = NS_DispatchToCurrentThreadQueue(
1273 NS_NewRunnableFunction(
1274 "AndroidUseCounterPingSubmitter",
1275 []() { glean_pings::UseCounters.Submit("idle_startup"_ns); }),
1276 EventQueuePriority::Idle);
1277 // This is mostly best-effort, so if it goes awry, just log.
1278 (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"
, 1278)
;
1279#endif // defined(MOZ_WIDGET_ANDROID)
1280
1281 RunOnShutdown(
1282 [&] { glean_pings::UseCounters.Submit("app_shutdown_confirmed"_ns); },
1283 ShutdownPhase::AppShutdownConfirmed);
1284
1285 // On child process, this is initialized in ContentChild.
1286 LookAndFeel::EnsureInit();
1287 }
1288
1289 RefPtr<UserInteractionObserver> uio = new UserInteractionObserver();
1290 uio->Init();
1291 uio.forget(&sUserInteractionObserver);
1292
1293 for (const auto& pref : kRfpPrefs) {
1294 Preferences::RegisterCallback(RecomputeResistFingerprintingAllDocs, pref);
1295 }
1296
1297 mozilla::dom::ReportDeliver::Initialize();
1298
1299 sInitialized = true;
1300
1301 return NS_OK;
1302}
1303
1304bool nsContentUtils::InitJSBytecodeMimeType() {
1305 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", 1305); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1305); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1306 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", 1306); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!sJSScriptBytecodeMimeType" ")"); do { MOZ_CrashSequence
(__null, 1306); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1307 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", 1307); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!sJSModuleBytecodeMimeType" ")"); do { MOZ_CrashSequence
(__null, 1307); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1308
1309 JS::BuildIdCharVector jsBuildId;
1310 if (!JS::GetScriptTranscodingBuildId(&jsBuildId)) {
1311 return false;
1312 }
1313
1314 nsDependentCSubstring jsBuildIdStr(jsBuildId.begin(), jsBuildId.length());
1315 sJSScriptBytecodeMimeType =
1316 new nsCString("javascript/moz-script-bytecode-"_ns + jsBuildIdStr);
1317 sJSModuleBytecodeMimeType =
1318 new nsCString("javascript/moz-module-bytecode-"_ns + jsBuildIdStr);
1319 return true;
1320}
1321
1322void nsContentUtils::GetShiftText(nsAString& text) {
1323 if (!sShiftText) InitializeModifierStrings();
1324 text.Assign(*sShiftText);
1325}
1326
1327void nsContentUtils::GetControlText(nsAString& text) {
1328 if (!sControlText) InitializeModifierStrings();
1329 text.Assign(*sControlText);
1330}
1331
1332void nsContentUtils::GetCommandOrWinText(nsAString& text) {
1333 if (!sCommandOrWinText) {
1334 InitializeModifierStrings();
1335 }
1336 text.Assign(*sCommandOrWinText);
1337}
1338
1339void nsContentUtils::GetAltText(nsAString& text) {
1340 if (!sAltText) InitializeModifierStrings();
1341 text.Assign(*sAltText);
1342}
1343
1344void nsContentUtils::GetModifierSeparatorText(nsAString& text) {
1345 if (!sModifierSeparator) InitializeModifierStrings();
1346 text.Assign(*sModifierSeparator);
1347}
1348
1349void nsContentUtils::InitializeModifierStrings() {
1350 // load the display strings for the keyboard accelerators
1351 nsCOMPtr<nsIStringBundleService> bundleService =
1352 mozilla::components::StringBundle::Service();
1353 nsCOMPtr<nsIStringBundle> bundle;
1354 DebugOnly<nsresult> rv = NS_OK;
1355 if (bundleService) {
1356 rv = bundleService->CreateBundle(
1357 "chrome://global-platform/locale/platformKeys.properties",
1358 getter_AddRefs(bundle));
1359 }
1360
1361 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"
, 1363); MOZ_PretendNoReturn(); } } while (0)
1362 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"
, 1363); MOZ_PretendNoReturn(); } } while (0)
1363 "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"
, 1363); MOZ_PretendNoReturn(); } } while (0)
;
1364 nsAutoString shiftModifier;
1365 nsAutoString commandOrWinModifier;
1366 nsAutoString altModifier;
1367 nsAutoString controlModifier;
1368 nsAutoString modifierSeparator;
1369 if (bundle) {
1370 // macs use symbols for each modifier key, so fetch each from the bundle,
1371 // which also covers i18n
1372 bundle->GetStringFromName("VK_SHIFT", shiftModifier);
1373 bundle->GetStringFromName("VK_COMMAND_OR_WIN", commandOrWinModifier);
1374 bundle->GetStringFromName("VK_ALT", altModifier);
1375 bundle->GetStringFromName("VK_CONTROL", controlModifier);
1376 bundle->GetStringFromName("MODIFIER_SEPARATOR", modifierSeparator);
1377 }
1378 // if any of these don't exist, we get an empty string
1379 sShiftText = new nsString(std::move(shiftModifier));
1380 sCommandOrWinText = new nsString(std::move(commandOrWinModifier));
1381 sAltText = new nsString(std::move(altModifier));
1382 sControlText = new nsString(std::move(controlModifier));
1383 sModifierSeparator = new nsString(std::move(modifierSeparator));
1384}
1385
1386mozilla::EventClassID nsContentUtils::GetEventClassIDFromMessage(
1387 EventMessage aEventMessage) {
1388 switch (aEventMessage) {
1389#define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
1390 case message_: \
1391 return struct_;
1392#include "mozilla/EventNameList.inc"
1393#undef MESSAGE_TO_EVENT
1394 default:
1395 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"
, 1395); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Invalid event message?" ")"); do
{ MOZ_CrashSequence(__null, 1395); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1396 return eBasicEventClass;
1397 }
1398}
1399
1400bool nsContentUtils::IsExternalProtocol(nsIURI* aURI) {
1401 bool doesNotReturnData = false;
1402 nsresult rv = NS_URIChainHasFlags(
1403 aURI, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA, &doesNotReturnData);
1404 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && doesNotReturnData;
1405}
1406
1407/* static */
1408nsAtom* nsContentUtils::GetEventTypeFromMessage(EventMessage aEventMessage) {
1409 switch (aEventMessage) {
1410#define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
1411 case message_: \
1412 return nsGkAtoms::on##name_;
1413#include "mozilla/EventNameList.inc"
1414#undef MESSAGE_TO_EVENT
1415 default:
1416 return nullptr;
1417 }
1418}
1419
1420/* static */
1421already_AddRefed<nsAtom> nsContentUtils::GetEventType(
1422 const WidgetEvent* aEvent) {
1423 RefPtr<nsAtom> typeAtom =
1424 aEvent->mMessage == eUnidentifiedEvent
1425 ? aEvent->mSpecifiedEventType.get()
1426 : nsContentUtils::GetEventTypeFromMessage(aEvent->mMessage);
1427 return typeAtom.forget();
1428}
1429
1430bool nsContentUtils::InitializeEventTable() {
1431 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"
, 1431); MOZ_PretendNoReturn(); } } while (0)
;
1432 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"
, 1432); MOZ_PretendNoReturn(); } } while (0)
;
1433
1434 static const EventNameMapping eventArray[] = {
1435#define EVENT(name_, _message, _type, _class) \
1436 {nsGkAtoms::on##name_, _type, _message, _class},
1437#define WINDOW_ONLY_EVENT EVENT
1438#define DOCUMENT_ONLY_EVENTEVENT EVENT
1439#define NON_IDL_EVENT EVENT
1440#include "mozilla/EventNameList.inc"
1441#undef WINDOW_ONLY_EVENT
1442#undef NON_IDL_EVENT
1443#undef EVENT
1444 {nullptr}};
1445
1446 sAtomEventTable =
1447 new nsTHashMap<RefPtr<nsAtom>, EventNameMapping>(std::size(eventArray));
1448 sStringEventTable =
1449 new nsTHashMap<nsStringHashKey, EventNameMapping>(std::size(eventArray));
1450 sUserDefinedEvents = new nsTArray<RefPtr<nsAtom>>(64);
1451
1452 // Subtract one from the length because of the trailing null
1453 for (uint32_t i = 0; i < std::size(eventArray) - 1; ++i) {
1454 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", 1455
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sAtomEventTable->Contains(eventArray[i].mAtom)"
") (" "Double-defining event name; fix your EventNameList.inc"
")"); do { MOZ_CrashSequence(__null, 1455); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1455 "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", 1455
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sAtomEventTable->Contains(eventArray[i].mAtom)"
") (" "Double-defining event name; fix your EventNameList.inc"
")"); do { MOZ_CrashSequence(__null, 1455); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1456 sAtomEventTable->InsertOrUpdate(eventArray[i].mAtom, eventArray[i]);
1457 sStringEventTable->InsertOrUpdate(
1458 Substring(nsDependentAtomString(eventArray[i].mAtom), 2),
1459 eventArray[i]);
1460 }
1461
1462 return true;
1463}
1464
1465void nsContentUtils::InitializeTouchEventTable() {
1466 static bool sEventTableInitialized = false;
1467 if (!sEventTableInitialized && sAtomEventTable && sStringEventTable) {
1468 sEventTableInitialized = true;
1469 static const EventNameMapping touchEventArray[] = {
1470#define EVENT(name_, _message, _type, _class)
1471#define TOUCH_EVENT(name_, _message, _type, _class) \
1472 {nsGkAtoms::on##name_, _type, _message, _class},
1473#include "mozilla/EventNameList.inc"
1474#undef TOUCH_EVENT
1475#undef EVENT
1476 {nullptr}};
1477 // Subtract one from the length because of the trailing null
1478 for (uint32_t i = 0; i < std::size(touchEventArray) - 1; ++i) {
1479 sAtomEventTable->InsertOrUpdate(touchEventArray[i].mAtom,
1480 touchEventArray[i]);
1481 sStringEventTable->InsertOrUpdate(
1482 Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2),
1483 touchEventArray[i]);
1484 }
1485 }
1486}
1487
1488static bool Is8bit(const nsAString& aString) {
1489 static const char16_t EIGHT_BIT = char16_t(~0x00FF);
1490
1491 for (nsAString::const_char_iterator start = aString.BeginReading(),
1492 end = aString.EndReading();
1493 start != end; ++start) {
1494 if (*start & EIGHT_BIT) {
1495 return false;
1496 }
1497 }
1498
1499 return true;
1500}
1501
1502nsresult nsContentUtils::Btoa(const nsAString& aBinaryData,
1503 nsAString& aAsciiBase64String) {
1504 if (!Is8bit(aBinaryData)) {
1505 aAsciiBase64String.Truncate();
1506 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1507 }
1508
1509 return Base64Encode(aBinaryData, aAsciiBase64String);
1510}
1511
1512nsresult nsContentUtils::Atob(const nsAString& aAsciiBase64String,
1513 nsAString& aBinaryData) {
1514 if (!Is8bit(aAsciiBase64String)) {
1515 aBinaryData.Truncate();
1516 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1517 }
1518
1519 const char16_t* start = aAsciiBase64String.BeginReading();
1520 const char16_t* cur = start;
1521 const char16_t* end = aAsciiBase64String.EndReading();
1522 bool hasWhitespace = false;
1523
1524 while (cur < end) {
1525 if (nsContentUtils::IsHTMLWhitespace(*cur)) {
1526 hasWhitespace = true;
1527 break;
1528 }
1529 cur++;
1530 }
1531
1532 nsresult rv;
1533
1534 if (hasWhitespace) {
1535 nsString trimmedString;
1536
1537 if (!trimmedString.SetCapacity(aAsciiBase64String.Length(), fallible)) {
1538 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1539 }
1540
1541 trimmedString.Append(start, cur - start);
1542
1543 while (cur < end) {
1544 if (!nsContentUtils::IsHTMLWhitespace(*cur)) {
1545 trimmedString.Append(*cur);
1546 }
1547 cur++;
1548 }
1549 rv = Base64Decode(trimmedString, aBinaryData);
1550 } else {
1551 rv = Base64Decode(aAsciiBase64String, aBinaryData);
1552 }
1553
1554 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && rv == NS_ERROR_INVALID_ARG) {
1555 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1556 }
1557 return rv;
1558}
1559
1560bool nsContentUtils::IsAutocompleteEnabled(mozilla::dom::Element* aElement) {
1561 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", 1561
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ") (" "aElement should not be null!"
")"); do { MOZ_CrashSequence(__null, 1561); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1562
1563 nsAutoString autocomplete;
1564
1565 if (auto* input = HTMLInputElement::FromNodeOrNull(aElement)) {
1566 input->GetAutocomplete(autocomplete);
1567 } else if (auto* textarea = HTMLTextAreaElement::FromNodeOrNull(aElement)) {
1568 textarea->GetAutocomplete(autocomplete);
1569 }
1570
1571 if (autocomplete.IsEmpty()) {
1572 auto* control = nsGenericHTMLFormControlElement::FromNode(aElement);
1573 auto* form = control->GetFormInternal();
1574 if (!form) {
1575 return true;
1576 }
1577
1578 form->GetAutocomplete(autocomplete);
1579 }
1580
1581 return !autocomplete.EqualsLiteral("off");
1582}
1583
1584nsContentUtils::AutocompleteAttrState
1585nsContentUtils::SerializeAutocompleteAttribute(
1586 const nsAttrValue* aAttr, nsAString& aResult,
1587 AutocompleteAttrState aCachedState) {
1588 if (!aAttr ||
1589 aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) {
1590 return aCachedState;
1591 }
1592
1593 if (aCachedState == nsContentUtils::eAutocompleteAttrState_Valid) {
1594 uint32_t atomCount = aAttr->GetAtomCount();
1595 for (uint32_t i = 0; i < atomCount; i++) {
1596 if (i != 0) {
1597 aResult.Append(' ');
1598 }
1599 aResult.Append(nsDependentAtomString(aAttr->AtomAt(i)));
1600 }
1601 nsContentUtils::ASCIIToLower(aResult);
1602 return aCachedState;
1603 }
1604
1605 aResult.Truncate();
1606
1607 mozilla::dom::AutocompleteInfo info;
1608 AutocompleteAttrState state =
1609 InternalSerializeAutocompleteAttribute(aAttr, info);
1610 if (state == eAutocompleteAttrState_Valid) {
1611 // Concatenate the info fields.
1612 aResult = info.mSection;
1613
1614 if (!info.mAddressType.IsEmpty()) {
1615 if (!aResult.IsEmpty()) {
1616 aResult += ' ';
1617 }
1618 aResult += info.mAddressType;
1619 }
1620
1621 if (!info.mContactType.IsEmpty()) {
1622 if (!aResult.IsEmpty()) {
1623 aResult += ' ';
1624 }
1625 aResult += info.mContactType;
1626 }
1627
1628 if (!info.mFieldName.IsEmpty()) {
1629 if (!aResult.IsEmpty()) {
1630 aResult += ' ';
1631 }
1632 aResult += info.mFieldName;
1633 }
1634
1635 // The autocomplete attribute value "webauthn" is interpreted as both a
1636 // field name and a credential type. The corresponding IDL-exposed autofill
1637 // value is "webauthn", not "webauthn webauthn".
1638 if (!info.mCredentialType.IsEmpty() &&
1639 !(info.mCredentialType.Equals(u"webauthn"_ns) &&
1640 info.mCredentialType.Equals(aResult))) {
1641 if (!aResult.IsEmpty()) {
1642 aResult += ' ';
1643 }
1644 aResult += info.mCredentialType;
1645 }
1646 }
1647
1648 return state;
1649}
1650
1651nsContentUtils::AutocompleteAttrState
1652nsContentUtils::SerializeAutocompleteAttribute(
1653 const nsAttrValue* aAttr, mozilla::dom::AutocompleteInfo& aInfo,
1654 AutocompleteAttrState aCachedState, bool aGrantAllValidValue) {
1655 if (!aAttr ||
1656 aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) {
1657 return aCachedState;
1658 }
1659
1660 return InternalSerializeAutocompleteAttribute(aAttr, aInfo,
1661 aGrantAllValidValue);
1662}
1663
1664/**
1665 * Helper to validate the @autocomplete tokens.
1666 *
1667 * @return {AutocompleteAttrState} The state of the attribute (invalid/valid).
1668 */
1669nsContentUtils::AutocompleteAttrState
1670nsContentUtils::InternalSerializeAutocompleteAttribute(
1671 const nsAttrValue* aAttrVal, mozilla::dom::AutocompleteInfo& aInfo,
1672 bool aGrantAllValidValue) {
1673 // No autocomplete attribute so we are done
1674 if (!aAttrVal) {
1675 return eAutocompleteAttrState_Invalid;
1676 }
1677
1678 uint32_t numTokens = aAttrVal->GetAtomCount();
1679 if (!numTokens || numTokens > INT32_MAX(2147483647)) {
1680 return eAutocompleteAttrState_Invalid;
1681 }
1682
1683 uint32_t index = numTokens - 1;
1684 nsString tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1685 AutocompleteCategory category;
1686 nsAttrValue enumValue;
1687 nsAutoString credentialTypeStr;
1688
1689 bool result = enumValue.ParseEnumValue(
1690 tokenString, kAutocompleteCredentialTypeTable, false);
1691 if (result) {
1692 if (!enumValue.Equals(u"webauthn"_ns, eIgnoreCase) || numTokens > 5) {
1693 return eAutocompleteAttrState_Invalid;
1694 }
1695 enumValue.ToString(credentialTypeStr);
1696 ASCIIToLower(credentialTypeStr);
1697 // category is Credential and the indexth token is "webauthn"
1698 if (index == 0) {
1699 aInfo.mFieldName.Assign(credentialTypeStr);
1700 aInfo.mCredentialType.Assign(credentialTypeStr);
1701 return eAutocompleteAttrState_Valid;
1702 }
1703
1704 --index;
1705 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1706
1707 // Only the Normal and Contact categories are allowed with webauthn
1708 // - disallow Credential
1709 if (enumValue.ParseEnumValue(tokenString, kAutocompleteCredentialTypeTable,
1710 false)) {
1711 return eAutocompleteAttrState_Invalid;
1712 }
1713 // - disallow Off and Automatic
1714 if (enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable,
1715 false)) {
1716 if (enumValue.Equals(u"off"_ns, eIgnoreCase) ||
1717 enumValue.Equals(u"on"_ns, eIgnoreCase)) {
1718 return eAutocompleteAttrState_Invalid;
1719 }
1720 }
1721
1722 // Proceed to process the remaining tokens as if "webauthn" was not present.
1723 // We need to decrement numTokens to enforce the correct per-category limits
1724 // on the maximum number of tokens.
1725 --numTokens;
1726 }
1727
1728 bool unsupported = false;
1729 if (!aGrantAllValidValue) {
1730 unsupported = enumValue.ParseEnumValue(
1731 tokenString, kAutocompleteUnsupportedFieldNameTable, false);
1732 if (unsupported) {
1733 return eAutocompleteAttrState_Invalid;
1734 }
1735 }
1736
1737 nsAutoString fieldNameStr;
1738 result =
1739 enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable, false);
1740
1741 if (result) {
1742 // Off/Automatic/Normal categories.
1743 if (enumValue.Equals(u"off"_ns, eIgnoreCase) ||
1744 enumValue.Equals(u"on"_ns, eIgnoreCase)) {
1745 if (numTokens > 1) {
1746 return eAutocompleteAttrState_Invalid;
1747 }
1748 enumValue.ToString(fieldNameStr);
1749 ASCIIToLower(fieldNameStr);
1750 aInfo.mFieldName.Assign(fieldNameStr);
1751 aInfo.mCredentialType.Assign(credentialTypeStr);
1752 aInfo.mCanAutomaticallyPersist =
1753 !enumValue.Equals(u"off"_ns, eIgnoreCase);
1754 return eAutocompleteAttrState_Valid;
1755 }
1756
1757 // Only allow on/off if form autofill @autocomplete values aren't enabled
1758 // and it doesn't grant all valid values.
1759 if (!StaticPrefs::dom_forms_autocomplete_formautofill() &&
1760 !aGrantAllValidValue) {
1761 return eAutocompleteAttrState_Invalid;
1762 }
1763
1764 // Normal category
1765 if (numTokens > 3) {
1766 return eAutocompleteAttrState_Invalid;
1767 }
1768 category = eAutocompleteCategory_NORMAL;
1769 } else { // Check if the last token is of the contact category instead.
1770 // Only allow on/off if form autofill @autocomplete values aren't enabled
1771 // and it doesn't grant all valid values.
1772 if (!StaticPrefs::dom_forms_autocomplete_formautofill() &&
1773 !aGrantAllValidValue) {
1774 return eAutocompleteAttrState_Invalid;
1775 }
1776
1777 result = enumValue.ParseEnumValue(
1778 tokenString, kAutocompleteContactFieldNameTable, false);
1779 if (!result || numTokens > 4) {
1780 return eAutocompleteAttrState_Invalid;
1781 }
1782
1783 category = eAutocompleteCategory_CONTACT;
1784 }
1785
1786 enumValue.ToString(fieldNameStr);
1787 ASCIIToLower(fieldNameStr);
1788
1789 aInfo.mFieldName.Assign(fieldNameStr);
1790 aInfo.mCredentialType.Assign(credentialTypeStr);
1791 aInfo.mCanAutomaticallyPersist = !enumValue.ParseEnumValue(
1792 tokenString, kAutocompleteNoPersistFieldNameTable, false);
1793
1794 // We are done if this was the only token.
1795 if (numTokens == 1) {
1796 return eAutocompleteAttrState_Valid;
1797 }
1798
1799 --index;
1800 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1801
1802 if (category == eAutocompleteCategory_CONTACT) {
1803 if (!aGrantAllValidValue) {
1804 unsupported = enumValue.ParseEnumValue(
1805 tokenString, kAutocompleteUnsupportedContactFieldHintTable, false);
1806 if (unsupported) {
1807 return eAutocompleteAttrState_Invalid;
1808 }
1809 }
1810
1811 nsAttrValue contactFieldHint;
1812 result = contactFieldHint.ParseEnumValue(
1813 tokenString, kAutocompleteContactFieldHintTable, false);
1814 if (result) {
1815 nsAutoString contactFieldHintString;
1816 contactFieldHint.ToString(contactFieldHintString);
1817 ASCIIToLower(contactFieldHintString);
1818 aInfo.mContactType.Assign(contactFieldHintString);
1819 if (index == 0) {
1820 return eAutocompleteAttrState_Valid;
1821 }
1822 --index;
1823 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1824 }
1825 }
1826
1827 // Check for billing/shipping tokens
1828 nsAttrValue fieldHint;
1829 if (fieldHint.ParseEnumValue(tokenString, kAutocompleteFieldHintTable,
1830 false)) {
1831 nsString fieldHintString;
1832 fieldHint.ToString(fieldHintString);
1833 ASCIIToLower(fieldHintString);
1834 aInfo.mAddressType.Assign(fieldHintString);
1835 if (index == 0) {
1836 return eAutocompleteAttrState_Valid;
1837 }
1838 --index;
1839 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1840 }
1841
1842 // Check for section-* token
1843 const nsDependentSubstring& section = Substring(tokenString, 0, 8);
1844 if (section.LowerCaseEqualsASCII("section-")) {
1845 ASCIIToLower(tokenString);
1846 aInfo.mSection.Assign(tokenString);
1847 if (index == 0) {
1848 return eAutocompleteAttrState_Valid;
1849 }
1850 }
1851
1852 // Clear the fields as the autocomplete attribute is invalid.
1853 aInfo.mSection.Truncate();
1854 aInfo.mAddressType.Truncate();
1855 aInfo.mContactType.Truncate();
1856 aInfo.mFieldName.Truncate();
1857 aInfo.mCredentialType.Truncate();
1858
1859 return eAutocompleteAttrState_Invalid;
1860}
1861
1862// Parse an integer according to HTML spec
1863template <class CharT>
1864int32_t nsContentUtils::ParseHTMLIntegerImpl(
1865 const CharT* aStart, const CharT* aEnd,
1866 ParseHTMLIntegerResultFlags* aResult) {
1867 int result = eParseHTMLInteger_NoFlags;
1868
1869 const CharT* iter = aStart;
1870
1871 while (iter != aEnd && nsContentUtils::IsHTMLWhitespace(*iter)) {
1872 result |= eParseHTMLInteger_NonStandard;
1873 ++iter;
1874 }
1875
1876 if (iter == aEnd) {
1877 result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
1878 *aResult = (ParseHTMLIntegerResultFlags)result;
1879 return 0;
1880 }
1881
1882 int sign = 1;
1883 if (*iter == CharT('-')) {
1884 sign = -1;
1885 result |= eParseHTMLInteger_Negative;
1886 ++iter;
1887 } else if (*iter == CharT('+')) {
1888 result |= eParseHTMLInteger_NonStandard;
1889 ++iter;
1890 }
1891
1892 bool foundValue = false;
1893 CheckedInt32 value = 0;
1894
1895 // Check for leading zeros first.
1896 uint64_t leadingZeros = 0;
1897 while (iter != aEnd) {
1898 if (*iter != CharT('0')) {
1899 break;
1900 }
1901
1902 ++leadingZeros;
1903 foundValue = true;
1904 ++iter;
1905 }
1906
1907 while (iter != aEnd) {
1908 if (*iter >= CharT('0') && *iter <= CharT('9')) {
1909 value = (value * 10) + (*iter - CharT('0')) * sign;
1910 ++iter;
1911 if (!value.isValid()) {
1912 result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorOverflow;
1913 break;
1914 }
1915 foundValue = true;
1916 } else {
1917 break;
1918 }
1919 }
1920
1921 if (!foundValue) {
1922 result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
1923 }
1924
1925 if (value.isValid() &&
1926 ((leadingZeros > 1 || (leadingZeros == 1 && !(value == 0))) ||
1927 (sign == -1 && value == 0))) {
1928 result |= eParseHTMLInteger_NonStandard;
1929 }
1930
1931 if (iter != aEnd) {
1932 result |= eParseHTMLInteger_DidNotConsumeAllInput;
1933 }
1934
1935 *aResult = (ParseHTMLIntegerResultFlags)result;
1936 return value.isValid() ? value.value() : 0;
1937}
1938
1939// Parse an integer according to HTML spec
1940int32_t nsContentUtils::ParseHTMLInteger(const char16_t* aStart,
1941 const char16_t* aEnd,
1942 ParseHTMLIntegerResultFlags* aResult) {
1943 return ParseHTMLIntegerImpl(aStart, aEnd, aResult);
1944}
1945
1946int32_t nsContentUtils::ParseHTMLInteger(const char* aStart, const char* aEnd,
1947 ParseHTMLIntegerResultFlags* aResult) {
1948 return ParseHTMLIntegerImpl(aStart, aEnd, aResult);
1949}
1950
1951Maybe<double> nsContentUtils::ParseHTMLFloatingPointNumber(
1952 const nsAString& aString) {
1953 // Check if it is a valid floating-point number first since the result of
1954 // nsString.ToDouble() is more lenient than the spec,
1955 // https://html.spec.whatwg.org/#valid-floating-point-number
1956 nsAString::const_iterator iter, end;
1957 aString.BeginReading(iter);
1958 aString.EndReading(end);
1959
1960 if (iter == end) {
1961 return {};
1962 }
1963
1964 if (*iter == char16_t('-') && ++iter == end) {
1965 return {};
1966 }
1967
1968 if (IsAsciiDigit(*iter)) {
1969 for (; iter != end && IsAsciiDigit(*iter); ++iter);
1970 } else if (*iter == char16_t('.')) {
1971 // Do nothing, jumps to fraction part
1972 } else {
1973 return {};
1974 }
1975
1976 // Fraction
1977 if (*iter == char16_t('.')) {
1978 ++iter;
1979 if (iter == end || !IsAsciiDigit(*iter)) {
1980 // U+002E FULL STOP character (.) must be followed by one or more ASCII
1981 // digits
1982 return {};
1983 }
1984
1985 for (; iter != end && IsAsciiDigit(*iter); ++iter);
1986 }
1987
1988 if (iter != end && (*iter == char16_t('e') || *iter == char16_t('E'))) {
1989 ++iter;
1990 if (*iter == char16_t('-') || *iter == char16_t('+')) {
1991 ++iter;
1992 }
1993
1994 if (iter == end || !IsAsciiDigit(*iter)) {
1995 // Should have one or more ASCII digits
1996 return {};
1997 }
1998
1999 for (; iter != end && IsAsciiDigit(*iter); ++iter);
2000 }
2001
2002 if (iter != end) {
2003 return {};
2004 }
2005
2006 nsresult rv;
2007 double result = PromiseFlatStringTPromiseFlatString<char16_t>(aString).ToDouble(&rv);
2008 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2009 return {};
2010 }
2011 return Some(result);
2012}
2013
2014#define SKIP_WHITESPACE(iter, end_iter, end_res)while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(
iter))) { ++(iter); } if ((iter) == (end_iter)) { return (end_res
); }
\
2015 while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \
2016 ++(iter); \
2017 } \
2018 if ((iter) == (end_iter)) { \
2019 return (end_res); \
2020 }
2021
2022#define SKIP_ATTR_NAME(iter, end_iter)while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*
(iter)) && *(iter) != '=') { ++(iter); }
\
2023 while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*(iter)) && \
2024 *(iter) != '=') { \
2025 ++(iter); \
2026 }
2027
2028bool nsContentUtils::GetPseudoAttributeValue(const nsString& aSource,
2029 nsAtom* aName, nsAString& aValue) {
2030 aValue.Truncate();
2031
2032 const char16_t* start = aSource.get();
2033 const char16_t* end = start + aSource.Length();
2034 const char16_t* iter;
2035
2036 while (start != end) {
2037 SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start
))) { ++(start); } if ((start) == (end)) { return (false); }
2038 iter = start;
2039 SKIP_ATTR_NAME(iter, end)while ((iter) != (end) && !nsCRT::IsAsciiSpace(*(iter
)) && *(iter) != '=') { ++(iter); }
2040
2041 if (start == iter) {
2042 return false;
2043 }
2044
2045 // Remember the attr name.
2046 const nsDependentSubstring& attrName = Substring(start, iter);
2047
2048 // Now check whether this is a valid name="value" pair.
2049 start = iter;
2050 SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start
))) { ++(start); } if ((start) == (end)) { return (false); }
2051 if (*start != '=') {
2052 // No '=', so this is not a name="value" pair. We don't know
2053 // what it is, and we have no way to handle it.
2054 return false;
2055 }
2056
2057 // Have to skip the value.
2058 ++start;
2059 SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start
))) { ++(start); } if ((start) == (end)) { return (false); }
2060 char16_t q = *start;
2061 if (q != kQuote && q != kApostrophe) {
2062 // Not a valid quoted value, so bail.
2063 return false;
2064 }
2065
2066 ++start; // Point to the first char of the value.
2067 iter = start;
2068
2069 while (iter != end && *iter != q) {
2070 ++iter;
2071 }
2072
2073 if (iter == end) {
2074 // Oops, unterminated quoted string.
2075 return false;
2076 }
2077
2078 // At this point attrName holds the name of the "attribute" and
2079 // the value is between start and iter.
2080
2081 if (aName->Equals(attrName)) {
2082 // We'll accumulate as many characters as possible (until we hit either
2083 // the end of the string or the beginning of an entity). Chunks will be
2084 // delimited by start and chunkEnd.
2085 const char16_t* chunkEnd = start;
2086 while (chunkEnd != iter) {
2087 if (*chunkEnd == kLessThan) {
2088 aValue.Truncate();
2089
2090 return false;
2091 }
2092
2093 if (*chunkEnd == kAmpersand) {
2094 aValue.Append(start, chunkEnd - start);
2095
2096 const char16_t* afterEntity = nullptr;
2097 char16_t result[2];
2098 uint32_t count = MOZ_XMLTranslateEntity(
2099 reinterpret_cast<const char*>(chunkEnd),
2100 reinterpret_cast<const char*>(iter),
2101 reinterpret_cast<const char**>(&afterEntity), result);
2102 if (count == 0) {
2103 aValue.Truncate();
2104
2105 return false;
2106 }
2107
2108 aValue.Append(result, count);
2109
2110 // Advance to after the entity and begin a new chunk.
2111 start = chunkEnd = afterEntity;
2112 } else {
2113 ++chunkEnd;
2114 }
2115 }
2116
2117 // Append remainder.
2118 aValue.Append(start, iter - start);
2119
2120 return true;
2121 }
2122
2123 // Resume scanning after the end of the attribute value (past the quote
2124 // char).
2125 start = iter + 1;
2126 }
2127
2128 return false;
2129}
2130
2131bool nsContentUtils::IsJavaScriptLanguage(const nsString& aName) {
2132 // Create MIME type as "text/" + given input
2133 nsAutoString mimeType(u"text/");
2134 mimeType.Append(aName);
2135
2136 return IsJavascriptMIMEType(mimeType);
2137}
2138
2139void nsContentUtils::SplitMimeType(const nsAString& aValue, nsString& aType,
2140 nsString& aParams) {
2141 aType.Truncate();
2142 aParams.Truncate();
2143 int32_t semiIndex = aValue.FindChar(char16_t(';'));
2144 if (-1 != semiIndex) {
2145 aType = Substring(aValue, 0, semiIndex);
2146 aParams =
2147 Substring(aValue, semiIndex + 1, aValue.Length() - (semiIndex + 1));
2148 aParams.StripWhitespace();
2149 } else {
2150 aType = aValue;
2151 }
2152 aType.StripWhitespace();
2153}
2154
2155/**
2156 * A helper function that parses a sandbox attribute (of an <iframe> or a CSP
2157 * directive) and converts it to the set of flags used internally.
2158 *
2159 * @param aSandboxAttr the sandbox attribute
2160 * @return the set of flags (SANDBOXED_NONE if aSandboxAttr is
2161 * null)
2162 */
2163uint32_t nsContentUtils::ParseSandboxAttributeToFlags(
2164 const nsAttrValue* aSandboxAttr) {
2165 if (!aSandboxAttr) {
2166 return SANDBOXED_NONE;
2167 }
2168
2169 uint32_t out = SANDBOX_ALL_FLAGS;
2170
2171#define SANDBOX_KEYWORD(string, atom, flags) \
2172 if (aSandboxAttr->Contains(nsGkAtoms::atom, eIgnoreCase)) { \
2173 out &= ~(flags); \
2174 }
2175#include "IframeSandboxKeywordList.inc"
2176#undef SANDBOX_KEYWORD
2177
2178 return out;
2179}
2180
2181/**
2182 * A helper function that checks if a string matches a valid sandbox flag.
2183 *
2184 * @param aFlag the potential sandbox flag.
2185 * @return true if the flag is a sandbox flag.
2186 */
2187bool nsContentUtils::IsValidSandboxFlag(const nsAString& aFlag) {
2188#define SANDBOX_KEYWORD(string, atom, flags) \
2189 if (EqualsIgnoreASCIICase(nsDependentAtomString(nsGkAtoms::atom), aFlag)) { \
2190 return true; \
2191 }
2192#include "IframeSandboxKeywordList.inc"
2193#undef SANDBOX_KEYWORD
2194 return false;
2195}
2196
2197/**
2198 * A helper function that returns a string attribute corresponding to the
2199 * sandbox flags.
2200 *
2201 * @param aFlags the sandbox flags
2202 * @param aString the attribute corresponding to the flags (null if aFlags
2203 * is zero)
2204 */
2205void nsContentUtils::SandboxFlagsToString(uint32_t aFlags, nsAString& aString) {
2206 if (!aFlags) {
2207 SetDOMStringToNull(aString);
2208 return;
2209 }
2210
2211 aString.Truncate();
2212
2213#define SANDBOX_KEYWORD(string, atom, flags) \
2214 if (!(aFlags & (flags))) { \
2215 if (!aString.IsEmpty()) { \
2216 aString.AppendLiteral(u" "); \
2217 } \
2218 aString.Append(nsDependentAtomString(nsGkAtoms::atom)); \
2219 }
2220#include "IframeSandboxKeywordList.inc"
2221#undef SANDBOX_KEYWORD
2222}
2223
2224nsIBidiKeyboard* nsContentUtils::GetBidiKeyboard() {
2225 if (!sBidiKeyboard) {
2226 sBidiKeyboard = nsIWidget::CreateBidiKeyboard();
2227 }
2228 return sBidiKeyboard;
2229}
2230
2231// static
2232bool nsContentUtils::IsAlphanumeric(uint32_t aChar) {
2233 nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);
2234
2235 return (cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber);
2236}
2237
2238// static
2239bool nsContentUtils::IsAlphanumericOrSymbol(uint32_t aChar) {
2240 nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);
2241
2242 return cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber ||
2243 cat == nsUGenCategory::kSymbol;
2244}
2245
2246// static
2247bool nsContentUtils::IsHyphen(uint32_t aChar) {
2248 // Characters treated as hyphens for the purpose of "emergency" breaking
2249 // when the content would otherwise overflow.
2250 return aChar == uint32_t('-') || // HYPHEN-MINUS
2251 aChar == 0x2010 || // HYPHEN
2252 aChar == 0x2012 || // FIGURE DASH
2253 aChar == 0x2013 || // EN DASH
2254 aChar == 0x058A; // ARMENIAN HYPHEN
2255}
2256
2257/* static */
2258bool nsContentUtils::IsHTMLWhitespace(char16_t aChar) {
2259 return aChar == char16_t(0x0009) || aChar == char16_t(0x000A) ||
2260 aChar == char16_t(0x000C) || aChar == char16_t(0x000D) ||
2261 aChar == char16_t(0x0020);
2262}
2263
2264/* static */
2265bool nsContentUtils::IsHTMLWhitespaceOrNBSP(char16_t aChar) {
2266 return IsHTMLWhitespace(aChar) || aChar == char16_t(0xA0);
2267}
2268
2269/* static */
2270bool nsContentUtils::IsHTMLBlockLevelElement(nsIContent* aContent) {
2271 return aContent->IsAnyOfHTMLElements(
2272 nsGkAtoms::address, nsGkAtoms::article, nsGkAtoms::aside,
2273 nsGkAtoms::blockquote, nsGkAtoms::center, nsGkAtoms::dir, nsGkAtoms::div,
2274 nsGkAtoms::dl, // XXX why not dt and dd?
2275 nsGkAtoms::fieldset,
2276 nsGkAtoms::figure, // XXX shouldn't figcaption be on this list
2277 nsGkAtoms::footer, nsGkAtoms::form, nsGkAtoms::h1, nsGkAtoms::h2,
2278 nsGkAtoms::h3, nsGkAtoms::h4, nsGkAtoms::h5, nsGkAtoms::h6,
2279 nsGkAtoms::header, nsGkAtoms::hgroup, nsGkAtoms::hr, nsGkAtoms::li,
2280 nsGkAtoms::listing, nsGkAtoms::menu, nsGkAtoms::nav, nsGkAtoms::ol,
2281 nsGkAtoms::p, nsGkAtoms::pre, nsGkAtoms::section, nsGkAtoms::table,
2282 nsGkAtoms::ul, nsGkAtoms::xmp);
2283}
2284
2285// static
2286int32_t nsContentUtils::ParseLegacyFontSize(const nsAString& aValue) {
2287 nsAString::const_iterator iter, end;
2288 aValue.BeginReading(iter);
2289 aValue.EndReading(end);
2290
2291 while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
2292 ++iter;
2293 }
2294
2295 if (iter == end) {
2296 return 0;
2297 }
2298
2299 bool relative = false;
2300 bool negate = false;
2301 if (*iter == char16_t('-')) {
2302 relative = true;
2303 negate = true;
2304 ++iter;
2305 } else if (*iter == char16_t('+')) {
2306 relative = true;
2307 ++iter;
2308 }
2309
2310 if (iter == end || *iter < char16_t('0') || *iter > char16_t('9')) {
2311 return 0;
2312 }
2313
2314 // We don't have to worry about overflow, since we can bail out as soon as
2315 // we're bigger than 7.
2316 int32_t value = 0;
2317 while (iter != end && *iter >= char16_t('0') && *iter <= char16_t('9')) {
2318 value = 10 * value + (*iter - char16_t('0'));
2319 if (value >= 7) {
2320 break;
2321 }
2322 ++iter;
2323 }
2324
2325 if (relative) {
2326 if (negate) {
2327 value = 3 - value;
2328 } else {
2329 value = 3 + value;
2330 }
2331 }
2332
2333 return std::clamp(value, 1, 7);
2334}
2335
2336/* static */
2337void nsContentUtils::GetOfflineAppManifest(Document* aDocument, nsIURI** aURI) {
2338 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", 2338); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2338); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2339 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"
, 2339); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { MOZ_CrashSequence(__null, 2339); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2340 *aURI = nullptr;
2341
2342 if (aDocument->GetController().isSome()) {
2343 return;
2344 }
2345
2346 Element* docElement = aDocument->GetRootElement();
2347 if (!docElement) {
2348 return;
2349 }
2350
2351 nsAutoString manifestSpec;
2352 docElement->GetAttr(nsGkAtoms::manifest, manifestSpec);
2353
2354 // Manifest URIs can't have fragment identifiers.
2355 if (manifestSpec.IsEmpty() || manifestSpec.Contains('#')) {
2356 return;
2357 }
2358
2359 nsContentUtils::NewURIWithDocumentCharset(aURI, manifestSpec, aDocument,
2360 aDocument->GetDocBaseURI());
2361}
2362
2363/* static */
2364bool nsContentUtils::OfflineAppAllowed(nsIURI* aURI) { return false; }
2365
2366/* static */
2367bool nsContentUtils::OfflineAppAllowed(nsIPrincipal* aPrincipal) {
2368 return false;
2369}
2370// Static
2371bool nsContentUtils::IsErrorPage(nsIURI* aURI) {
2372 if (!aURI) {
2373 return false;
2374 }
2375
2376 if (!aURI->SchemeIs("about")) {
2377 return false;
2378 }
2379
2380 nsAutoCString name;
2381 nsresult rv = NS_GetAboutModuleName(aURI, name);
2382 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"
, 2382); return false; } } while (false)
;
2383
2384 return name.EqualsLiteral("certerror") || name.EqualsLiteral("neterror") ||
2385 name.EqualsLiteral("blocked");
2386}
2387
2388// static
2389void nsContentUtils::Shutdown() {
2390 sInitialized = false;
2391
2392 nsHTMLTags::ReleaseTable();
2393
2394 NS_IF_RELEASE(sContentPolicyService)do { if (sContentPolicyService) { (sContentPolicyService)->
Release(); (sContentPolicyService) = 0; } } while (0)
;
2395 sTriedToGetContentPolicy = false;
2396 for (StaticRefPtr<nsIStringBundle>& bundle : sStringBundles) {
2397 bundle = nullptr;
2398 }
2399
2400 NS_IF_RELEASE(sStringBundleService)do { if (sStringBundleService) { (sStringBundleService)->Release
(); (sStringBundleService) = 0; } } while (0)
;
2401 NS_IF_RELEASE(sConsoleService)do { if (sConsoleService) { (sConsoleService)->Release(); (
sConsoleService) = 0; } } while (0)
;
2402 NS_IF_RELEASE(sXPConnect)do { if (sXPConnect) { (sXPConnect)->Release(); (sXPConnect
) = 0; } } while (0)
;
2403 NS_IF_RELEASE(sSecurityManager)do { if (sSecurityManager) { (sSecurityManager)->Release()
; (sSecurityManager) = 0; } } while (0)
;
2404 NS_IF_RELEASE(sSystemPrincipal)do { if (sSystemPrincipal) { (sSystemPrincipal)->Release()
; (sSystemPrincipal) = 0; } } while (0)
;
2405 NS_IF_RELEASE(sNullSubjectPrincipal)do { if (sNullSubjectPrincipal) { (sNullSubjectPrincipal)->
Release(); (sNullSubjectPrincipal) = 0; } } while (0)
;
2406 NS_IF_RELEASE(sFingerprintingProtectionPrincipal)do { if (sFingerprintingProtectionPrincipal) { (sFingerprintingProtectionPrincipal
)->Release(); (sFingerprintingProtectionPrincipal) = 0; } }
while (0)
;
2407
2408 sBidiKeyboard = nullptr;
2409
2410 delete sAtomEventTable;
2411 sAtomEventTable = nullptr;
2412 delete sStringEventTable;
2413 sStringEventTable = nullptr;
2414 delete sUserDefinedEvents;
2415 sUserDefinedEvents = nullptr;
2416
2417 // Managers left in the list remove themselves from it when they're deleted,
2418 // which can happen after this point.
2419 NS_ASSERTION(sNodeEventListenerManagers.isEmpty(),do { if (!(sNodeEventListenerManagers.isEmpty())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Node event listener manager list not empty at shutdown!"
, "sNodeEventListenerManagers.isEmpty()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 2420); MOZ_PretendNoReturn(); } } while (0)
2420 "Node event listener manager list not empty at shutdown!")do { if (!(sNodeEventListenerManagers.isEmpty())) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "Node event listener manager list not empty at shutdown!"
, "sNodeEventListenerManagers.isEmpty()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 2420); MOZ_PretendNoReturn(); } } while (0)
;
2421
2422 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", 2422); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sDOMArenaHashtable->Count() == 0" ")");
do { MOZ_CrashSequence(__null, 2422); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2423 delete sDOMArenaHashtable;
2424 sDOMArenaHashtable = nullptr;
2425
2426 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", 2427); MOZ_PretendNoReturn
(); } } while (0)
2427 "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", 2427); MOZ_PretendNoReturn
(); } } while (0)
;
2428 delete sBlockedScriptRunners;
2429 sBlockedScriptRunners = nullptr;
2430
2431 delete sShiftText;
2432 sShiftText = nullptr;
2433 delete sControlText;
2434 sControlText = nullptr;
2435 delete sCommandOrWinText;
2436 sCommandOrWinText = nullptr;
2437 delete sAltText;
2438 sAltText = nullptr;
2439 delete sModifierSeparator;
2440 sModifierSeparator = nullptr;
2441
2442 delete sJSScriptBytecodeMimeType;
2443 sJSScriptBytecodeMimeType = nullptr;
2444
2445 delete sJSModuleBytecodeMimeType;
2446 sJSModuleBytecodeMimeType = nullptr;
2447
2448 NS_IF_RELEASE(sSameOriginChecker)do { if (sSameOriginChecker) { (sSameOriginChecker)->Release
(); (sSameOriginChecker) = 0; } } while (0)
;
2449
2450 if (sUserInteractionObserver) {
2451 sUserInteractionObserver->Shutdown();
2452 NS_RELEASE(sUserInteractionObserver)do { (sUserInteractionObserver)->Release(); (sUserInteractionObserver
) = 0; } while (0)
;
2453 }
2454
2455 for (const auto& pref : kRfpPrefs) {
2456 Preferences::UnregisterCallback(RecomputeResistFingerprintingAllDocs, pref);
2457 }
2458
2459 TextControlState::Shutdown();
2460}
2461
2462/**
2463 * Checks whether two nodes come from the same origin. aTrustedNode is
2464 * considered 'safe' in that a user can operate on it.
2465 */
2466// static
2467nsresult nsContentUtils::CheckSameOrigin(const nsINode* aTrustedNode,
2468 const nsINode* unTrustedNode) {
2469 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"
, 2469); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTrustedNode"
")"); do { MOZ_CrashSequence(__null, 2469); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2470 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", 2470); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "unTrustedNode" ")"); do { MOZ_CrashSequence
(__null, 2470); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2471
2472 /*
2473 * Get hold of each node's principal
2474 */
2475
2476 nsIPrincipal* trustedPrincipal = aTrustedNode->NodePrincipal();
2477 nsIPrincipal* unTrustedPrincipal = unTrustedNode->NodePrincipal();
2478
2479 if (trustedPrincipal == unTrustedPrincipal) {
2480 return NS_OK;
2481 }
2482
2483 bool equal;
2484 // XXXbz should we actually have a Subsumes() check here instead? Or perhaps
2485 // a separate method for that, with callers using one or the other?
2486 if (NS_FAILED(trustedPrincipal->Equals(unTrustedPrincipal, &equal))((bool)(__builtin_expect(!!(NS_FAILED_impl(trustedPrincipal->
Equals(unTrustedPrincipal, &equal))), 0)))
||
2487 !equal) {
2488 return NS_ERROR_DOM_PROP_ACCESS_DENIED;
2489 }
2490
2491 return NS_OK;
2492}
2493
2494// static
2495bool nsContentUtils::CanCallerAccess(nsIPrincipal* aSubjectPrincipal,
2496 nsIPrincipal* aPrincipal) {
2497 bool subsumes;
2498 nsresult rv = aSubjectPrincipal->Subsumes(aPrincipal, &subsumes);
2499 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"
, 2499); return false; } } while (false)
;
2500
2501 if (subsumes) {
2502 return true;
2503 }
2504
2505 // The subject doesn't subsume aPrincipal. Allow access only if the subject
2506 // is chrome.
2507 return IsCallerChrome();
2508}
2509
2510// static
2511bool nsContentUtils::CanCallerAccess(const nsINode* aNode) {
2512 nsIPrincipal* subject = SubjectPrincipal();
2513 if (subject->IsSystemPrincipal()) {
2514 return true;
2515 }
2516
2517 if (aNode->ChromeOnlyAccess()) {
2518 return false;
2519 }
2520
2521 return CanCallerAccess(subject, aNode->NodePrincipal());
2522}
2523
2524// static
2525bool nsContentUtils::CanCallerAccess(nsPIDOMWindowInner* aWindow) {
2526 nsCOMPtr<nsIScriptObjectPrincipal> scriptObject = do_QueryInterface(aWindow);
2527 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",
2527); return false; } } while (false)
;
2528
2529 return CanCallerAccess(SubjectPrincipal(), scriptObject->GetPrincipal());
2530}
2531
2532// static
2533bool nsContentUtils::PrincipalHasPermission(nsIPrincipal& aPrincipal,
2534 const nsAtom* aPerm) {
2535 // Chrome gets access by default.
2536 if (aPrincipal.IsSystemPrincipal()) {
2537 return true;
2538 }
2539
2540 // Otherwise, only allow if caller is an addon with the permission.
2541 return BasePrincipal::Cast(aPrincipal).AddonHasPermission(aPerm);
2542}
2543
2544// static
2545bool nsContentUtils::CallerHasPermission(JSContext* aCx, const nsAtom* aPerm) {
2546 return PrincipalHasPermission(*SubjectPrincipal(aCx), aPerm);
2547}
2548
2549// static
2550nsIPrincipal* nsContentUtils::GetAttrTriggeringPrincipal(
2551 nsIContent* aContent, const nsAString& aAttrValue,
2552 nsIPrincipal* aSubjectPrincipal) {
2553 nsIPrincipal* contentPrin = aContent ? aContent->NodePrincipal() : nullptr;
2554
2555 // If the subject principal is the same as the content principal, or no
2556 // explicit subject principal was provided, we don't need to do any further
2557 // checks. Just return the content principal.
2558 if (contentPrin == aSubjectPrincipal || !aSubjectPrincipal) {
2559 return contentPrin;
2560 }
2561
2562 // Only use the subject principal if the URL string we are going to end up
2563 // fetching is under the control of that principal, which is never the case
2564 // for relative URLs.
2565 if (aAttrValue.IsEmpty() ||
2566 !IsAbsoluteURL(NS_ConvertUTF16toUTF8(aAttrValue))) {
2567 return contentPrin;
2568 }
2569
2570 // Only use the subject principal as the attr triggering principal if it
2571 // should override the CSP of the node's principal.
2572 if (BasePrincipal::Cast(aSubjectPrincipal)->OverridesCSP(contentPrin)) {
2573 return aSubjectPrincipal;
2574 }
2575
2576 return contentPrin;
2577}
2578
2579// static
2580bool nsContentUtils::CanNavigate(mozilla::dom::BrowsingContext* aSource,
2581 mozilla::dom::BrowsingContext* aTarget,
2582 nsIPrincipal* aDocumentPrincipal,
2583 bool aConsiderOpener) {
2584 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", 2586
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aSource->Group() == aTarget->Group()"
") (" "Source and target BrowsingContexts must be in the same group"
")"); do { MOZ_CrashSequence(__null, 2586); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2585 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", 2586
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aSource->Group() == aTarget->Group()"
") (" "Source and target BrowsingContexts must be in the same group"
")"); do { MOZ_CrashSequence(__null, 2586); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2586 "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", 2586
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aSource->Group() == aTarget->Group()"
") (" "Source and target BrowsingContexts must be in the same group"
")"); do { MOZ_CrashSequence(__null, 2586); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2587 if (aSource->Group() != aTarget->Group()) {
2588 return false;
2589 }
2590
2591 auto isFileScheme = [](nsIPrincipal* aPrincipal) -> bool {
2592 // NOTE: This code previously checked for a file scheme using
2593 // `nsIPrincipal::GetURI()` combined with `NS_GetInnermostURI`. We no longer
2594 // use GetURI, as it has been deprecated, and it makes more sense to take
2595 // advantage of the pre-computed origin, which will already use the
2596 // innermost URI (bug 1810619)
2597 nsAutoCString origin, scheme;
2598 return NS_SUCCEEDED(aPrincipal->GetOriginNoSuffix(origin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->GetOriginNoSuffix
(origin))), 1)))
&&
2599 NS_SUCCEEDED(net_ExtractURLScheme(origin, scheme))((bool)(__builtin_expect(!!(!NS_FAILED_impl(net_ExtractURLScheme
(origin, scheme))), 1)))
&&
2600 scheme == "file"_ns;
2601 };
2602
2603 // A frame can navigate itself and its own root.
2604 if (aTarget == aSource || aTarget == aSource->Top()) {
2605 return true;
2606 }
2607
2608 // If the target frame doesn't yet have a WindowContext, start checking
2609 // principals from its direct ancestor instead. It would inherit its principal
2610 // from this document upon creation.
2611 dom::WindowContext* initialWc = aTarget->GetCurrentWindowContext();
2612 if (!initialWc) {
2613 initialWc = aTarget->GetParentWindowContext();
2614 }
2615
2616 // A frame can navigate any frame with a same-origin ancestor.
2617 bool isFileDocument = isFileScheme(aDocumentPrincipal);
2618 for (dom::WindowContext* wc = initialWc; wc;
2619 wc = wc->GetParentWindowContext()) {
2620 nsIPrincipal* documentPrincipal = nullptr;
2621 if (XRE_IsParentProcess()) {
2622 dom::WindowGlobalParent* wgp = wc->Canonical();
2623 if (!wgp) {
2624 continue;
2625 }
2626 documentPrincipal = wgp->DocumentPrincipal();
2627 } else {
2628 dom::WindowGlobalChild* wgc = wc->GetWindowGlobalChild();
2629 if (!wgc) {
2630 continue; // not same-origin.
2631 }
2632 documentPrincipal = wgc->DocumentPrincipal();
2633 }
2634
2635 if (aDocumentPrincipal->Equals(documentPrincipal)) {
2636 return true;
2637 }
2638
2639 // Not strictly equal, special case if both are file: URIs.
2640 //
2641 // file: URIs are considered the same domain for the purpose of frame
2642 // navigation, regardless of script accessibility (bug 420425).
2643 if (isFileDocument && isFileScheme(documentPrincipal)) {
2644 return true;
2645 }
2646 }
2647
2648 // If the target is a top-level document, a frame can navigate it
2649 // when the source is allowed to navigate the opener
2650 if (aConsiderOpener && !aTarget->GetParent()) {
2651 if (RefPtr<dom::BrowsingContext> opener = aTarget->GetOpener()) {
2652 return CanNavigate(aSource, opener, aDocumentPrincipal, false);
2653 }
2654 }
2655
2656 return false;
2657}
2658
2659// static
2660bool nsContentUtils::IsAbsoluteURL(const nsACString& aURL) {
2661 nsAutoCString scheme;
2662 if (NS_FAILED(net_ExtractURLScheme(aURL, scheme))((bool)(__builtin_expect(!!(NS_FAILED_impl(net_ExtractURLScheme
(aURL, scheme))), 0)))
) {
2663 // If we can't extract a scheme, it's not an absolute URL.
2664 return false;
2665 }
2666
2667 // If it parses as an absolute StandardURL, it's definitely an absolute URL,
2668 // so no need to check with the IO service.
2669 if (net_IsAbsoluteURL(aURL)) {
2670 return true;
2671 }
2672
2673 nsresult rv = NS_OK;
2674 nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service(&rv);
2675 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"
, 2675); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2675); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2676 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2677 return false;
2678 }
2679
2680 uint32_t flags;
2681 if (NS_SUCCEEDED(io->GetProtocolFlags(scheme.get(), &flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(io->GetProtocolFlags
(scheme.get(), &flags))), 1)))
) {
2682 return flags & nsIProtocolHandler::URI_NORELATIVE;
2683 }
2684
2685 return false;
2686}
2687
2688// static
2689bool nsContentUtils::InProlog(nsINode* aNode) {
2690 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", 2690
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode" ") (" "missing node to nsContentUtils::InProlog"
")"); do { MOZ_CrashSequence(__null, 2690); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2691
2692 nsINode* parent = aNode->GetParentNode();
2693 if (!parent || !parent->IsDocument()) {
2694 return false;
2695 }
2696
2697 const Document* doc = parent->AsDocument();
2698 const nsIContent* root = doc->GetRootElement();
2699 if (!root) {
2700 return true;
2701 }
2702 const Maybe<uint32_t> indexOfNode = doc->ComputeIndexOf(aNode);
2703 const Maybe<uint32_t> indexOfRoot = doc->ComputeIndexOf(root);
2704 if (MOZ_LIKELY(indexOfNode.isSome() && indexOfRoot.isSome())(__builtin_expect(!!(indexOfNode.isSome() && indexOfRoot
.isSome()), 1))
) {
2705 return *indexOfNode < *indexOfRoot;
2706 }
2707 // XXX Keep the odd traditional behavior for now.
2708 return indexOfNode.isNothing() && indexOfRoot.isSome();
2709}
2710
2711bool nsContentUtils::IsCallerChrome() {
2712 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", 2712); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2712); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2713 return SubjectPrincipal() == sSystemPrincipal;
2714}
2715
2716#ifdef FUZZING
2717bool nsContentUtils::IsFuzzingEnabled() {
2718 return StaticPrefs::fuzzing_enabled();
2719}
2720#endif
2721
2722/* static */
2723bool nsContentUtils::IsCallerChromeOrElementTransformGettersEnabled(
2724 JSContext* aCx, JSObject*) {
2725 return ThreadsafeIsSystemCaller(aCx) ||
2726 StaticPrefs::dom_element_transform_getters_enabled();
2727}
2728
2729// Older Should RFP Functions ----------------------------------
2730
2731/* static */
2732bool nsContentUtils::ShouldResistFingerprinting(bool aIsPrivateMode,
2733 RFPTarget aTarget) {
2734 return nsRFPService::IsRFPEnabledFor(aIsPrivateMode, aTarget, Nothing());
2735}
2736
2737/* static */
2738bool nsContentUtils::ShouldResistFingerprinting(nsIGlobalObject* aGlobalObject,
2739 RFPTarget aTarget) {
2740 if (!aGlobalObject) {
2741 return ShouldResistFingerprinting("Null Object", aTarget);
2742 }
2743 return aGlobalObject->ShouldResistFingerprinting(aTarget);
2744}
2745
2746// Newer Should RFP Functions ----------------------------------
2747// Utilities ---------------------------------------------------
2748
2749inline void LogDomainAndList(const char* urlType, nsAutoCString& list,
2750 nsAutoCString& url, bool isExemptDomain) {
2751 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)
2752 ("%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)
2753 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)
2754 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)
;
2755}
2756
2757inline already_AddRefed<nsICookieJarSettings> GetCookieJarSettings(
2758 nsILoadInfo* aLoadInfo) {
2759 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
2760 nsresult rv =
2761 aLoadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings));
2762 if (rv == NS_ERROR_NOT_IMPLEMENTED) {
2763 // The TRRLoadInfo in particular does not implement this method
2764 // In that instance. We will return false and let other code decide if
2765 // we shouldRFP for this connection
2766 return nullptr;
2767 }
2768 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"
, 2768)
) {
2769 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)
2770 ("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)
2771 "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)
;
2772 return nullptr;
2773 }
2774
2775 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", 2775); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "cookieJarSettings" ")"); do { MOZ_CrashSequence
(__null, 2775); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2776 return cookieJarSettings.forget();
2777}
2778
2779bool nsContentUtils::ETPSaysShouldNotResistFingerprinting(
2780 nsICookieJarSettings* aCookieJarSettings, bool aIsPBM) {
2781 // A positive return from this function should always be obeyed.
2782 // A negative return means we should keep checking things.
2783
2784 // We do not want this check to apply to RFP, only to FPP.
2785 if (nsRFPService::IsRFPPrefEnabled(aIsPBM)) {
2786 // In RFP, never use the ETP toggle to exempt.
2787 // We can safely return false here even if we are not in PBM mode
2788 // and RFP_pbmode is enabled because we will later see that and
2789 // return false from the ShouldRFP function entirely.
2790 return false;
2791 }
2792
2793 return ContentBlockingAllowList::Check(aCookieJarSettings);
2794}
2795
2796bool nsContentUtils::ETPSaysShouldNotResistFingerprinting(
2797 nsIChannel* aChannel, nsILoadInfo* aLoadInfo) {
2798 bool isPBM = NS_UsePrivateBrowsing(aChannel);
2799
2800 nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
2801 GetCookieJarSettings(aLoadInfo);
2802 if (!cookieJarSettings) {
2803 return false;
2804 }
2805
2806 return ETPSaysShouldNotResistFingerprinting(cookieJarSettings, isPBM);
2807}
2808
2809inline bool CookieJarSettingsSaysShouldResistFingerprinting(
2810 nsILoadInfo* aLoadInfo) {
2811 // A positive return from this function should always be obeyed.
2812 // A negative return means we should keep checking things.
2813
2814 nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
2815 GetCookieJarSettings(aLoadInfo);
2816 if (!cookieJarSettings) {
2817 return false;
2818 }
2819 return cookieJarSettings->GetShouldResistFingerprinting();
2820}
2821
2822inline bool SchemeSaysShouldNotResistFingerprinting(nsIURI* aURI) {
2823 return aURI->SchemeIs("chrome") || aURI->SchemeIs("resource") ||
2824 aURI->SchemeIs("view-source") || aURI->SchemeIs("moz-extension") ||
2825 (aURI->SchemeIs("about") && !NS_IsContentAccessibleAboutURI(aURI));
2826}
2827
2828inline bool SchemeSaysShouldNotResistFingerprinting(nsIPrincipal* aPrincipal) {
2829 if (aPrincipal->SchemeIs("chrome") || aPrincipal->SchemeIs("resource") ||
2830 aPrincipal->SchemeIs("view-source") ||
2831 aPrincipal->SchemeIs("moz-extension")) {
2832 return true;
2833 }
2834
2835 if (!aPrincipal->SchemeIs("about")) {
2836 return false;
2837 }
2838
2839 bool isContentAccessibleAboutURI;
2840 (void)aPrincipal->IsContentAccessibleAboutURI(&isContentAccessibleAboutURI);
2841 return !isContentAccessibleAboutURI;
2842}
2843
2844// mFirstPartyDomain and mPartitionKey are serialized either as a bare host
2845// ("example.com") or in site format ("(https,example.com[,port][,f])"),
2846// depending on privacy.firstparty.isolate.use_site and
2847// privacy.dynamic_firstparty.use_site respectively. Those two prefs are
2848// independent, and ParsePartitionKey() only consults the latter, so detect the
2849// format here instead of letting it decide for a first-party domain.
2850inline void TopLevelInfoToBaseDomain(const nsAString& aInfo,
2851 nsAString& aBaseDomain) {
2852 if (aInfo.IsEmpty() || aInfo.First() != '(') {
2853 aBaseDomain = aInfo;
2854 return;
2855 }
2856
2857 nsAutoString scheme;
2858 int32_t port;
2859 bool foreignByAncestorContext;
2860 if (!OriginAttributes::ParsePartitionKey(aInfo, scheme, aBaseDomain, port,
2861 foreignByAncestorContext)) {
2862 aBaseDomain.Truncate();
2863 }
2864}
2865
2866inline bool PartionKeyIsAlsoExempted(
2867 const mozilla::OriginAttributes& aOriginAttributes) {
2868 // If we've gotten here we have (probably) passed the CookieJarSettings
2869 // check that would tell us that if we _are_ a subdocument, then we are on
2870 // an exempted top-level domain and we should see if we ourselves are
2871 // exempted. But we may have gotten here because we directly called the
2872 // _dangerous function and we haven't done that check, but we _were_
2873 // instatiated from a state where we could have been partitioned.
2874 // So perform this last-ditch check for that scenario.
2875 // We arbitrarily use https as the scheme, but it doesn't matter.
2876 nsAutoString baseDomain;
2877 if (StaticPrefs::privacy_firstparty_isolate() &&
2878 !aOriginAttributes.mFirstPartyDomain.IsEmpty()) {
2879 TopLevelInfoToBaseDomain(aOriginAttributes.mFirstPartyDomain, baseDomain);
2880 } else if (!aOriginAttributes.mPartitionKey.IsEmpty()) {
2881 TopLevelInfoToBaseDomain(aOriginAttributes.mPartitionKey, baseDomain);
2882 }
2883
2884 nsresult rv = NS_ERROR_NOT_INITIALIZED;
2885 nsCOMPtr<nsIURI> uri;
2886 if (!baseDomain.IsEmpty()) {
2887 rv = NS_NewURI(getter_AddRefs(uri), u"https://"_ns + baseDomain);
2888 }
2889
2890 if (!NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2891 nsAutoCString list;
2892 nsRFPService::GetExemptedDomainsLowercase(list);
2893 bool isExemptPartitionKey = nsContentUtils::IsURIInList(uri, list);
2894 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
2895 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
2896 nsAutoCString url;
2897 uri->GetHost(url);
2898 LogDomainAndList("Partition Key", list, url, isExemptPartitionKey);
2899 }
2900 return isExemptPartitionKey;
2901 }
2902 return true;
2903}
2904
2905// Functions ---------------------------------------------------
2906
2907/* static */
2908bool nsContentUtils::ShouldResistFingerprinting(const char* aJustification,
2909 RFPTarget aTarget) {
2910 // See comment in header file for information about usage
2911 // We hardcode PBM to true to be the more restrictive option.
2912 return nsContentUtils::ShouldResistFingerprinting(true, aTarget);
2913}
2914
2915namespace {
2916
2917// This function is only called within this file for Positive Return Checks
2918bool ShouldResistFingerprinting_(const char* aJustification,
2919 bool aIsPrivateMode, RFPTarget aTarget) {
2920 // See comment in header file for information about usage
2921 return nsContentUtils::ShouldResistFingerprinting(aIsPrivateMode, aTarget);
2922}
2923
2924} // namespace
2925
2926/* static */
2927bool nsContentUtils::ShouldResistFingerprinting(CallerType aCallerType,
2928 nsIGlobalObject* aGlobalObject,
2929 RFPTarget aTarget) {
2930 if (aCallerType == CallerType::System) {
2931 return false;
2932 }
2933 return ShouldResistFingerprinting(aGlobalObject, aTarget);
2934}
2935
2936/* static */
2937bool nsContentUtils::ShouldResistFingerprinting(nsIDocShell* aDocShell,
2938 RFPTarget aTarget) {
2939 if (!aDocShell) {
2940 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)
2941 ("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)
2942 "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)
;
2943 return ShouldResistFingerprinting("Null Object", aTarget);
2944 }
2945 return ShouldResistFingerprinting(aDocShell->GetDocument(), aTarget);
2946}
2947
2948/* static */
2949bool nsContentUtils::ShouldResistFingerprinting(const Document* aDocument,
2950 RFPTarget aTarget) {
2951 if (!aDocument) {
2952 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)
2953 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)
2954 ("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)
2955 "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)
;
2956 return ShouldResistFingerprinting("Null Object", aTarget);
2957 }
2958 return aDocument->ShouldResistFingerprinting(aTarget);
2959}
2960
2961/* static */
2962bool nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel,
2963 RFPTarget aTarget) {
2964 if (!aChannel) {
2965 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)
2966 ("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)
2967 "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)
;
2968 return ShouldResistFingerprinting("Null Object", aTarget);
2969 }
2970
2971 bool isPBM = NS_UsePrivateBrowsing(aChannel);
2972
2973 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
2974 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
2975 nsCOMPtr<nsIURI> channelURI;
2976 (void)NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
2977 nsAutoCString channelSpec;
2978 channelURI->GetSpec(channelSpec);
2979 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)
2980 ("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)
2981 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)
;
2982 }
2983
2984 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
2985 if (!loadInfo) {
2986 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)
2987 ("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)
2988 "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)
;
2989 return ShouldResistFingerprinting("Null Object", aTarget);
2990 }
2991
2992 // With this check, we can ensure that the prefs and target say yes, so only
2993 // an exemption would cause us to return false.
2994 if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) {
2995 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)
2996 ("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)
2997 " 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)
2998 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)
;
2999 return false;
3000 }
3001
3002 auto contentType = loadInfo->GetExternalContentPolicyType();
3003
3004 if (sSecurityManager && (contentType == ExtContentPolicy::TYPE_DOCUMENT ||
3005 contentType == ExtContentPolicy::TYPE_SUBDOCUMENT)) {
3006 nsCOMPtr<nsIPrincipal> resultPrincipal;
3007 nsresult rv = sSecurityManager->GetChannelResultPrincipal(
3008 aChannel, getter_AddRefs(resultPrincipal));
3009 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && IsPDFJS(resultPrincipal)) {
3010 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)
3011 ("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)
3012 " 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)
;
3013 return false;
3014 }
3015 }
3016
3017 if (ETPSaysShouldNotResistFingerprinting(aChannel, loadInfo)) {
3018 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)
3019 ("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)
3020 " 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)
;
3021 return false;
3022 }
3023
3024 if (CookieJarSettingsSaysShouldResistFingerprinting(loadInfo)) {
3025 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)
3026 ("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)
3027 " 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)
;
3028 return true;
3029 }
3030
3031 // Document types have no loading principal. Subdocument types do have a
3032 // loading principal, but it is the loading principal of the parent
3033 // document; not the subdocument.
3034 // Case 1: Document or Subdocument load
3035 if (contentType == ExtContentPolicy::TYPE_DOCUMENT ||
3036 contentType == ExtContentPolicy::TYPE_SUBDOCUMENT) {
3037 nsCOMPtr<nsIURI> channelURI;
3038 nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
3039 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", 3042
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { MOZ_CrashSequence(__null, 3042); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3040 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", 3042
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { MOZ_CrashSequence(__null, 3042); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3041 "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", 3042
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { MOZ_CrashSequence(__null, 3042); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3042 "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", 3042
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { MOZ_CrashSequence(__null, 3042); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3043 // this check is to ensure that we do not crash in non-debug builds.
3044 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3045 return true;
3046 }
3047
3048 nsAutoCString loadingPrincipalSpec;
3049 nsAutoCString channelSpec;
3050 channelURI->GetSpec(channelSpec);
3051
3052 if (contentType == ExtContentPolicy::TYPE_SUBDOCUMENT) {
3053 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)
3054 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)
3055 ("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)
3056 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)
3057 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)
3058 ? 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)
3059 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)
;
3060 } else {
3061 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)
3062 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)
3063 ("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)
3064 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)
3065 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)
3066 ? 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)
3067 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)
;
3068 }
3069
3070 return ShouldResistFingerprinting_dangerous(
3071 channelURI, loadInfo->GetOriginAttributes(), "Internal Call", aTarget);
3072 }
3073
3074 // Case 2: Subresource Load
3075 // Because this code is only used for subresource loads, this
3076 // will check the parent's principal
3077 nsIPrincipal* principal = loadInfo->GetLoadingPrincipal();
3078
3079 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", 3082); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { MOZ_CrashSequence(__null, 3082); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3080 !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", 3082); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { MOZ_CrashSequence(__null, 3082); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3081 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", 3082); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { MOZ_CrashSequence(__null, 3082); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3082 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", 3082); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { MOZ_CrashSequence(__null, 3082); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3083 return ShouldResistFingerprinting_dangerous(principal, "Internal Call",
3084 aTarget);
3085}
3086
3087/* static */
3088bool nsContentUtils::ShouldResistFingerprinting_dangerous(
3089 nsIURI* aURI, const mozilla::OriginAttributes& aOriginAttributes,
3090 const char* aJustification, RFPTarget aTarget) {
3091 // With this check, we can ensure that the prefs and target say yes, so only
3092 // an exemption would cause us to return false.
3093 bool isPBM = aOriginAttributes.IsPrivateBrowsing();
3094
3095 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)
3096 ("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)
3097 " 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)
3098 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)
;
3099
3100 if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) {
3101 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)
3102 ("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)
3103 " 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)
3104 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)
;
3105 return false;
3106 }
3107
3108 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)
3109 ("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)
3110 " 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)
3111 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)
;
3112
3113 // Exclude internal schemes and web extensions
3114 if (SchemeSaysShouldNotResistFingerprinting(aURI)) {
3115 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)
3116 ("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)
3117 " 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)
;
3118 return false;
3119 }
3120
3121 bool isExemptDomain = false;
3122 nsAutoCString list;
3123 nsRFPService::GetExemptedDomainsLowercase(list);
3124 isExemptDomain = IsURIInList(aURI, list);
3125
3126 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
3127 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
3128 nsAutoCString url;
3129 aURI->GetHost(url);
3130 LogDomainAndList("URI", list, url, isExemptDomain);
3131 }
3132
3133 if (isExemptDomain) {
3134 isExemptDomain &= PartionKeyIsAlsoExempted(aOriginAttributes);
3135 }
3136
3137 return !isExemptDomain;
3138}
3139
3140/* static */
3141bool nsContentUtils::ShouldResistFingerprinting_dangerous(
3142 nsIPrincipal* aPrincipal, const char* aJustification, RFPTarget aTarget) {
3143 if (!aPrincipal) {
3144 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)
3145 ("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)
3146 "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)
;
3147 return ShouldResistFingerprinting("Null object", aTarget);
3148 }
3149
3150 const auto& originAttributes =
3151 BasePrincipal::Cast(aPrincipal)->OriginAttributesRef();
3152 // With this check, we can ensure that the prefs and target say yes, so only
3153 // an exemption would cause us to return false.
3154 bool isPBM = originAttributes.IsPrivateBrowsing();
3155
3156 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
3157 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
3158 nsAutoCString origin;
3159 aPrincipal->GetOrigin(origin);
3160 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)
3161 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)
3162 ("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)
3163 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)
;
3164 }
3165
3166 if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) {
3167 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)
3168 ("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)
3169 "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)
3170 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)
;
3171 return false;
3172 }
3173
3174 if (aPrincipal->IsSystemPrincipal()) {
3175 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)
3176 ("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)
3177 "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)
;
3178 return false;
3179 }
3180
3181 // Exclude internal schemes and web extensions
3182 if (SchemeSaysShouldNotResistFingerprinting(aPrincipal)) {
3183 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)
3184 ("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)
3185 " 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)
;
3186 return false;
3187 }
3188
3189 // Web extension principals are also excluded
3190 if (BasePrincipal::Cast(aPrincipal)->AddonPolicyCore()) {
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*)" " and AddonPolicy said false"
); } } while (0)
3192 ("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)
3193 " 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)
;
3194 return false;
3195 }
3196
3197 bool isExemptDomain = false;
3198 nsAutoCString list;
3199 nsRFPService::GetExemptedDomainsLowercase(list);
3200 aPrincipal->IsURIInList(list, &isExemptDomain);
3201
3202 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
3203 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
3204 nsAutoCString origin;
3205 aPrincipal->GetOrigin(origin);
3206 LogDomainAndList("URI", list, origin, isExemptDomain);
3207 }
3208
3209 if (isExemptDomain) {
3210 isExemptDomain &= PartionKeyIsAlsoExempted(originAttributes);
3211 }
3212
3213 return !isExemptDomain;
3214}
3215
3216// --------------------------------------------------------------------
3217
3218/* static */
3219void nsContentUtils::CalcRoundedWindowSizeForResistingFingerprinting(
3220 int32_t aChromeWidth, int32_t aChromeHeight, int32_t aScreenWidth,
3221 int32_t aScreenHeight, int32_t aInputWidth, int32_t aInputHeight,
3222 bool aSetOuterWidth, bool aSetOuterHeight, int32_t* aOutputWidth,
3223 int32_t* aOutputHeight) {
3224 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"
, 3224); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOutputWidth"
")"); do { MOZ_CrashSequence(__null, 3224); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3225 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", 3225); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aOutputHeight" ")"); do { MOZ_CrashSequence
(__null, 3225); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3226
3227 int32_t availContentWidth = 0;
3228 int32_t availContentHeight = 0;
3229
3230 availContentWidth = std::min(StaticPrefs::privacy_window_maxInnerWidth(),
3231 aScreenWidth - aChromeWidth);
3232#ifdef MOZ_WIDGET_GTK1
3233 // In the GTK window, it will not report outside system decorations
3234 // when we get available window size, see Bug 581863. So, we leave a
3235 // 40 pixels space for them when calculating the available content
3236 // height. It is not necessary for the width since the content width
3237 // is usually pretty much the same as the chrome width.
3238 availContentHeight = std::min(StaticPrefs::privacy_window_maxInnerHeight(),
3239 (-40 + aScreenHeight) - aChromeHeight);
3240#else
3241 availContentHeight = std::min(StaticPrefs::privacy_window_maxInnerHeight(),
3242 aScreenHeight - aChromeHeight);
3243#endif
3244
3245 // Ideally, we'd like to round window size to 1000x1000, but the
3246 // screen space could be too small to accommodate this size in some
3247 // cases. If it happens, we would round the window size to the nearest
3248 // 200x100.
3249 availContentWidth = availContentWidth - (availContentWidth % 200);
3250 availContentHeight = availContentHeight - (availContentHeight % 100);
3251
3252 // If aIsOuter is true, we are setting the outer window. So we
3253 // have to consider the chrome UI.
3254 int32_t chromeOffsetWidth = aSetOuterWidth ? aChromeWidth : 0;
3255 int32_t chromeOffsetHeight = aSetOuterHeight ? aChromeHeight : 0;
3256 int32_t resultWidth = 0, resultHeight = 0;
3257
3258 // if the original size is greater than the maximum available size, we set
3259 // it to the maximum size. And if the original value is less than the
3260 // minimum rounded size, we set it to the minimum 200x100.
3261 if (aInputWidth > (availContentWidth + chromeOffsetWidth)) {
3262 resultWidth = availContentWidth + chromeOffsetWidth;
3263 } else if (aInputWidth < (200 + chromeOffsetWidth)) {
3264 resultWidth = 200 + chromeOffsetWidth;
3265 } else {
3266 // Otherwise, we round the window to the nearest upper rounded 200x100.
3267 resultWidth = NSToIntCeil((aInputWidth - chromeOffsetWidth) / 200.0) * 200 +
3268 chromeOffsetWidth;
3269 }
3270
3271 if (aInputHeight > (availContentHeight + chromeOffsetHeight)) {
3272 resultHeight = availContentHeight + chromeOffsetHeight;
3273 } else if (aInputHeight < (100 + chromeOffsetHeight)) {
3274 resultHeight = 100 + chromeOffsetHeight;
3275 } else {
3276 resultHeight =
3277 NSToIntCeil((aInputHeight - chromeOffsetHeight) / 100.0) * 100 +
3278 chromeOffsetHeight;
3279 }
3280
3281 *aOutputWidth = resultWidth;
3282 *aOutputHeight = resultHeight;
3283}
3284
3285bool nsContentUtils::ThreadsafeIsCallerChrome() {
3286 return NS_IsMainThread() ? IsCallerChrome()
3287 : IsCurrentThreadRunningChromeWorker();
3288}
3289
3290bool nsContentUtils::IsCallerUAWidget() {
3291 JSContext* cx = GetCurrentJSContext();
3292 if (!cx) {
3293 return false;
3294 }
3295
3296 JS::Realm* realm = JS::GetCurrentRealmOrNull(cx);
3297 if (!realm) {
3298 return false;
3299 }
3300
3301 return xpc::IsUAWidgetScope(realm);
3302}
3303
3304bool nsContentUtils::IsSystemCaller(JSContext* aCx) {
3305 // Note that SubjectPrincipal() assumes we are in a compartment here.
3306 return SubjectPrincipal(aCx) == sSystemPrincipal;
3307}
3308
3309bool nsContentUtils::ThreadsafeIsSystemCaller(JSContext* aCx) {
3310 CycleCollectedJSContext* ccjscx = CycleCollectedJSContext::Get();
3311 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", 3311); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ccjscx->Context() == aCx" ")"); do { MOZ_CrashSequence
(__null, 3311); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3312
3313 return ccjscx->IsSystemCaller();
3314}
3315
3316// static
3317bool nsContentUtils::LookupBindingMember(
3318 JSContext* aCx, nsIContent* aContent, JS::Handle<jsid> aId,
3319 JS::MutableHandle<JS::PropertyDescriptor> aDesc) {
3320 return true;
3321}
3322
3323nsINode* nsContentUtils::GetNearestInProcessCrossDocParentNode(
3324 nsINode* aChild) {
3325 if (aChild->IsDocument()) {
3326 for (BrowsingContext* bc = aChild->AsDocument()->GetBrowsingContext(); bc;
3327 bc = bc->GetParent()) {
3328 if (bc->GetEmbedderElement()) {
3329 return bc->GetEmbedderElement();
3330 }
3331 }
3332 return nullptr;
3333 }
3334
3335 nsINode* parent = aChild->GetParentNode();
3336 if (parent && parent->IsContent() && aChild->IsContent()) {
3337 parent = aChild->AsContent()->GetFlattenedTreeParent();
3338 }
3339
3340 return parent;
3341}
3342
3343bool nsContentUtils::ContentIsHostIncludingDescendantOf(
3344 const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) {
3345 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"
, 3345); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { MOZ_CrashSequence
(__null, 3345); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3346 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"
, 3346); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { MOZ_CrashSequence
(__null, 3346); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3347
3348 while (true) {
3349 if (aPossibleDescendant == aPossibleAncestor) {
3350 return true;
3351 }
3352 if (nsINode* parent = aPossibleDescendant->GetParentNode()) {
3353 aPossibleDescendant = parent;
3354 continue;
3355 }
3356 if (auto* df = DocumentFragment::FromNode(aPossibleDescendant)) {
3357 if (nsINode* host = df->GetHost()) {
3358 aPossibleDescendant = host;
3359 continue;
3360 }
3361 }
3362 break;
3363 }
3364 return false;
3365}
3366
3367// static
3368bool nsContentUtils::ContentIsCrossDocDescendantOf(nsINode* aPossibleDescendant,
3369 nsINode* aPossibleAncestor) {
3370 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"
, 3370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { MOZ_CrashSequence
(__null, 3370); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3371 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"
, 3371); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { MOZ_CrashSequence
(__null, 3371); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3372
3373 do {
3374 if (aPossibleDescendant == aPossibleAncestor) {
3375 return true;
3376 }
3377
3378 aPossibleDescendant =
3379 GetNearestInProcessCrossDocParentNode(aPossibleDescendant);
3380 } while (aPossibleDescendant);
3381
3382 return false;
3383}
3384
3385// static
3386bool nsContentUtils::ContentIsFlattenedTreeDescendantOf(
3387 const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) {
3388 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"
, 3388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { MOZ_CrashSequence
(__null, 3388); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3389 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"
, 3389); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { MOZ_CrashSequence
(__null, 3389); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3390
3391 do {
3392 if (aPossibleDescendant == aPossibleAncestor) {
3393 return true;
3394 }
3395 aPossibleDescendant = aPossibleDescendant->GetFlattenedTreeParentNode();
3396 } while (aPossibleDescendant);
3397
3398 return false;
3399}
3400
3401// static
3402bool nsContentUtils::ContentIsFlattenedTreeDescendantOfForStyle(
3403 const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) {
3404 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"
, 3404); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { MOZ_CrashSequence
(__null, 3404); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3405 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"
, 3405); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { MOZ_CrashSequence
(__null, 3405); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3406
3407 do {
3408 if (aPossibleDescendant == aPossibleAncestor) {
3409 return true;
3410 }
3411 aPossibleDescendant =
3412 aPossibleDescendant->GetFlattenedTreeParentNodeForStyle();
3413 } while (aPossibleDescendant);
3414
3415 return false;
3416}
3417
3418// static
3419nsINode* nsContentUtils::Retarget(nsINode* aTargetA, const nsINode* aTargetB) {
3420 while (true && aTargetA) {
3421 // If A's root is not a shadow root...
3422 nsINode* root = aTargetA->SubtreeRoot();
3423 if (!root->IsShadowRoot()) {
3424 // ...then return A.
3425 return aTargetA;
3426 }
3427
3428 // or A's root is a shadow-including inclusive ancestor of B...
3429 if (aTargetB && aTargetB->IsShadowIncludingInclusiveDescendantOf(root)) {
3430 // ...then return A.
3431 return aTargetA;
3432 }
3433
3434 aTargetA = ShadowRoot::FromNode(root)->GetHost();
3435 }
3436
3437 return nullptr;
3438}
3439
3440// static
3441Element* nsContentUtils::GetAnElementForTiming(Element* aTarget,
3442 const Document* aDocument,
3443 nsIGlobalObject* aGlobal) {
3444 if (!aTarget->IsInComposedDoc()) {
3445 return nullptr;
3446 }
3447
3448 if (!aDocument) {
3449 nsCOMPtr<nsPIDOMWindowInner> inner = do_QueryInterface(aGlobal);
3450 if (!inner) {
3451 return nullptr;
3452 }
3453 aDocument = inner->GetExtantDoc();
3454 }
3455
3456 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"
, 3456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { MOZ_CrashSequence(__null, 3456); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3457
3458 if (aTarget->GetUncomposedDocOrConnectedShadowRoot() != aDocument ||
3459 !aDocument->IsCurrentActiveDocument()) {
3460 return nullptr;
3461 }
3462
3463 return aTarget;
3464}
3465
3466// static
3467nsresult nsContentUtils::GetInclusiveAncestors(nsINode* aNode,
3468 nsTArray<nsINode*>& aArray) {
3469 while (aNode) {
3470 aArray.AppendElement(aNode);
3471 aNode = aNode->GetParentNode();
3472 }
3473 return NS_OK;
3474}
3475
3476// static
3477template <typename GetParentFunc, typename ComputeChildIndexFunc>
3478nsresult static GetInclusiveAncestorsAndOffsetsHelper(
3479 nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes,
3480 nsTArray<Maybe<uint32_t>>& aAncestorOffsets, GetParentFunc aGetParentFunc,
3481 ComputeChildIndexFunc aComputeChildIndexFunc) {
3482 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", 3482); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3483
3484 if (!aNode->IsContent()) {
3485 return NS_ERROR_FAILURE;
3486 }
3487 nsIContent* content = aNode->AsContent();
3488
3489 if (!aAncestorNodes.IsEmpty()) {
3490 NS_WARNING("aAncestorNodes is not empty")NS_DebugBreak(NS_DEBUG_WARNING, "aAncestorNodes is not empty"
, nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp",
3490)
;
3491 aAncestorNodes.Clear();
3492 }
3493
3494 if (!aAncestorOffsets.IsEmpty()) {
3495 NS_WARNING("aAncestorOffsets is not empty")NS_DebugBreak(NS_DEBUG_WARNING, "aAncestorOffsets is not empty"
, nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp",
3495)
;
3496 aAncestorOffsets.Clear();
3497 }
3498
3499 // insert the node itself
3500 aAncestorNodes.AppendElement(content);
3501 aAncestorOffsets.AppendElement(Some(aOffset));
3502
3503 // insert all the ancestors
3504 nsIContent* child = content;
3505 nsIContent* parent = aGetParentFunc(child);
3506 while (parent) {
3507 aAncestorNodes.AppendElement(parent->AsContent());
3508 aAncestorOffsets.AppendElement(aComputeChildIndexFunc(parent, child));
3509 child = parent;
3510 parent = aGetParentFunc(child);
3511 }
3512
3513 return NS_OK;
3514}
3515
3516nsresult nsContentUtils::GetInclusiveAncestorsAndOffsets(
3517 nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes,
3518 nsTArray<Maybe<uint32_t>>& aAncestorOffsets) {
3519 return GetInclusiveAncestorsAndOffsetsHelper(
3520 aNode, aOffset, aAncestorNodes, aAncestorOffsets,
3521 [](nsIContent* aContent) { return aContent->GetParent(); },
3522 [](nsIContent* aParent, nsIContent* aChild) {
3523 return aParent->ComputeIndexOf(aChild);
3524 });
3525}
3526
3527nsresult nsContentUtils::GetFlattenedTreeAncestorsAndOffsetsForSelection(
3528 nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes,
3529 nsTArray<Maybe<uint32_t>>& aAncestorOffsets) {
3530 return GetInclusiveAncestorsAndOffsetsHelper(
3531 aNode, aOffset, aAncestorNodes, aAncestorOffsets,
3532 [](nsIContent* aContent) -> nsIContent* {
3533 return nsIContent::FromNodeOrNull(
3534 GetParentNodeForComparison<TreeKind::FlatForSelection>::Get(
3535 aContent));
3536 },
3537 [](nsIContent* aParent, nsIContent* aChild) {
3538 return GetParentNodeForComparison<
3539 TreeKind::FlatForSelection>::ComputeChildIndex(aParent, aChild);
3540 });
3541}
3542
3543/* static */
3544nsINode* nsContentUtils::GetCommonAncestorHelper(nsINode* aNode1,
3545 nsINode* aNode2) {
3546 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"
, 3546); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ")"
); do { MOZ_CrashSequence(__null, 3546); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3547 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"
, 3547); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ")"
); do { MOZ_CrashSequence(__null, 3547); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3548 return CommonAncestors<GetParentNode>(*aNode1, *aNode2)
3549 .GetClosestCommonAncestor();
3550}
3551
3552/* static */
3553nsINode* nsContentUtils::GetClosestCommonShadowIncludingInclusiveAncestor(
3554 nsINode* aNode1, nsINode* aNode2) {
3555 if (aNode1 == aNode2) {
3556 return aNode1;
3557 }
3558
3559 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"
, 3559); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ")"
); do { MOZ_CrashSequence(__null, 3559); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3560 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"
, 3560); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ")"
); do { MOZ_CrashSequence(__null, 3560); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3561 return CommonAncestors<GetParentOrShadowHostNode>(*aNode1, *aNode2)
3562 .GetClosestCommonAncestor();
3563}
3564
3565/* static */
3566nsIContent* nsContentUtils::GetCommonFlattenedTreeAncestorHelper(
3567 nsIContent* aContent1, nsIContent* aContent2) {
3568 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"
, 3568); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent1" ")"
); do { MOZ_CrashSequence(__null, 3568); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3569 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"
, 3569); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent2" ")"
); do { MOZ_CrashSequence(__null, 3569); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3570 return CommonAncestors<GetFlattenedTreeParent>(*aContent1, *aContent2)
3571 .GetClosestCommonAncestor();
3572}
3573
3574/* static */
3575nsINode* nsContentUtils::GetCommonFlattenedTreeAncestorForSelection(
3576 nsINode* aNode1, nsINode* aNode2) {
3577 if (aNode1 == aNode2) {
3578 return aNode1;
3579 }
3580 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"
, 3580); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ")"
); do { MOZ_CrashSequence(__null, 3580); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3581 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"
, 3581); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ")"
); do { MOZ_CrashSequence(__null, 3581); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3582 return CommonAncestors<GetFlattenedTreeParentNodeForSelection>(*aNode1,
3583 *aNode2)
3584 .GetClosestCommonAncestor();
3585}
3586
3587/* static */
3588Element* nsContentUtils::GetCommonFlattenedTreeAncestorForStyle(
3589 Element* aElement1, Element* aElement2) {
3590 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"
, 3590); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement1" ")"
); do { MOZ_CrashSequence(__null, 3590); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3591 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"
, 3591); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement2" ")"
); do { MOZ_CrashSequence(__null, 3591); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3592 return CommonAncestors<GetFlattenedTreeParentElementForStyle>(*aElement1,
3593 *aElement2)
3594 .GetClosestCommonAncestor();
3595}
3596
3597/* static */
3598template <TreeKind aKind, typename Dummy>
3599Maybe<int32_t> nsContentUtils::CompareChildNodes(
3600 const nsINode& aParent, const nsIContent* aChild1,
3601 const nsIContent* aChild2, NodeIndexCache* aIndexCache /* = nullptr */) {
3602 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", 3603); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3603); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3603 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", 3603); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3603); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3604 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", 3605); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3605); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3605 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", 3605); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3605); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3606 // See the explanation of TreeKindToCompareChildren. aParent may be computed
3607 // with TreeKind::ShadowIncludingDOM if aKind is TreeKind::DOM.
3608 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", 3612); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3612); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3609 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", 3612); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3612); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3610 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", 3612); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3612); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3611 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", 3612); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3612); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3612 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", 3612); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3612); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3613 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", 3617); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3617); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3614 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", 3617); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3617); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3615 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", 3617); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3617); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3616 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", 3617); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3617); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3617 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", 3617); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3617); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3618
3619 // FIXME: bug 1946003 and bug 1946008.
3620 if ((aChild1 && NS_WARN_IF(aChild1->IsDocumentFragment())NS_warn_if_impl(aChild1->IsDocumentFragment(), "aChild1->IsDocumentFragment()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3620)
) ||
3621 (aChild2 && NS_WARN_IF(aChild2->IsDocumentFragment())NS_warn_if_impl(aChild2->IsDocumentFragment(), "aChild2->IsDocumentFragment()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3621)
)) [[unlikely]] {
3622 return Nothing();
3623 }
3624 if (MOZ_UNLIKELY(aChild1 == aChild2)(__builtin_expect(!!(aChild1 == aChild2), 0))) {
3625 return Some(0);
3626 }
3627 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", 3627); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aChild1 || aChild2" ")"); do { MOZ_CrashSequence
(__null, 3627); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3628 // Native anonymous content (e.g. ::before/::after pseudo-elements) is not in
3629 // the regular child list, so the sibling/index fast paths below cannot order
3630 // it against regular children or the end-of-children boundary (a null child).
3631 // GetIndexInParent assigns flat-tree-consistent indices to NAC roots, so use
3632 // it to order the points instead.
3633 if (MOZ_UNLIKELY((aChild1 && aChild1->IsRootOfNativeAnonymousSubtree()) ||(__builtin_expect(!!((aChild1 && aChild1->IsRootOfNativeAnonymousSubtree
()) || (aChild2 && aChild2->IsRootOfNativeAnonymousSubtree
())), 0))
3634 (aChild2 && aChild2->IsRootOfNativeAnonymousSubtree()))(__builtin_expect(!!((aChild1 && aChild1->IsRootOfNativeAnonymousSubtree
()) || (aChild2 && aChild2->IsRootOfNativeAnonymousSubtree
())), 0))
) {
3635 const nsINode& parent =
3636 aChild1 ? *GetParentNodeForComparison<aKind>::Get(aChild1)
3637 : *GetParentNodeForComparison<aKind>::Get(aChild2);
3638 // A null child is the boundary at the end of the parent's regular child
3639 // list (offset == number of regular children). Regular children occupy
3640 // indices [0, regularCount) in the index space assigned by
3641 // GetIndexInParent, while trailing NAC (other anonymous subtrees and
3642 // ::after) start at regularCount. The discriminator here must match the
3643 // one in GetIndexInParent so the boundary lands in the same index space:
3644 // only the flat tree indexes regular children via the flattened iterator;
3645 // DOM and ShadowIncludingDOM both index them via ComputeIndexOf.
3646 const int32_t regularCount =
3647 aKind == TreeKind::Flat
3648 ? int32_t(FlattenedChildIterator::GetLength(&parent))
3649 : int32_t(parent.GetChildCount());
3650 const auto indexOf = [&](const nsIContent* aChild) -> Maybe<int32_t> {
3651 if (!aChild) {
3652 return Some(regularCount);
3653 }
3654 return aIndexCache ? aIndexCache->ComputeIndexOf<aKind>(&parent, aChild)
3655 : GetIndexInParent<aKind>(&parent, aChild);
3656 };
3657 const Maybe<int32_t> child1Index = indexOf(aChild1);
3658 const Maybe<int32_t> child2Index = indexOf(aChild2);
3659 if (MOZ_LIKELY(child1Index.isSome() && child2Index.isSome())(__builtin_expect(!!(child1Index.isSome() && child2Index
.isSome()), 1))
) {
3660 if (*child1Index != *child2Index) {
3661 return Some(*child1Index < *child2Index ? -1 : 1);
3662 }
3663 // Equal indices only happen when one child is the end-of-children
3664 // boundary (null) and the other is the first trailing NAC subtree at the
3665 // same index. The boundary precedes trailing NAC in tree order.
3666 if (!aChild1) {
3667 return Some(-1);
3668 }
3669 if (!aChild2) {
3670 return Some(1);
3671 }
3672 }
3673 // XXX Keep the odd traditional behavior for now.
3674 return Some(1);
3675 }
3676 if (!aChild1) { // i.e., end of parent vs aChild2
3677 return Some(1);
3678 }
3679 if (!aChild2) { // i.e., aChild1 vs. end of parent
3680 return Some(-1);
3681 }
3682
3683 if constexpr (aKind == TreeKind::FlatForSelection) {
3684 // If we're handling flattened tree for selection, aChild1 and/or aChild2
3685 // may be:
3686 // - fallback content of a <slot> which has some assigned nodes
3687 // - unassigned child node of a shadow host
3688 // Even though they are not part of the flattened tree, but they are also
3689 // valid for range boundaries. Therefore, we need to handle the case here.
3690 if (aParent.GetAsHTMLSlotElementIfFilledForSelection() ||
3691 aParent.GetShadowRootForSelection()) {
3692 if (aChild1->GetParentNode() == &aParent) {
3693 if (aChild2->GetParentNode() == &aParent) {
3694 // If both aChild1 and aChild2 are the fallback content or the
3695 // unassigned children of a shadow host, compare them in the DOM.
3696 return CompareChildNodes<TreeKind::DOM>(aParent, aChild1, aChild2);
3697 }
3698 // If only aChild1 is the fallback content or the unassigned child,
3699 // let's treat it as after the last assigned node.
3700 return Some(1);
3701 }
3702 if (aChild2->GetParentNode() == &aParent) {
3703 // If only aChild2 is the fallback content or the unassigned child,
3704 // let's treat it as after the last assigned node for now.
3705 return Some(-1);
3706 }
3707 }
3708 }
3709
3710 if constexpr (ShouldHandleAssignedNodesOnSlot<aKind>()) {
3711 HTMLSlotElement* const slot1 = aChild1->GetAssignedSlot<aKind>();
3712 HTMLSlotElement* const slot2 = aChild2->GetAssignedSlot<aKind>();
3713 if (slot1 || slot2) {
3714 // If they are assigned into a same <slot>, compare the index.
3715 if (slot1 == slot2) {
3716 const auto* slot = HTMLSlotElement::FromNode(aParent);
3717 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"
, 3717); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slot" ")");
do { MOZ_CrashSequence(__null, 3717); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3718
3719 constexpr auto NoIndex = size_t(-1);
3720 auto child1Index = NoIndex;
3721 auto child2Index = NoIndex;
3722 size_t index = 0;
3723 for (nsINode* node : slot->AssignedNodes()) {
3724 if (node == aChild1) {
3725 child1Index = index;
3726 if (child2Index != NoIndex) {
3727 break;
3728 }
3729 } else if (node == aChild2) {
3730 child2Index = index;
3731 if (child1Index != NoIndex) {
3732 break;
3733 }
3734 }
3735 index++;
3736 }
3737
3738 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", 3738); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "child1Index != NoIndex" ")"); do { MOZ_CrashSequence
(__null, 3738); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3739 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", 3739); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "child2Index != NoIndex" ")"); do { MOZ_CrashSequence
(__null, 3739); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3740
3741 return Some(child1Index < child2Index ? -1 : 1);
3742 }
3743 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"
, 3749)
3744 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"
, 3749)
3745 "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"
, 3749)
3746 "<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"
, 3749)
3747 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"
, 3749)
3748 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"
, 3749)
3749 .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"
, 3749)
;
3750 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"
, 3750); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!slot1" ")"
); do { MOZ_CrashSequence(__null, 3750); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3751 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"
, 3751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!slot2" ")"
); do { MOZ_CrashSequence(__null, 3751); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3752 return Nothing();
3753 }
3754 }
3755
3756 ChildIteratorBase<aKind> iter(&aParent);
3757
3758 // If the parent node is not a shadow host, we can use
3759 // nsINode::GetNextSibling() and nsINode::GetPreviousSibling() in any trees
3760 // so that we can check whether aChild1 and aChild2 are adjacent siblings.
3761 if (MOZ_LIKELY(!iter.ShadowDOMInvolved())(__builtin_expect(!!(!iter.ShadowDOMInvolved()), 1))) {
3762 if (aChild1->GetNextSibling() == aChild2) {
3763 return Some(-1);
3764 }
3765 if (aChild2->GetNextSibling() == aChild1) {
3766 return Some(1);
3767 }
3768 }
3769
3770 // Retrieving the first child and the last child is not expensive so, let's
3771 // check whether aChild1 or aChild2 is the first/last child.
3772 const nsIContent* lastChild = iter.GetLastChild();
3773 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"
, 3773); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastChild" ")"
); do { MOZ_CrashSequence(__null, 3773); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3774 if (aChild1 == lastChild) {
3775 return Some(1);
3776 }
3777 if (aChild2 == lastChild) {
3778 return Some(-1);
3779 }
3780 const nsIContent* firstChild = iter.GetFirstChild();
3781 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"
, 3781); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstChild"
")"); do { MOZ_CrashSequence(__null, 3781); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3782 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", 3782); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "firstChild != lastChild" ")"); do { MOZ_CrashSequence
(__null, 3782); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3783 if (aChild1 == firstChild) {
3784 return Some(-1);
3785 }
3786 if (aChild2 == firstChild) {
3787 return Some(1);
3788 }
3789
3790 // nsINode::ComputeIndexOf() computes the index with scanning siblings from
3791 // the first child in the worst case. However, if the node caches the
3792 // computed result, the scan range may be narrowed in fortunate cases.
3793 // Therefore, if the node uses the cache, we should use it because the callers
3794 // may need to compute the index again. In such cases, the cache saves the
3795 // computation cost.
3796 if (aParent.MaybeCachesComputedIndex()) {
3797 Maybe<uint32_t> child1Index;
3798 Maybe<uint32_t> child2Index;
3799 if (aIndexCache) {
3800 Maybe<int32_t> maybeGenContentChild1Index;
3801 Maybe<int32_t> maybeGenContentChild2Index;
3802 aIndexCache->ComputeIndicesOf<aKind>(&aParent, aChild1, aChild2,
3803 maybeGenContentChild1Index,
3804 maybeGenContentChild2Index);
3805 // Negative offset if the child is generated content or native anonymous
3806 // content. However, this method does not support such nodes. Therefore,
3807 // we should treat them as "disconnected".
3808 if (maybeGenContentChild1Index && *maybeGenContentChild1Index >= 0) {
3809 child1Index.emplace(static_cast<uint32_t>(*maybeGenContentChild1Index));
3810 }
3811 if (maybeGenContentChild2Index && *maybeGenContentChild2Index >= 0) {
3812 child2Index.emplace(static_cast<uint32_t>(*maybeGenContentChild2Index));
3813 }
3814#ifdef DEBUG1
3815 const Maybe<uint32_t> child1IndexDebug =
3816 aParent.ComputeIndexOf<aKind>(aChild1);
3817 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"
, 3823); } } while (false)
3818 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"
, 3823); } } while (false)
3819 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"
, 3823); } } while (false)
3820 "{}\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"
, 3823); } } while (false)
3821 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"
, 3823); } } while (false)
3822 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"
, 3823); } } while (false)
3823 .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"
, 3823); } } while (false)
;
3824 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"
, 3824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "child1Index == child1IndexDebug"
")"); do { MOZ_CrashSequence(__null, 3824); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3825 const Maybe<uint32_t> child2IndexDebug =
3826 aParent.ComputeIndexOf<aKind>(aChild2);
3827 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"
, 3833); } } while (false)
3828 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"
, 3833); } } while (false)
3829 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"
, 3833); } } while (false)
3830 "{}\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"
, 3833); } } while (false)
3831 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"
, 3833); } } while (false)
3832 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"
, 3833); } } while (false)
3833 .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"
, 3833); } } while (false)
;
3834 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"
, 3834); AnnotateMozCrashReason("MOZ_ASSERT" "(" "child2Index == child2IndexDebug"
")"); do { MOZ_CrashSequence(__null, 3834); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3835#endif // #ifdef DEBUG
3836 } else {
3837 child1Index = aParent.ComputeIndexOf<aKind>(aChild1);
3838 child2Index = aParent.ComputeIndexOf<aKind>(aChild2);
3839 }
3840 if (MOZ_LIKELY(child1Index.isSome() && child2Index.isSome())(__builtin_expect(!!(child1Index.isSome() && child2Index
.isSome()), 1))
) {
3841 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"
, 3841); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*child1Index != *child2Index"
")"); do { MOZ_CrashSequence(__null, 3841); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3842 return Some(*child1Index < *child2Index ? -1 : 1);
3843 }
3844 // XXX Keep the odd traditional behavior for now.
3845 return Some(child1Index.isNothing() && child2Index.isSome() ? -1 : 1);
3846 }
3847
3848 // On the other hand, it does not use the cache, let's scan siblings starting
3849 // from aChild1. Then, if we find aChild2, the position is aChild1 < aChild2.
3850 // Otherwise, aChild2 < aChild1. This narrows the scanning range than using
3851 // ComputeIndexOf(), i.e., even in the worst case, this is faster than a call
3852 // of ComputeIndexOf().
3853 if (NS_WARN_IF(!iter.Seek(aChild1))NS_warn_if_impl(!iter.Seek(aChild1), "!iter.Seek(aChild1)", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3853)
) {
3854 return Nothing{};
3855 }
3856 for (const nsIContent* followingSiblingOfChild1 = iter.GetNextChild();
3857 followingSiblingOfChild1;
3858 followingSiblingOfChild1 = iter.GetNextChild()) {
3859 if (followingSiblingOfChild1 == aChild2) {
3860 return Some(-1);
3861 }
3862 }
3863 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"
, 3863); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent.ComputeIndexOf<aKind>(aChild2).isSome()"
")"); do { MOZ_CrashSequence(__null, 3863); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3864 return Some(1);
3865}
3866
3867/* static */
3868template <TreeKind aKind, typename Dummy>
3869Maybe<int32_t> nsContentUtils::CompareClosestCommonAncestorChildren(
3870 const nsINode& aParent, const nsIContent* aChild1,
3871 const nsIContent* aChild2, nsContentUtils::NodeIndexCache* aIndexCache) {
3872 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", 3873); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3873); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3873 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", 3873); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3873); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3874 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", 3875); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3875); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3875 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", 3875); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3875); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3876 // See the explanation of TreeKindToCompareChildren. aParent may be computed
3877 // with TreeKind::ShadowIncludingDOM if aKind is TreeKind::DOM.
3878 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", 3882); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3882); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3879 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", 3882); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3882); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3880 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", 3882); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3882); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3881 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", 3882); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3882); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3882 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", 3882); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3882); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3883 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", 3887); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3887); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3884 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", 3887); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3887); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3885 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", 3887); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3887); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3886 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", 3887); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3887); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3887 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", 3887); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3887); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3888
3889 if (aChild1 && aChild2) {
3890 if (MOZ_UNLIKELY(aChild1->IsShadowRoot())(__builtin_expect(!!(aChild1->IsShadowRoot()), 0))) {
3891 // Shadow roots come before light DOM per
3892 // https://dom.spec.whatwg.org/#concept-shadow-including-tree-order
3893 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"
, 3893); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChild2->IsShadowRoot()"
") (" "Two shadow roots?" ")"); do { MOZ_CrashSequence(__null
, 3893); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
3894 return Some(-1);
3895 }
3896 if (MOZ_UNLIKELY(aChild2->IsShadowRoot())(__builtin_expect(!!(aChild2->IsShadowRoot()), 0))) {
3897 return Some(1);
3898 }
3899 }
3900 // FIXME: bug 1946003 and bug 1946008.
3901 if (MOZ_UNLIKELY((aChild1 && aChild1->IsDocumentFragment()) ||(__builtin_expect(!!((aChild1 && aChild1->IsDocumentFragment
()) || (aChild2 && aChild2->IsDocumentFragment()))
, 0))
3902 (aChild2 && aChild2->IsDocumentFragment()))(__builtin_expect(!!((aChild1 && aChild1->IsDocumentFragment
()) || (aChild2 && aChild2->IsDocumentFragment()))
, 0))
) {
3903 // XXX Keep the odd traditional behavior for now. I think that we should
3904 // return Nothing in this case.
3905 return Some(1);
3906 }
3907
3908 const Maybe<int32_t> comp = nsContentUtils::CompareChildNodes<aKind>(
3909 aParent, aChild1, aChild2, aIndexCache);
3910 if (MOZ_UNLIKELY(comp.isNothing())(__builtin_expect(!!(comp.isNothing()), 0))) {
3911 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", 3913); MOZ_PretendNoReturn
(); } } while (0)
3912 "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", 3913); MOZ_PretendNoReturn
(); } } while (0)
3913 "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", 3913); MOZ_PretendNoReturn
(); } } while (0)
;
3914 // XXX Keep the odd traditional behavior for now. I think that we should
3915 // return Nothing in this case.
3916 return Some(1);
3917 }
3918#ifdef DEBUG1
3919 const auto NodeIsNullOrValidChild = [](const nsINode& aParent,
3920 const nsIContent* aChild) {
3921 if (!aChild || aParent.ComputeIndexOf<aKind>(aChild).isSome()) {
3922 return true;
3923 }
3924 if constexpr (aKind == TreeKind::FlatForSelection) {
3925 const Element* const excluderShadowHostOrSlotElement =
3926 aChild->GetClosestFlatTreeAncestorElementForNonFlatTreeNode<
3927 TreeKind::FlatForSelection>();
3928 if (excluderShadowHostOrSlotElement &&
3929 (excluderShadowHostOrSlotElement == &aParent ||
3930 excluderShadowHostOrSlotElement->GetShadowRootForSelection() ==
3931 &aParent)) {
3932 return true;
3933 }
3934 }
3935 return false;
3936 };
3937 const auto ChildrenHaveSameIndex = [](const nsIContent* aChild1,
3938 const nsIContent* aChild2) {
3939 if (aChild1 == aChild2) {
3940 return true;
3941 }
3942 const bool child1IsAtEndOfParent =
3943 !aChild1 ||
3944 (aKind == TreeKind::FlatForSelection &&
3945 aChild1->GetClosestFlatTreeAncestorElementForNonFlatTreeNode<
3946 TreeKind::FlatForSelection>());
3947 const bool child2IsAtEndOfParent =
3948 !aChild2 ||
3949 (aKind == TreeKind::FlatForSelection &&
3950 aChild2->GetClosestFlatTreeAncestorElementForNonFlatTreeNode<
3951 TreeKind::FlatForSelection>());
3952 return child1IsAtEndOfParent && child2IsAtEndOfParent;
3953 };
3954 const auto ChildIndexIsLessThanTheOtherChildIndex =
3955 [](const nsINode& aParent, const nsIContent* aChild1,
3956 const nsIContent* aChild2) {
3957 const uint32_t child1Index =
3958 aChild1 ? aParent.ComputeIndexOf<aKind>(aChild1).valueOr(
3959 aParent.GetChildCount<aKind>())
3960 : aParent.GetChildCount<aKind>();
3961 const uint32_t child2Index =
3962 aChild2 ? aParent.ComputeIndexOf<aKind>(aChild2).valueOr(
3963 aParent.GetChildCount<aKind>())
3964 : aParent.GetChildCount<aKind>();
3965 return child1Index < child2Index;
3966 };
3967 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", 3971); }
} while (false)
3968 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", 3971); }
} while (false)
3969 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", 3971); }
} while (false)
3970 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", 3971); }
} while (false)
3971 .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", 3971); }
} while (false)
;
3972 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", 3976); }
} while (false)
3973 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", 3976); }
} while (false)
3974 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", 3976); }
} while (false)
3975 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", 3976); }
} while (false)
3976 .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", 3976); }
} while (false)
;
3977 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", 3977); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aChild1 == aChild2" ")"); do { MOZ_CrashSequence
(__null, 3977); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
3978 const DebugOnly<bool> eitherIsNAC =
3979 (aChild1 && aChild1->IsRootOfNativeAnonymousSubtree()) ||
3980 (aChild2 && aChild2->IsRootOfNativeAnonymousSubtree());
3981 const DebugOnly<bool> eitherIsNotPartOfTree =
3982 ShouldHandleAssignedNodesOnSlot<aKind>() &&
3983 ((aParent.GetShadowRoot<aKind>() &&
3984 ((aChild1 && aChild1->GetParentNode() == &aParent) ||
3985 (aChild2 && aChild2->GetParentNode() == &aParent))) ||
3986 ((aParent.GetAsHTMLSlotElementIfFilled<aKind>() &&
3987 ((aChild1 && !aChild1->GetAssignedSlot<aKind>()) ||
3988 (aChild2 && !aChild2->GetAssignedSlot<aKind>())))));
3989 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"
, 3990); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChildrenHaveSameIndex(aChild1, aChild2)"
")"); do { MOZ_CrashSequence(__null, 3990); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3990 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"
, 3990); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChildrenHaveSameIndex(aChild1, aChild2)"
")"); do { MOZ_CrashSequence(__null, 3990); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3991 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", 3993); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2)"
")"); do { MOZ_CrashSequence(__null, 3993); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3992 !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", 3993); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2)"
")"); do { MOZ_CrashSequence(__null, 3993); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3993 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", 3993); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2)"
")"); do { MOZ_CrashSequence(__null, 3993); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3994 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", 3996); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1)"
")"); do { MOZ_CrashSequence(__null, 3996); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3995 !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", 3996); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1)"
")"); do { MOZ_CrashSequence(__null, 3996); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3996 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", 3996); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1)"
")"); do { MOZ_CrashSequence(__null, 3996); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3997#endif // #ifdef DEBUG
3998 return comp;
3999}
4000
4001/* static */
4002template <TreeKind aKind, typename Dummy>
4003Maybe<int32_t> nsContentUtils::CompareChildOffsetAndChildNode(
4004 const nsINode& aParent, uint32_t aOffset1, const nsIContent& aChild2,
4005 NodeIndexCache* aIndexCache /* = nullptr */) {
4006 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", 4007); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4007); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4007 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", 4007); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4007); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4008 // See the explanation of TreeKindToCompareChildren. aParent may be computed
4009 // with TreeKind::ShadowIncludingDOM if aKind is TreeKind::DOM.
4010 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", 4014); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4014); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4011 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", 4014); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4014); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4012 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", 4014); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4014); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4013 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", 4014); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4014); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4014 &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", 4014); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4014); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4015
4016 if (NS_WARN_IF(aChild2.IsDocumentFragment())NS_warn_if_impl(aChild2.IsDocumentFragment(), "aChild2.IsDocumentFragment()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4016)
) {
4017 return Nothing();
4018 }
4019 // Native anonymous content (e.g. ::before/::after) is not in the regular
4020 // child list, so order it against the [parentNode, aOffset1] boundary using
4021 // the flat-tree index space from GetIndexInParent. aOffset1 indexes regular
4022 // children [0, N); the NAC child sits at child2Index in the same space, and
4023 // the boundary precedes it iff aOffset1 <= child2Index.
4024 if (MOZ_UNLIKELY(aChild2.IsRootOfNativeAnonymousSubtree())(__builtin_expect(!!(aChild2.IsRootOfNativeAnonymousSubtree()
), 0))
) {
4025 const Maybe<int32_t> child2Index =
4026 aIndexCache ? aIndexCache->ComputeIndexOf<aKind>(&aParent, &aChild2)
4027 : GetIndexInParent<aKind>(&aParent, &aChild2);
4028 if (NS_WARN_IF(child2Index.isNothing())NS_warn_if_impl(child2Index.isNothing(), "child2Index.isNothing()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4028)
) {
4029 // XXX Keep the odd traditional behavior for now.
4030 return Some(1);
4031 }
4032 return Some(int32_t(aOffset1) <= *child2Index ? -1 : 1);
4033 }
4034
4035 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", 4035); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4035); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4036
4037 const uint32_t parentNodeChildCount = aParent.GetChildCount<aKind>();
4038 if (NS_WARN_IF(aOffset1 > parentNodeChildCount)NS_warn_if_impl(aOffset1 > parentNodeChildCount, "aOffset1 > parentNodeChildCount"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4038)
) {
4039 // If the root caller's boundary points after end of aParent, let's treat
4040 // it's after the fallback content for now... If you find a bug and you know
4041 // better result in this case, feel free to change.
4042 return Some(1);
4043 }
4044
4045 if constexpr (aKind == TreeKind::FlatForSelection) {
4046 // If we're handling flattened tree for selection, aChild2 may be a fallback
4047 // content of a <slot> which has some assigned nodes or an unassigned child
4048 // node of a shadow host. Then, aChild2 is not part of the flattened tree,
4049 // but it is also valid for range boundaries. Therefore, we need to handle
4050 // the case here.
4051 if (aChild2.GetParentNode() == &aParent &&
4052 (aParent.GetAsHTMLSlotElementIfFilledForSelection() ||
4053 aParent.GetShadowRootForSelection())) {
4054 // Treat the fallback content and the unassigned node is after the last
4055 // assigned node or the shadow.
4056 // XXX I'm not sure whether we should treat the end of aParent and a
4057 // fallback content node are the same position or not. For now, we treat
4058 // them as the same, but if you find a bug and you know better result in
4059 // this case, feel free to change here.
4060 return aOffset1 == parentNodeChildCount ? Some(0) : Some(-1);
4061 }
4062 }
4063
4064 if (aOffset1 == parentNodeChildCount) {
4065 return Some(1); // Comparing with after the last child and a child.
4066 }
4067
4068 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"
, 4068); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent.GetFirstChild<aKind>()"
")"); do { MOZ_CrashSequence(__null, 4068); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4069 const nsIContent& firstChild = *aParent.GetFirstChild<aKind>();
4070 if (&aChild2 == &firstChild) {
4071 return Some(!aOffset1 ? 0 : 1);
4072 }
4073
4074 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"
, 4074); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent.GetLastChild<aKind>()"
")"); do { MOZ_CrashSequence(__null, 4074); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4075 const nsIContent& lastChild = *aParent.GetLastChild<aKind>();
4076 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", 4080); }
} while (false)
4077 &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", 4080); }
} while (false)
4078 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", 4080); }
} while (false)
4079 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", 4080); }
} while (false)
4080 .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", 4080); }
} while (false)
;
4081 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"
, 4081); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&firstChild != &lastChild"
")"); do { MOZ_CrashSequence(__null, 4081); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4082 if (&aChild2 == &lastChild) {
4083 return Some(aOffset1 == parentNodeChildCount - 1 ? 0 : -1);
4084 }
4085 Maybe<uint32_t> child2Index;
4086 if (aIndexCache) {
4087 const Maybe<int32_t> maybeGenContentChild2Index =
4088 aIndexCache->ComputeIndexOf<aKind>(&aParent, &aChild2);
4089 if (maybeGenContentChild2Index && *maybeGenContentChild2Index >= 0) {
4090 child2Index.emplace(static_cast<uint32_t>(*maybeGenContentChild2Index));
4091 }
4092#ifdef DEBUG1
4093 const Maybe<uint32_t> child2IndexDebug =
4094 aParent.ComputeIndexOf<aKind>(&aChild2);
4095 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"
, 4101); } } while (false)
4096 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"
, 4101); } } while (false)
4097 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"
, 4101); } } while (false)
4098 "{}\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"
, 4101); } } while (false)
4099 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"
, 4101); } } while (false)
4100 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"
, 4101); } } while (false)
4101 .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"
, 4101); } } while (false)
;
4102 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"
, 4102); AnnotateMozCrashReason("MOZ_ASSERT" "(" "child2Index == child2IndexDebug"
")"); do { MOZ_CrashSequence(__null, 4102); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4103#endif // #ifdef DEBUG
4104 } else {
4105 child2Index = aParent.ComputeIndexOf<aKind>(&aChild2);
4106 }
4107 if (NS_WARN_IF(child2Index.isNothing())NS_warn_if_impl(child2Index.isNothing(), "child2Index.isNothing()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4107)
) {
4108 return Some(1);
4109 }
4110 return Some(aOffset1 == *child2Index ? 0
4111 : (aOffset1 < *child2Index ? -1 : 1));
4112}
4113
4114/* static */
4115template <TreeKind aKind, typename Dummy>
4116Maybe<int32_t> nsContentUtils::CompareChildNodeAndChildOffset(
4117 const nsINode& aParent, const nsIContent& aChild1, uint32_t aOffset2,
4118 NodeIndexCache* aIndexCache /* = nullptr */) {
4119 const Maybe<int32_t> comp = CompareChildOffsetAndChildNode<aKind>(
4120 aParent, aOffset2, aChild1, aIndexCache);
4121 if (comp.isNothing()) {
4122 return comp;
4123 }
4124 return Some(*comp * -1);
4125}
4126
4127/* static */
4128template <TreeKind aKind>
4129Maybe<int32_t> nsContentUtils::ComparePointsWithIndices(
4130 const nsINode* aParent1, uint32_t aOffset1, const nsINode* aParent2,
4131 uint32_t aOffset2, NodeIndexCache* aIndexCache) {
4132 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"
, 4132); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent1" ")"
); do { MOZ_CrashSequence(__null, 4132); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4133 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"
, 4133); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent2" ")"
); do { MOZ_CrashSequence(__null, 4133); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4134
4135 if (aParent1 == aParent2) {
4136 return Some(aOffset1 < aOffset2 ? -1 : (aOffset1 > aOffset2 ? 1 : 0));
4137 }
4138
4139 const CommonAncestors<GetParentNodeForComparison<aKind>> commonAncestors(
4140 *aParent1, *aParent2);
4141 const nsINode* const closestCommonAncestor =
4142 commonAncestors.GetClosestCommonAncestor();
4143 if (MOZ_UNLIKELY(!closestCommonAncestor)(__builtin_expect(!!(!closestCommonAncestor), 0))) {
4144 return Nothing();
4145 }
4146
4147 const nsIContent* closestCommonAncestorChild1 = nsIContent::FromNodeOrNull(
4148 commonAncestors.GetClosestCommonAncestorChild1());
4149 const nsIContent* closestCommonAncestorChild2 = nsIContent::FromNodeOrNull(
4150 commonAncestors.GetClosestCommonAncestorChild2());
4151 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", 4151); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1 != closestCommonAncestorChild2"
")"); do { MOZ_CrashSequence(__null, 4151); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4152 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"
, 4153); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 4153); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4153 !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"
, 4153); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 4153); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4154 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"
, 4155); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 4155); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4155 !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"
, 4155); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 4155); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4156 commonAncestors
4157 .template WarnIfClosestCommonAncestorChildrenAreNotInChildList<aKind>();
4158 if (closestCommonAncestorChild1 && closestCommonAncestorChild2) {
4159 return CompareClosestCommonAncestorChildren<
4160 TreeKindToCompareChildren<aKind>()>(
4161 *closestCommonAncestor, closestCommonAncestorChild1,
4162 closestCommonAncestorChild2, aIndexCache);
4163 }
4164
4165 if (closestCommonAncestorChild2) {
4166 // aParent1 is the common ancestor.
4167 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", 4168); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aParent1"
")"); do { MOZ_CrashSequence(__null, 4168); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4168 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", 4168); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aParent1"
")"); do { MOZ_CrashSequence(__null, 4168); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4169 if (aKind != TreeKind::DOM && ChildNodeIsInShadowDOMHostedByParent<aKind>(
4170 aParent1, closestCommonAncestorChild2)) {
4171 // Comparing a shadow host with its shadow root.
4172 // We consider:
4173 // [aParent1, 0] < closestCommonAncestorChild2 < [aParent1, 1]
4174 return aOffset1 > 0 ? Some(1) : Some(-1);
4175 }
4176
4177 // FIXME: bug 1946003 and bug 1946008.
4178 if (MOZ_UNLIKELY(closestCommonAncestorChild2->IsDocumentFragment())(__builtin_expect(!!(closestCommonAncestorChild2->IsDocumentFragment
()), 0))
) {
4179 // XXX Keep the odd traditional behavior for now.
4180 return Some(1);
4181 }
4182 // If the common ancestor is a shadow host, closestCommonAncestorChild2 must
4183 // be a child node of the host and we shouldn't handle the flattened tree.
4184 // Therefore, we can compare closestCommonAncestorChild2 and the child at
4185 // aBoundary1 can be compared within TreeKind::DOM tree.
4186 // NOTE: When aKind is TreeKind::FlatForSelection,
4187 // GetParentNodeForComparison returns the shadow host as the parent node
4188 // of a child node even if it's not assigned to any <slot>. Therefore, even
4189 // when we should return Nothing, we may return Some value for now.
4190 // Therefore, we need to relax this assertion for TreeKind::FlatForSelection
4191 // until fixing bug 2014622. And it's okay to compare the child nodes not a
4192 // part of flattened tree as in the DOM since anyway we return wrong value.
4193 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", 4196); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4196); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4194 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", 4196); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4196); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4195 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", 4196); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4196); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4196 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", 4196); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4196); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4197 const Maybe<int32_t> comp = nsContentUtils::CompareChildOffsetAndChildNode<
4198 TreeKindToCompareChildren<aKind>()>(*closestCommonAncestor, aOffset1,
4199 *closestCommonAncestorChild2,
4200 aIndexCache);
4201 if (NS_WARN_IF(comp.isNothing())NS_warn_if_impl(comp.isNothing(), "comp.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4201)
) {
4202 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", 4205); MOZ_PretendNoReturn
(); } } while (0)
4203 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", 4205); MOZ_PretendNoReturn
(); } } while (0)
4204 "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", 4205); MOZ_PretendNoReturn
(); } } while (0)
4205 "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", 4205); MOZ_PretendNoReturn
(); } } while (0)
;
4206 // XXX Keep the odd traditional behavior for now.
4207 return Some(1);
4208 }
4209 // If the child of the closest common ancestor is at aOffset1 of aParent1,
4210 // it means that aOffset2 of aParent2 refers a descendant of the child.
4211 // So, aOffset2 of aParent2 refers a descendant of aOffset1 of aParent1.
4212 if (!*comp) {
4213 return Some(-1);
4214 }
4215 return comp;
4216 }
4217
4218 // aParent2 is the common ancestor.
4219 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", 4219); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1" ")"); do { MOZ_CrashSequence
(__null, 4219); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4220 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", 4221); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aParent2"
")"); do { MOZ_CrashSequence(__null, 4221); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4221 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", 4221); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aParent2"
")"); do { MOZ_CrashSequence(__null, 4221); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4222 if (aKind != TreeKind::DOM && ChildNodeIsInShadowDOMHostedByParent<aKind>(
4223 aParent2, closestCommonAncestorChild1)) {
4224 // Comparing a shadow host with its shadow root.
4225 // We consider: [aParent2, 0] < closestCommonAncestorChild1 < [aParent2, 1]
4226 return aOffset2 > 0 ? Some(-1) : Some(1);
4227 }
4228
4229 // FIXME: bug 1946003 and bug 1946008.
4230 if (MOZ_UNLIKELY(closestCommonAncestorChild1->IsDocumentFragment())(__builtin_expect(!!(closestCommonAncestorChild1->IsDocumentFragment
()), 0))
) {
4231 // XXX Keep the odd traditional behavior for now.
4232 return Some(-1);
4233 }
4234 // If the common ancestor is a shadow host, closestCommonAncestorChild1 must
4235 // be a child node of the host and we shouldn't handle the flattened tree.
4236 // Therefore, we can compare closestCommonAncestorChild1 and the child at
4237 // aBoundary2 can be compared within TreeKind::DOM tree.
4238 // NOTE: When aKind is TreeKind::FlatForSelection,
4239 // GetParentNodeForComparison returns the shadow host as the parent node
4240 // of a child node even if it's not assigned to any <slot>. Therefore, even
4241 // when we should return Nothing, we may return Some value for now.
4242 // Therefore, we need to relax this assertion for TreeKind::FlatForSelection
4243 // until fixing bug 2014622. And it's okay to compare the child nodes not a
4244 // part of flattened tree as in the DOM since anyway we return wrong value.
4245 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", 4248); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4248); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4246 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", 4248); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4248); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4247 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", 4248); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4248); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4248 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", 4248); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4248); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4249 const Maybe<int32_t> comp = nsContentUtils::CompareChildNodeAndChildOffset<
4250 TreeKindToCompareChildren<aKind>()>(*closestCommonAncestor,
4251 *closestCommonAncestorChild1,
4252 aOffset2, aIndexCache);
4253 if (NS_WARN_IF(comp.isNothing())NS_warn_if_impl(comp.isNothing(), "comp.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4253)
) {
4254 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"
, 4256); MOZ_PretendNoReturn(); } } while (0)
4255 "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"
, 4256); MOZ_PretendNoReturn(); } } while (0)
4256 "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"
, 4256); MOZ_PretendNoReturn(); } } while (0)
;
4257 // XXX Keep the odd traditional behavior for now.
4258 return Some(-1);
4259 }
4260 // If the child of the closet common ancestor is at aOffset2 of aParent2, it
4261 // means that aOffset1 of aParent1 refers a descendant of the child.
4262 // So, aOffset1 of aParent1 refers a descendant of aOffset2 of aParent2.
4263 if (!*comp) {
4264 return Some(1);
4265 }
4266 return comp;
4267}
4268
4269/* static */
4270BrowserParent* nsContentUtils::GetCommonBrowserParentAncestor(
4271 BrowserParent* aBrowserParent1, BrowserParent* aBrowserParent2) {
4272 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", 4272); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aBrowserParent1" ")"); do { MOZ_CrashSequence
(__null, 4272); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4273 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", 4273); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aBrowserParent2" ")"); do { MOZ_CrashSequence
(__null, 4273); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4274 return CommonAncestors<GetParentBrowserParent>(*aBrowserParent1,
4275 *aBrowserParent2)
4276 .GetClosestCommonAncestor();
4277}
4278
4279/* static */
4280Element* nsContentUtils::GetTargetElement(Document* aDocument,
4281 const nsAString& aAnchorName) {
4282 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"
, 4282); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { MOZ_CrashSequence(__null, 4282); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4283
4284 if (aAnchorName.IsEmpty()) {
4285 return nullptr;
4286 }
4287 // 1. If there is an element in the document tree that has an ID equal to
4288 // fragment, then return the first such element in tree order.
4289 if (Element* el = aDocument->GetElementById(aAnchorName)) {
4290 return el;
4291 }
4292
4293 // 2. If there is an a element in the document tree that has a name
4294 // attribute whose value is equal to fragment, then return the first such
4295 // element in tree order.
4296 //
4297 // FIXME(emilio): Why the different code-paths for HTML and non-HTML docs?
4298 if (aDocument->IsHTMLDocument()) {
4299 RefPtr<NodeList> list = aDocument->GetElementsByName(aAnchorName);
4300 // Loop through the named nodes looking for the first anchor
4301 uint32_t length = list->Length();
4302 for (uint32_t i = 0; i < length; i++) {
4303 nsIContent* node = list->Item(i);
4304 if (node->IsHTMLElement(nsGkAtoms::a)) {
4305 return node->AsElement();
4306 }
4307 }
4308 } else {
4309 constexpr auto nameSpace = u"http://www.w3.org/1999/xhtml"_ns;
4310 // Get the list of anchor elements
4311 RefPtr<NodeList> list =
4312 aDocument->GetElementsByTagNameNS(nameSpace, u"a"_ns);
4313 // Loop through the anchors looking for the first one with the given name.
4314 for (uint32_t i = 0; true; i++) {
4315 nsIContent* node = list->Item(i);
4316 if (!node) { // End of list
4317 break;
4318 }
4319
4320 // Compare the name attribute
4321 if (node->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
4322 aAnchorName, eCaseMatters)) {
4323 return node->AsElement();
4324 }
4325 }
4326 }
4327
4328 // 3. Return null.
4329 return nullptr;
4330}
4331
4332/* static */
4333template <TreeKind aKind, typename PT1, typename RT1, typename PT2,
4334 typename RT2>
4335Maybe<int32_t> nsContentUtils::ComparePoints(
4336 const RangeBoundaryBase<PT1, RT1>& aBoundary1,
4337 const RangeBoundaryBase<PT2, RT2>& aBoundary2,
4338 NodeIndexCache* aIndexCache /* = nullptr */) {
4339 if (!aBoundary1.IsSet() || !aBoundary2.IsSet()) {
4340 return Nothing{};
4341 }
4342 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"
, 4342); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBoundary1.GetTreeKind() == aBoundary2.GetTreeKind()"
")"); do { MOZ_CrashSequence(__null, 4342); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4343
4344 const auto kValidOrInvalidOffsets1 =
4345 RangeBoundaryBase<PT1, RT1>::OffsetFilter::kValidOrInvalidOffsets;
4346 const auto kValidOrInvalidOffsets2 =
4347 RangeBoundaryBase<PT2, RT2>::OffsetFilter::kValidOrInvalidOffsets;
4348
4349 // RangeBoundaryBase instances may be initialized only with a child node or an
4350 // offset in the container. If both instances have computed offset, we can
4351 // use ComparePointsWithIndices() which works with offsets.
4352 if (aBoundary1.HasOffset() && aBoundary2.HasOffset()) {
4353 return ComparePointsWithIndices<aKind>(
4354 aBoundary1.GetContainer(), *aBoundary1.Offset(kValidOrInvalidOffsets1),
4355 aBoundary2.GetContainer(), *aBoundary2.Offset(kValidOrInvalidOffsets2),
4356 aIndexCache);
4357 }
4358
4359 // Otherwise, i.e., at least one RangeBoundaryBase stores the child node.
4360 // In the most cases, RangeBoundaryBase has it, so, the worst scenario here
4361 // is, one of the boundaries comes from a StaticRange or is initialized with
4362 // offset and RangeBoundarySetBy::Offset. However, for making it faster in
4363 // the most cases, we should compare the child nodes without offsets if
4364 // possible.
4365
4366 // If we're comparing children in the same container, we don't need to compute
4367 // common ancestors. So, we can skip it and just compare the children.
4368 if (aBoundary1.GetContainer() == aBoundary2.GetContainer()) {
4369 const nsIContent* const child1 = aBoundary1.GetChildAtOffset();
4370 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", 4370); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!child1->IsShadowRoot()" ")"); do { MOZ_CrashSequence
(__null, 4370); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
4371 const nsIContent* const child2 = aBoundary2.GetChildAtOffset();
4372 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", 4372); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!child2->IsShadowRoot()" ")"); do { MOZ_CrashSequence
(__null, 4372); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
4373 // But aBoundary1 and aBoundary2 may be not updated for the latest DOM.
4374 // In such case, we need to return Nothing.
4375 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", 4376)
4376 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", 4376)
||
4377 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", 4378)
4378 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", 4378)
) [[unlikely]] {
4379 return Nothing{};
4380 }
4381 return CompareClosestCommonAncestorChildren<
4382 TreeKindToCompareChildren<aKind>()>(*aBoundary1.GetContainer(), child1,
4383 child2, aIndexCache);
4384 }
4385
4386 // Otherwise, we need to compare the common ancestor children which is the
4387 // most distant different inclusive ancestors of the containers. So, the
4388 // following implementation is similar to ComparePointsWithIndices(), but we
4389 // don't have offset, so, we cannot use offset when we compare the boundaries
4390 // whose one is a descendant of the other.
4391 const CommonAncestors<GetParentNodeForComparison<aKind>> commonAncestors(
4392 *aBoundary1.GetContainer(), *aBoundary2.GetContainer());
4393
4394 const nsINode* const closestCommonAncestor =
4395 commonAncestors.GetClosestCommonAncestor();
4396 if (MOZ_UNLIKELY(!closestCommonAncestor)(__builtin_expect(!!(!closestCommonAncestor), 0))) {
4397 return Nothing();
4398 }
4399 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", 4399); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "commonAncestors.GetClosestCommonAncestor()"
")"); do { MOZ_CrashSequence(__null, 4399); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4400
4401 const nsIContent* closestCommonAncestorChild1 = nsIContent::FromNodeOrNull(
4402 commonAncestors.GetClosestCommonAncestorChild1());
4403 const nsIContent* closestCommonAncestorChild2 = nsIContent::FromNodeOrNull(
4404 commonAncestors.GetClosestCommonAncestorChild2());
4405 commonAncestors
4406 .template WarnIfClosestCommonAncestorChildrenAreNotInChildList<aKind>();
4407 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", 4407); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1 != closestCommonAncestorChild2"
")"); do { MOZ_CrashSequence(__null, 4407); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4408 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"
, 4409); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 4409); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4409 !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"
, 4409); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 4409); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4410 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"
, 4411); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 4411); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4411 !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"
, 4411); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 4411); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4412 if (closestCommonAncestorChild1 && closestCommonAncestorChild2) {
4413 return CompareClosestCommonAncestorChildren<
4414 TreeKindToCompareChildren<aKind>()>(
4415 *closestCommonAncestor, closestCommonAncestorChild1,
4416 closestCommonAncestorChild2, aIndexCache);
4417 }
4418
4419 if (closestCommonAncestorChild2) {
4420 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", 4421); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aBoundary1.GetContainer()"
")"); do { MOZ_CrashSequence(__null, 4421); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4421 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", 4421); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aBoundary1.GetContainer()"
")"); do { MOZ_CrashSequence(__null, 4421); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4422 // FIXME: bug 1946003 and bug 1946008.
4423 if (MOZ_UNLIKELY(closestCommonAncestorChild2->IsDocumentFragment())(__builtin_expect(!!(closestCommonAncestorChild2->IsDocumentFragment
()), 0))
) {
4424 // XXX Keep the odd traditional behavior for now.
4425 return Some(1);
4426 }
4427 // If the common ancestor is a shadow host, closestCommonAncestorChild2 must
4428 // be a child node of the host and we shouldn't handle the flattened tree.
4429 // Therefore, we can compare closestCommonAncestorChild2 and the child at
4430 // aBoundary1 can be compared within TreeKind::DOM tree.
4431 // NOTE: When aKind is TreeKind::FlatForSelection,
4432 // GetParentNodeForComparison returns the shadow host as the parent node
4433 // of a child node even if it's not assigned to any <slot>. Therefore, even
4434 // when we should return Nothing, we may return Some value for now.
4435 // Therefore, we need to relax this assertion for TreeKind::FlatForSelection
4436 // until fixing bug 2014622. And it's okay to compare the child nodes not a
4437 // part of flattened tree as in the DOM since anyway we return wrong value.
4438 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", 4441); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4441); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4439 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", 4441); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4441); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4440 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", 4441); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4441); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4441 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", 4441); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4441); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4442 const Maybe<int32_t> comp = nsContentUtils::CompareChildNodes<
4443 TreeKindToCompareChildren<TreeKindToCompareChildren<aKind>()>()>(
4444 *closestCommonAncestor, aBoundary1.GetChildAtOffset(),
4445 closestCommonAncestorChild2, aIndexCache);
4446 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", 4448); MOZ_PretendNoReturn
(); } } while (0)
4447 "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", 4448); MOZ_PretendNoReturn
(); } } while (0)
4448 "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", 4448); MOZ_PretendNoReturn
(); } } while (0)
;
4449 if (NS_WARN_IF(comp.isNothing())NS_warn_if_impl(comp.isNothing(), "comp.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4449)
) {
4450 // XXX Keep the odd traditional behavior for now.
4451 return Some(1);
4452 }
4453 // If the child of the closest common ancestor is at aBoundary1, it means
4454 // that aBoundary2 refers a descendant of the child. So, aBoundary2 refers a
4455 // descendant of aBoundary1.
4456 if (!*comp) {
4457 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", 4462); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4462); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4458 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", 4462); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4462); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4459 *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", 4462); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4462); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4460 ->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", 4462); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4462); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4461 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", 4462); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4462); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4462 *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", 4462); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4462); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4463 return Some(-1);
4464 }
4465 // ComputeIndexInParentNode() is the index in the regular child list, which
4466 // native anonymous content is not part of. CompareChildNodes already
4467 // ordered NAC via GetIndexInParent, so skip the regular-index sanity checks
4468 // for it.
4469 const DebugOnly<bool> child2IsNAC =
4470 closestCommonAncestorChild2->IsRootOfNativeAnonymousSubtree();
4471 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", 4476); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
")"); do { MOZ_CrashSequence(__null, 4476); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4472 !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", 4476); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
")"); do { MOZ_CrashSequence(__null, 4476); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4473 *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", 4476); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
")"); do { MOZ_CrashSequence(__null, 4476); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4474 *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", 4476); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
")"); do { MOZ_CrashSequence(__null, 4476); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4475 ->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", 4476); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
")"); do { MOZ_CrashSequence(__null, 4476); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4476 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", 4476); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
")"); do { MOZ_CrashSequence(__null, 4476); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4477 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", 4482); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4482); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4478 !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", 4482); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4482); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4479 *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", 4482); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4482); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4480 ->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", 4482); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4482); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4481 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", 4482); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4482); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4482 *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", 4482); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4482); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4483 return comp;
4484 }
4485
4486 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", 4486); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1" ")"); do { MOZ_CrashSequence
(__null, 4486); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4487 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", 4488); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aBoundary2.GetContainer()"
")"); do { MOZ_CrashSequence(__null, 4488); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4488 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", 4488); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aBoundary2.GetContainer()"
")"); do { MOZ_CrashSequence(__null, 4488); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4489 // FIXME: bug 1946003 and bug 1946008.
4490 if (MOZ_UNLIKELY(closestCommonAncestorChild1->IsDocumentFragment())(__builtin_expect(!!(closestCommonAncestorChild1->IsDocumentFragment
()), 0))
) {
4491 // XXX Keep the odd traditional behavior for now.
4492 return Some(-1);
4493 }
4494 // If the common ancestor is a shadow host, closestCommonAncestorChild1 must
4495 // be a child node of the host and we shouldn't handle the flattened tree.
4496 // Therefore, we can compare closestCommonAncestorChild1 and the child at
4497 // aBoundary2 can be compared within TreeKind::DOM tree.
4498 // NOTE: When aKind is TreeKind::FlatForSelection,
4499 // GetParentNodeForComparison returns the shadow host as the parent node
4500 // of a child node even if it's not assigned to any <slot>. Therefore, even
4501 // when we should return Nothing, we may return Some value for now.
4502 // Therefore, we need to relax this assertion for TreeKind::FlatForSelection
4503 // until fixing bug 2014622. And it's okay to compare the child nodes not a
4504 // part of flattened tree as in the DOM since anyway we return wrong value.
4505 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", 4508); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4508); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4506 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", 4508); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4508); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4507 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", 4508); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4508); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4508 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", 4508); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4508); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4509 const Maybe<int32_t> comp =
4510 nsContentUtils::CompareChildNodes<TreeKindToCompareChildren<aKind>()>(
4511 *closestCommonAncestor, closestCommonAncestorChild1,
4512 aBoundary2.GetChildAtOffset(), aIndexCache);
4513 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", 4515); MOZ_PretendNoReturn
(); } } while (0)
4514 "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", 4515); MOZ_PretendNoReturn
(); } } while (0)
4515 "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", 4515); MOZ_PretendNoReturn
(); } } while (0)
;
4516 if (NS_WARN_IF(comp.isNothing())NS_warn_if_impl(comp.isNothing(), "comp.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4516)
) {
4517 // XXX Keep the odd traditional behavior for now.
4518 return Some(-1);
4519 }
4520 // If the child of the closet common ancestor is at aBoundary2, it means that
4521 // aBoundary1 refers a descendant of the child. So, aBoundary1 refers a
4522 // descendant of aBoundary2.
4523 if (!*comp) {
4524 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", 4528); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4528); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4525 *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", 4528); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4528); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4526 ->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", 4528); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4528); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4527 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", 4528); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4528); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4528 *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", 4528); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4528); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4529 return Some(1);
4530 }
4531 // ComputeIndexInParentNode() is the index in the regular child list, which
4532 // native anonymous content is not part of. CompareChildNodes already ordered
4533 // NAC via GetIndexInParent, so skip the regular-index sanity checks for it.
4534 const DebugOnly<bool> child1IsNAC =
4535 closestCommonAncestorChild1->IsRootOfNativeAnonymousSubtree();
4536 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", 4541); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4541); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4537 !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", 4541); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4541); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4538 *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", 4541); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4541); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4539 ->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", 4541); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4541); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4540 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", 4541); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4541); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4541 *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", 4541); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4541); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4542 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", 4547); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
")"); do { MOZ_CrashSequence(__null, 4547); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4543 !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", 4547); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
")"); do { MOZ_CrashSequence(__null, 4547); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4544 *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", 4547); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
")"); do { MOZ_CrashSequence(__null, 4547); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4545 *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", 4547); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
")"); do { MOZ_CrashSequence(__null, 4547); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4546 ->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", 4547); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
")"); do { MOZ_CrashSequence(__null, 4547); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4547 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", 4547); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
")"); do { MOZ_CrashSequence(__null, 4547); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4548 return comp;
4549}
4550
4551inline bool IsCharInSet(const char* aSet, const char16_t aChar) {
4552 char16_t ch;
4553 while ((ch = *aSet)) {
4554 if (aChar == char16_t(ch)) {
4555 return true;
4556 }
4557 ++aSet;
4558 }
4559 return false;
4560}
4561
4562/**
4563 * This method strips leading/trailing chars, in given set, from string.
4564 */
4565
4566// static
4567const nsDependentSubstring nsContentUtils::TrimCharsInSet(
4568 const char* aSet, const nsAString& aValue) {
4569 nsAString::const_iterator valueCurrent, valueEnd;
4570
4571 aValue.BeginReading(valueCurrent);
4572 aValue.EndReading(valueEnd);
4573
4574 // Skip characters in the beginning
4575 while (valueCurrent != valueEnd) {
4576 if (!IsCharInSet(aSet, *valueCurrent)) {
4577 break;
4578 }
4579 ++valueCurrent;
4580 }
4581
4582 if (valueCurrent != valueEnd) {
4583 for (;;) {
4584 --valueEnd;
4585 if (!IsCharInSet(aSet, *valueEnd)) {
4586 break;
4587 }
4588 }
4589 ++valueEnd; // Step beyond the last character we want in the value.
4590 }
4591
4592 // valueEnd should point to the char after the last to copy
4593 return Substring(valueCurrent, valueEnd);
4594}
4595
4596/**
4597 * This method strips leading and trailing whitespace from a string.
4598 */
4599
4600// static
4601template <bool IsWhitespace(char16_t)>
4602const nsDependentSubstring nsContentUtils::TrimWhitespace(const nsAString& aStr,
4603 bool aTrimTrailing) {
4604 nsAString::const_iterator start, end;
4605
4606 aStr.BeginReading(start);
4607 aStr.EndReading(end);
4608
4609 // Skip whitespace characters in the beginning
4610 while (start != end && IsWhitespace(*start)) {
4611 ++start;
4612 }
4613
4614 if (aTrimTrailing) {
4615 // Skip whitespace characters in the end.
4616 while (end != start) {
4617 --end;
4618
4619 if (!IsWhitespace(*end)) {
4620 // Step back to the last non-whitespace character.
4621 ++end;
4622
4623 break;
4624 }
4625 }
4626 }
4627
4628 // Return a substring for the string w/o leading and/or trailing
4629 // whitespace
4630
4631 return Substring(start, end);
4632}
4633
4634// Declaring the templates we are going to use avoid linking issues without
4635// inlining the method. Considering there is not so much spaces checking
4636// methods we can consider this to be better than inlining.
4637template const nsDependentSubstring
4638nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(const nsAString&, bool);
4639template const nsDependentSubstring nsContentUtils::TrimWhitespace<
4640 nsContentUtils::IsHTMLWhitespace>(const nsAString&, bool);
4641template const nsDependentSubstring nsContentUtils::TrimWhitespace<
4642 nsContentUtils::IsHTMLWhitespaceOrNBSP>(const nsAString&, bool);
4643
4644static inline void KeyAppendSep(nsACString& aKey) {
4645 if (!aKey.IsEmpty()) {
4646 aKey.Append('>');
4647 }
4648}
4649
4650static inline void KeyAppendString(const nsAString& aString, nsACString& aKey) {
4651 KeyAppendSep(aKey);
4652
4653 // Could escape separator here if collisions happen. > is not a legal char
4654 // for a name or type attribute, so we should be safe avoiding that extra
4655 // work.
4656
4657 AppendUTF16toUTF8(aString, aKey);
4658}
4659
4660static inline void KeyAppendString(const nsACString& aString,
4661 nsACString& aKey) {
4662 KeyAppendSep(aKey);
4663
4664 // Could escape separator here if collisions happen. > is not a legal char
4665 // for a name or type attribute, so we should be safe avoiding that extra
4666 // work.
4667
4668 aKey.Append(aString);
4669}
4670
4671static inline void KeyAppendInt(int32_t aInt, nsACString& aKey) {
4672 KeyAppendSep(aKey);
4673
4674 aKey.AppendInt(aInt);
4675}
4676
4677static inline bool IsAutocompleteOff(const nsIContent* aContent) {
4678 return aContent->IsElement() &&
4679 aContent->AsElement()->AttrValueIs(kNameSpaceID_None,
4680 nsGkAtoms::autocomplete, u"off"_ns,
4681 eIgnoreCase);
4682}
4683
4684/*static*/
4685void nsContentUtils::GenerateStateKey(nsIContent* aContent, Document* aDocument,
4686 nsACString& aKey) {
4687 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"
, 4687); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { MOZ_CrashSequence(__null, 4687); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4688
4689 aKey.Truncate();
4690
4691 uint32_t partID = aDocument ? aDocument->GetPartID() : 0;
4692
4693 // Don't capture state for anonymous content
4694 if (aContent->IsInNativeAnonymousSubtree()) {
4695 return;
4696 }
4697
4698 if (IsAutocompleteOff(aContent)) {
4699 return;
4700 }
4701
4702 RefPtr<Document> doc = aContent->GetUncomposedDoc();
4703
4704 KeyAppendInt(partID, aKey); // first append a partID
4705 bool generatedUniqueKey = false;
4706
4707 if (doc && doc->IsHTMLOrXHTML()) {
4708 nsHTMLDocument* htmlDoc = doc->AsHTMLDocument();
4709
4710 // If we have a form control and can calculate form information, use that
4711 // as the key - it is more reliable than just recording position in the
4712 // DOM.
4713 // XXXbz Is it, really? We have bugs on this, I think...
4714 // Important to have a unique key, and tag/type/name may not be.
4715 //
4716 // The format of the key depends on whether the control has a form,
4717 // and whether the element was parser inserted:
4718 //
4719 // [Has Form, Parser Inserted]:
4720 // fp>type>FormNum>IndOfControlInForm>FormName>name
4721 //
4722 // [No Form, Parser Inserted]:
4723 // dp>type>ControlNum>name
4724 //
4725 // [Has Form, Not Parser Inserted]:
4726 // fn>type>IndOfFormInDoc>IndOfControlInForm>FormName>name
4727 //
4728 // [No Form, Not Parser Inserted]:
4729 // dn>type>IndOfControlInDoc>name
4730 //
4731 // XXX We don't need to use index if name is there
4732 // XXXbz We don't? Why not? I don't follow.
4733 //
4734 if (const auto* control = nsIFormControl::FromNode(aContent)) {
4735 // Get the control number if this was a parser inserted element from the
4736 // network.
4737 int32_t controlNumber =
4738 control->GetParserInsertedControlNumberForStateKey();
4739 bool parserInserted = controlNumber != -1;
4740
4741 RefPtr<ContentList> htmlForms;
4742 RefPtr<ContentList> htmlFormControls;
4743 if (!parserInserted) {
4744 // Getting these lists is expensive, as we need to keep them up to date
4745 // as the document loads, so we avoid it if we don't need them.
4746 htmlDoc->GetFormsAndFormControls(getter_AddRefs(htmlForms),
4747 getter_AddRefs(htmlFormControls));
4748 }
4749
4750 // Append the control type
4751 KeyAppendInt(int32_t(control->ControlType()), aKey);
4752
4753 // If in a form, add form name / index of form / index in form
4754 HTMLFormElement* formElement = control->GetFormInternal();
4755 if (formElement) {
4756 if (IsAutocompleteOff(formElement)) {
4757 aKey.Truncate();
4758 return;
4759 }
4760
4761 // Append the form number, if this is a parser inserted control, or
4762 // the index of the form in the document otherwise.
4763 bool appendedForm = false;
4764 if (parserInserted) {
4765 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", 4767
); 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, 4767); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4766 "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", 4767
); 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, 4767); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4767 "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", 4767
); 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, 4767); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4768 KeyAppendString("fp"_ns, aKey);
4769 KeyAppendInt(formElement->GetFormNumberForStateKey(), aKey);
4770 appendedForm = true;
4771 } else {
4772 KeyAppendString("fn"_ns, aKey);
4773 int32_t index = htmlForms->IndexOf(formElement);
4774 if (index <= -1) {
4775 //
4776 // XXX HACK this uses some state that was dumped into the document
4777 // specifically to fix bug 138892. What we are trying to do is
4778 // *guess* which form this control's state is found in, with the
4779 // highly likely guess that the highest form parsed so far is the
4780 // one. This code should not be on trunk, only branch.
4781 //
4782 index = htmlDoc->GetNumFormsSynchronous() - 1;
4783 }
4784 if (index > -1) {
4785 KeyAppendInt(index, aKey);
4786 appendedForm = true;
4787 }
4788 }
4789
4790 if (appendedForm) {
4791 // Append the index of the control in the form
4792 int32_t index = formElement->IndexOfContent(aContent);
4793
4794 if (index > -1) {
4795 KeyAppendInt(index, aKey);
4796 generatedUniqueKey = true;
4797 }
4798 }
4799
4800 // Append the form name
4801 nsAutoString formName;
4802 formElement->GetAttr(nsGkAtoms::name, formName);
4803 KeyAppendString(formName, aKey);
4804 } else {
4805 // Not in a form. Append the control number, if this is a parser
4806 // inserted control, or the index of the control in the document
4807 // otherwise.
4808 if (parserInserted) {
4809 KeyAppendString("dp"_ns, aKey);
4810 KeyAppendInt(control->GetParserInsertedControlNumberForStateKey(),
4811 aKey);
4812 generatedUniqueKey = true;
4813 } else {
4814 KeyAppendString("dn"_ns, aKey);
4815 int32_t index = htmlFormControls->IndexOf(aContent);
4816 if (index > -1) {
4817 KeyAppendInt(index, aKey);
4818 generatedUniqueKey = true;
4819 }
4820 }
4821
4822 // Append the control name
4823 nsAutoString name;
4824 aContent->AsElement()->GetAttr(nsGkAtoms::name, name);
4825 KeyAppendString(name, aKey);
4826 }
4827 }
4828 }
4829
4830 if (!generatedUniqueKey) {
4831 // Either we didn't have a form control or we aren't in an HTML document so
4832 // we can't figure out form info. Append the tag name if it's an element
4833 // to avoid restoring state for one type of element on another type.
4834 if (aContent->IsElement()) {
4835 KeyAppendString(nsDependentAtomString(aContent->NodeInfo()->NameAtom()),
4836 aKey);
4837 } else {
4838 // Append a character that is not "d" or "f" to disambiguate from
4839 // the case when we were a form control in an HTML document.
4840 KeyAppendString("o"_ns, aKey);
4841 }
4842
4843 // Now start at aContent and append the indices of it and all its ancestors
4844 // in their containers. That should at least pin down its position in the
4845 // DOM...
4846 nsINode* parent = aContent->GetParentNode();
4847 nsINode* content = aContent;
4848 while (parent) {
4849 if (content->IsShadowRoot()) {
4850 KeyAppendString("s"_ns, aKey);
4851 } else {
4852 KeyAppendInt(parent->ComputeIndexOf_Deprecated(content), aKey);
4853 }
4854 content = parent;
4855 parent = content->GetParentOrShadowHostNode();
4856 }
4857 }
4858}
4859
4860// static
4861nsIPrincipal* nsContentUtils::SubjectPrincipal(JSContext* aCx) {
4862 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", 4862); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 4862); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4863
4864 // As opposed to SubjectPrincipal(), we do in fact assume that
4865 // we're in a realm here; anyone who calls this function in
4866 // situations where that's not the case is doing it wrong.
4867 JS::Realm* realm = js::GetContextRealm(aCx);
4868 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"
, 4868); AnnotateMozCrashReason("MOZ_ASSERT" "(" "realm" ")")
; do { MOZ_CrashSequence(__null, 4868); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4869
4870 JSPrincipals* principals = JS::GetRealmPrincipals(realm);
4871 return nsJSPrincipals::get(principals);
4872}
4873
4874// static
4875nsIPrincipal* nsContentUtils::SubjectPrincipal() {
4876 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", 4876); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInitialized()" ")"); do { MOZ_CrashSequence
(__null, 4876); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4877 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", 4877); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 4877); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4878 JSContext* cx = GetCurrentJSContext();
4879 if (!cx) {
4880 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"
, 4882); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden" ")"); do { MOZ_CrashSequence(__null, 4882); __attribute__
((nomerge)) ::abort(); } while (false); } while (false)
4881 "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"
, 4882); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden" ")"); do { MOZ_CrashSequence(__null, 4882); __attribute__
((nomerge)) ::abort(); } while (false); } while (false)
4882 "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"
, 4882); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden" ")"); do { MOZ_CrashSequence(__null, 4882); __attribute__
((nomerge)) ::abort(); } while (false); } while (false)
;
4883 }
4884
4885 JS::Realm* realm = js::GetContextRealm(cx);
4886
4887 // When an AutoJSAPI is instantiated, we are in a null realm until the
4888 // first JSAutoRealm, which is kind of a purgatory as far as permissions
4889 // go. It would be nice to just hard-abort if somebody does a security check
4890 // in this purgatory zone, but that would be too fragile, since it could be
4891 // triggered by random IsCallerChrome() checks 20-levels deep.
4892 //
4893 // So we want to return _something_ here - and definitely not the System
4894 // Principal, since that would make an AutoJSAPI a very dangerous thing to
4895 // instantiate.
4896 //
4897 // The natural thing to return is a null principal. Ideally, we'd return a
4898 // different null principal each time, to avoid any unexpected interactions
4899 // when the principal accidentally gets inherited somewhere. But
4900 // SubjectPrincipal doesn't return strong references, so there's no way to
4901 // sanely manage the lifetime of multiple null principals.
4902 //
4903 // So we use a singleton null principal. To avoid it being accidentally
4904 // inherited and becoming a "real" subject or object principal, we do a
4905 // release-mode assert during realm creation against using this principal on
4906 // an actual global.
4907 if (!realm) {
4908 return sNullSubjectPrincipal;
4909 }
4910
4911 return SubjectPrincipal(cx);
4912}
4913
4914// static
4915nsIPrincipal* nsContentUtils::ObjectPrincipal(JSObject* aObj) {
4916#ifdef DEBUG1
4917 JS::AssertObjectBelongsToCurrentThread(aObj);
4918#endif
4919
4920 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"
, 4920); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!js::IsCrossCompartmentWrapper(aObj)"
")"); do { MOZ_CrashSequence(__null, 4920); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4921
4922 JS::Realm* realm = js::GetNonCCWObjectRealm(aObj);
4923 JSPrincipals* principals = JS::GetRealmPrincipals(realm);
4924 return nsJSPrincipals::get(principals);
4925}
4926
4927// static
4928nsresult nsContentUtils::NewURIWithDocumentCharset(nsIURI** aResult,
4929 const nsAString& aSpec,
4930 Document* aDocument,
4931 nsIURI* aBaseURI) {
4932 if (aDocument) {
4933 return NS_NewURI(aResult, aSpec, aDocument->GetDocumentCharacterSet(),
4934 aBaseURI);
4935 }
4936 return NS_NewURI(aResult, aSpec, nullptr, aBaseURI);
4937}
4938
4939// static
4940bool nsContentUtils::ContainsChar(nsAtom* aAtom, char aChar) {
4941 const uint32_t len = aAtom->GetLength();
4942 if (!len) {
4943 return false;
4944 }
4945 const char16_t* name = aAtom->GetUTF16String();
4946 uint32_t i = 0;
4947 while (i < len) {
4948 if (name[i] == aChar) {
4949 return true;
4950 }
4951 i++;
4952 }
4953 return false;
4954}
4955
4956// static
4957bool nsContentUtils::IsNameWithDash(nsAtom* aName) {
4958 // A valid custom element name is a sequence of characters name which
4959 // must match the PotentialCustomElementName production:
4960 // PotentialCustomElementName ::= [a-z] (PCENChar)* '-' (PCENChar)*
4961 const char16_t* name = aName->GetUTF16String();
4962 uint32_t len = aName->GetLength();
4963 bool hasDash = false;
4964
4965 // A string name is a valid custom element name if all of the following are
4966 // true:
4967
4968 // name's 0th code point is an ASCII lower alpha;
4969 if (!len || name[0] < 'a' || name[0] > 'z') {
4970 return false;
4971 }
4972
4973 uint32_t i = 1;
4974 while (i < len) {
4975 // name does not contain any ASCII upper alphas
4976 if (name[i] >= 'A' && name[i] <= 'Z') {
4977 return false;
4978 }
4979
4980 // name is a valid element local name;
4981 //
4982 // // https://dom.spec.whatwg.org/#valid-element-local-name
4983 // Step 2.1.
4984 // If name contains ASCII whitespace, U+0000 NULL, U+002F (/), or U+003E
4985 // (>), then return false.
4986 //
4987 // ASCII whitespace is U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, or
4988 // U+0020 SPACE.
4989 if (name[i] == 0x0000 || // null
4990 name[i] == 0x0009 || // tab
4991 name[i] == 0x000A || // newline
4992 name[i] == 0x000C || // form feed
4993 name[i] == 0x000D || // carriage return
4994 name[i] == 0x0020 || // space
4995 name[i] == 0x002F || // /
4996 name[i] == 0x003E) { // >
4997 return false;
4998 }
4999
5000 if (name[i] == '-') {
5001 hasDash = true;
5002 }
5003
5004 i++;
5005 }
5006 return hasDash;
5007}
5008
5009// static
5010bool nsContentUtils::IsCustomElementName(nsAtom* aName, uint32_t aNameSpaceID) {
5011 // Allow non-dashed names in XUL for XBL to Custom Element migrations.
5012 if (aNameSpaceID == kNameSpaceID_XUL8) {
5013 return true;
5014 }
5015
5016 bool hasDash = IsNameWithDash(aName);
5017 if (!hasDash) {
5018 return false;
5019 }
5020
5021 // The custom element name must not be one of the following values:
5022 // annotation-xml
5023 // color-profile
5024 // font-face
5025 // font-face-src
5026 // font-face-uri
5027 // font-face-format
5028 // font-face-name
5029 // missing-glyph
5030 return aName != nsGkAtoms::annotation_xml &&
5031 aName != nsGkAtoms::color_profile && aName != nsGkAtoms::font_face &&
5032 aName != nsGkAtoms::font_face_src &&
5033 aName != nsGkAtoms::font_face_uri &&
5034 aName != nsGkAtoms::font_face_format &&
5035 aName != nsGkAtoms::font_face_name && aName != nsGkAtoms::missingGlyph;
5036}
5037
5038bool nsContentUtils::IsValidShadowHostName(nsAtom* aName,
5039 uint32_t aNameSpaceID) {
5040 return IsCustomElementName(aName, aNameSpaceID) ||
5041 aName == nsGkAtoms::article || aName == nsGkAtoms::aside ||
5042 aName == nsGkAtoms::blockquote || aName == nsGkAtoms::body ||
5043 aName == nsGkAtoms::div || aName == nsGkAtoms::footer ||
5044 aName == nsGkAtoms::h1 || aName == nsGkAtoms::h2 ||
5045 aName == nsGkAtoms::h3 || aName == nsGkAtoms::h4 ||
5046 aName == nsGkAtoms::h5 || aName == nsGkAtoms::h6 ||
5047 aName == nsGkAtoms::header || aName == nsGkAtoms::main ||
5048 aName == nsGkAtoms::nav || aName == nsGkAtoms::p ||
5049 aName == nsGkAtoms::section || aName == nsGkAtoms::span;
5050}
5051
5052// static
5053nsresult nsContentUtils::CheckQName(const nsAString& aQualifiedName,
5054 bool aNamespaceAware,
5055 const char16_t** aColon) {
5056 const char* colon = nullptr;
5057 const char16_t* begin = aQualifiedName.BeginReading();
5058 const char16_t* end = aQualifiedName.EndReading();
5059
5060 int result = MOZ_XMLCheckQName(reinterpret_cast<const char*>(begin),
5061 reinterpret_cast<const char*>(end),
5062 aNamespaceAware, &colon);
5063
5064 if (!result) {
5065 if (aColon) {
5066 *aColon = reinterpret_cast<const char16_t*>(colon);
5067 }
5068
5069 return NS_OK;
5070 }
5071
5072 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5073}
5074
5075static inline bool IsValidRestrictedContinuation(char16_t c) {
5076 return mozilla::IsAsciiAlpha(c) || mozilla::IsAsciiDigit(c) || c == '-' ||
5077 c == '.' || c == ':' || c == '_' || c >= 0x80;
5078}
5079
5080// static
5081// https://dom.spec.whatwg.org/#valid-element-local-name
5082// Two paths:
5083// 1. Starts with [A-Za-z]: continuation can be any char except
5084// null/whitespace/>/'/'
5085// 2. Starts with [:_>=0x80]: continuation must be [A-Za-z0-9-.:_>=0x80]
5086bool nsContentUtils::IsValidElementLocalName(const nsAString& aName) {
5087 if (aName.IsEmpty()) {
5088 return false;
5089 }
5090
5091 const char16_t* ptr = aName.BeginReading();
5092 const char16_t* end = aName.EndReading();
5093 char16_t first = *ptr;
5094
5095 if (mozilla::IsAsciiAlpha(first)) {
5096 // Path 1: ASCII alpha start - any continuation except forbidden chars.
5097 for (++ptr; ptr < end; ++ptr) {
5098 char16_t c = *ptr;
5099 if (c == 0 || IsHTMLWhitespace(c) || c == '/' || c == '>') {
5100 return false;
5101 }
5102 }
5103 return true;
5104 }
5105
5106 if (first == ':' || first == '_' || first >= 0x80) {
5107 // Path 2: Colon, underscore, or non-ASCII start - restricted continuation.
5108 for (++ptr; ptr < end; ++ptr) {
5109 if (!IsValidRestrictedContinuation(*ptr)) {
5110 return false;
5111 }
5112 }
5113 return true;
5114 }
5115
5116 // Starting with anything else (e.g., digits, other ASCII) is invalid.
5117 return false;
5118}
5119
5120// static
5121// https://dom.spec.whatwg.org/#valid-attribute-local-name
5122bool nsContentUtils::IsValidAttributeLocalName(const nsAString& aName) {
5123 if (aName.IsEmpty()) {
5124 return false;
5125 }
5126 for (const char16_t* ptr = aName.BeginReading(); ptr < aName.EndReading();
5127 ptr++) {
5128 char16_t c = *ptr;
5129 if (c == 0 || IsHTMLWhitespace(c) || c == '>' || c == '/' || c == '=') {
5130 return false;
5131 }
5132 }
5133 return true;
5134}
5135
5136// static
5137// https://dom.spec.whatwg.org/#valid-namespace-prefix
5138bool nsContentUtils::IsValidNamespacePrefix(const nsAString& aPrefix) {
5139 // Empty prefix is valid (means no prefix).
5140 if (aPrefix.IsEmpty()) {
5141 return true;
5142 }
5143 for (const char16_t* ptr = aPrefix.BeginReading(); ptr < aPrefix.EndReading();
5144 ptr++) {
5145 char16_t c = *ptr;
5146 if (c == 0 || IsHTMLWhitespace(c) || c == '/' || c == '>') {
5147 return false;
5148 }
5149 }
5150 return true;
5151}
5152
5153// static
5154// https://dom.spec.whatwg.org/#valid-doctype-name
5155bool nsContentUtils::IsValidDoctypeName(const nsAString& aName) {
5156 // Empty doctype name is valid per spec (it just can't contain bad chars).
5157 for (const char16_t* ptr = aName.BeginReading(); ptr < aName.EndReading();
5158 ptr++) {
5159 char16_t c = *ptr;
5160 if (c == 0 || IsHTMLWhitespace(c) || c == '>') {
5161 return false;
5162 }
5163 }
5164 return true;
5165}
5166
5167// static
5168// https://dom.spec.whatwg.org/#validate-and-extract
5169// This implements only the validation and parsing portion of the algorithm.
5170// Namespace resolution (steps involving namespace lookups) is handled by
5171// callers.
5172nsresult nsContentUtils::ParseQualifiedNameRelaxed(
5173 const nsAString& aQualifiedName, uint16_t aNodeType,
5174 const char16_t** aColon, const char16_t** aLocalNameEnd) {
5175 if (aColon) {
5176 *aColon = nullptr;
5177 }
5178 if (aLocalNameEnd) {
5179 *aLocalNameEnd = nullptr;
5180 }
5181
5182 if (aQualifiedName.IsEmpty()) {
5183 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5184 }
5185
5186 const char16_t* begin = aQualifiedName.BeginReading();
5187 const char16_t* end = aQualifiedName.EndReading();
5188 const char16_t* firstColon = nullptr;
5189
5190 for (const char16_t* ptr = begin; ptr < end; ptr++) {
5191 if (*ptr == ':') {
5192 firstColon = ptr;
5193 break;
5194 }
5195 }
5196
5197 if (firstColon) {
5198 nsDependentSubstring prefix(begin, firstColon);
5199
5200 if (prefix.IsEmpty()) {
5201 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5202 }
5203
5204 if (!IsValidNamespacePrefix(prefix)) {
5205 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5206 }
5207
5208 // Local name is everything after the first colon.
5209 nsDependentSubstring localName(firstColon + 1, end);
5210
5211 // Local name must not be empty.
5212 if (localName.IsEmpty()) {
5213 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5214 }
5215
5216 // Validate local name based on node type.
5217 if (aNodeType == nsINode::ATTRIBUTE_NODE) {
5218 if (!IsValidAttributeLocalName(localName)) {
5219 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5220 }
5221 } else {
5222 if (!IsValidElementLocalName(localName)) {
5223 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5224 }
5225 }
5226
5227 if (aColon) {
5228 *aColon = firstColon;
5229 }
5230 if (aLocalNameEnd) {
5231 *aLocalNameEnd = end;
5232 }
5233 } else {
5234 // No colon, the whole string is the local name.
5235 if (aNodeType == nsINode::ATTRIBUTE_NODE) {
5236 if (!IsValidAttributeLocalName(aQualifiedName)) {
5237 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5238 }
5239 } else {
5240 if (!IsValidElementLocalName(aQualifiedName)) {
5241 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5242 }
5243 }
5244 }
5245
5246 return NS_OK;
5247}
5248
5249// static
5250nsresult nsContentUtils::SplitQName(const nsIContent* aNamespaceResolver,
5251 const nsString& aQName, int32_t* aNamespace,
5252 nsAtom** aLocalName) {
5253 const char16_t* colon;
5254 nsresult rv = nsContentUtils::CheckQName(aQName, true, &colon);
5255 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"
, 5255); return rv; } } while (false)
;
5256
5257 if (colon) {
5258 const char16_t* end;
5259 aQName.EndReading(end);
5260 nsAutoString nameSpace;
5261 rv = aNamespaceResolver->LookupNamespaceURIInternal(
5262 Substring(aQName.get(), colon), nameSpace);
5263 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"
, 5263); return rv; } } while (false)
;
5264
5265 *aNamespace = nsNameSpaceManager::GetInstance()->GetNameSpaceID(
5266 nameSpace, nsContentUtils::IsChromeDoc(aNamespaceResolver->OwnerDoc()));
5267 if (*aNamespace == kNameSpaceID_Unknown-1) return NS_ERROR_FAILURE;
5268
5269 *aLocalName = NS_AtomizeMainThread(Substring(colon + 1, end)).take();
5270 } else {
5271 *aNamespace = kNameSpaceID_None;
5272 *aLocalName = NS_AtomizeMainThread(aQName).take();
5273 }
5274 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", 5274
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
5275 return NS_OK;
5276}
5277
5278// static
5279nsresult nsContentUtils::GetNodeInfoFromQName(
5280 const nsAString& aNamespaceURI, const nsAString& aQualifiedName,
5281 nsNodeInfoManager* aNodeInfoManager, uint16_t aNodeType,
5282 mozilla::dom::NodeInfo** aNodeInfo) {
5283 const nsString& qName = PromiseFlatStringTPromiseFlatString<char16_t>(aQualifiedName);
5284 const char16_t* colon;
5285 const char16_t* localNameEnd;
5286 nsresult rv = nsContentUtils::ParseQualifiedNameRelaxed(
5287 qName, aNodeType, &colon, &localNameEnd);
5288 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"
, 5288); return rv; } } while (false)
;
5289
5290 int32_t nsID;
5291 nsNameSpaceManager::GetInstance()->RegisterNameSpace(aNamespaceURI, nsID);
5292 if (colon) {
5293 RefPtr<nsAtom> prefix = NS_AtomizeMainThread(Substring(qName.get(), colon));
5294
5295 rv = aNodeInfoManager->GetNodeInfo(Substring(colon + 1, localNameEnd),
5296 prefix, nsID, aNodeType, aNodeInfo);
5297 } else {
5298 rv = aNodeInfoManager->GetNodeInfo(aQualifiedName, nullptr, nsID, aNodeType,
5299 aNodeInfo);
5300 }
5301 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"
, 5301); return rv; } } while (false)
;
5302
5303 return nsContentUtils::IsValidNodeName((*aNodeInfo)->NameAtom(),
5304 (*aNodeInfo)->GetPrefixAtom(),
5305 (*aNodeInfo)->NamespaceID())
5306 ? NS_OK
5307 : NS_ERROR_DOM_NAMESPACE_ERR;
5308}
5309
5310// static
5311void nsContentUtils::SplitExpatName(const char16_t* aExpatName,
5312 nsAtom** aPrefix, nsAtom** aLocalName,
5313 int32_t* aNameSpaceID) {
5314 /**
5315 * Expat can send the following:
5316 * localName
5317 * namespaceURI<separator>localName
5318 * namespaceURI<separator>localName<separator>prefix
5319 *
5320 * and we use 0xFFFF for the <separator>.
5321 *
5322 */
5323
5324 const char16_t* uriEnd = nullptr;
5325 const char16_t* nameEnd = nullptr;
5326 const char16_t* pos;
5327 for (pos = aExpatName; *pos; ++pos) {
5328 if (*pos == 0xFFFF) {
5329 if (uriEnd) {
5330 nameEnd = pos;
5331 } else {
5332 uriEnd = pos;
5333 }
5334 }
5335 }
5336
5337 const char16_t* nameStart;
5338 if (uriEnd) {
5339 nsNameSpaceManager::GetInstance()->RegisterNameSpace(
5340 nsDependentSubstring(aExpatName, uriEnd), *aNameSpaceID);
5341
5342 nameStart = (uriEnd + 1);
5343 if (nameEnd) {
5344 const char16_t* prefixStart = nameEnd + 1;
5345 *aPrefix = NS_AtomizeMainThread(Substring(prefixStart, pos)).take();
5346 } else {
5347 nameEnd = pos;
5348 *aPrefix = nullptr;
5349 }
5350 } else {
5351 *aNameSpaceID = kNameSpaceID_None;
5352 nameStart = aExpatName;
5353 nameEnd = pos;
5354 *aPrefix = nullptr;
5355 }
5356 *aLocalName = NS_AtomizeMainThread(Substring(nameStart, nameEnd)).take();
5357}
5358
5359// static
5360PresShell* nsContentUtils::GetPresShellForContent(const nsIContent* aContent) {
5361 Document* doc = aContent->GetComposedDoc();
5362 if (!doc) {
5363 return nullptr;
5364 }
5365 return doc->GetPresShell();
5366}
5367
5368// static
5369nsPresContext* nsContentUtils::GetContextForContent(
5370 const nsIContent* aContent) {
5371 PresShell* presShell = GetPresShellForContent(aContent);
5372 if (!presShell) {
5373 return nullptr;
5374 }
5375 return presShell->GetPresContext();
5376}
5377
5378// static
5379bool nsContentUtils::IsInPrivateBrowsing(nsILoadGroup* aLoadGroup) {
5380 if (!aLoadGroup) {
5381 return false;
5382 }
5383 // See duplicated code in Document::Reset/ResetToURI
5384 bool isPrivate = false;
5385 nsCOMPtr<nsIInterfaceRequestor> callbacks;
5386 aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
5387 if (callbacks) {
5388 nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
5389 isPrivate = loadContext && loadContext->UsePrivateBrowsing();
5390 }
5391 return isPrivate;
5392}
5393
5394// FIXME(emilio): This is (effectively) almost but not quite the same as
5395// Document::ShouldLoadImages(), which one is right?
5396bool nsContentUtils::DocumentInactiveForImageLoads(Document* aDocument) {
5397 if (!aDocument) {
5398 return false;
5399 }
5400 if (IsChromeDoc(aDocument) || aDocument->IsResourceDoc() ||
5401 aDocument->IsStaticDocument()) {
5402 return false;
5403 }
5404 nsCOMPtr<nsPIDOMWindowInner> win =
5405 do_QueryInterface(aDocument->GetScopeObject());
5406 return !win || !win->GetDocShell();
5407}
5408
5409imgLoader* nsContentUtils::GetImgLoaderForDocument(Document* aDoc) {
5410 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"
, 5410); return nullptr; } } while (false)
;
5411
5412 if (!aDoc) {
5413 return imgLoader::NormalLoader();
5414 }
5415 const bool isPrivate = aDoc->IsInPrivateBrowsing();
5416 return isPrivate ? imgLoader::PrivateBrowsingLoader()
5417 : imgLoader::NormalLoader();
5418}
5419
5420// static
5421imgLoader* nsContentUtils::GetImgLoaderForChannel(nsIChannel* aChannel,
5422 Document* aContext) {
5423 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", 5423); return
nullptr; } } while (false)
;
5424
5425 if (!aChannel) {
5426 return imgLoader::NormalLoader();
5427 }
5428 return NS_UsePrivateBrowsing(aChannel) ? imgLoader::PrivateBrowsingLoader()
5429 : imgLoader::NormalLoader();
5430}
5431
5432// static
5433int32_t nsContentUtils::CORSModeToLoadImageFlags(mozilla::CORSMode aMode) {
5434 switch (aMode) {
5435 case CORS_ANONYMOUS:
5436 return imgILoader::LOAD_CORS_ANONYMOUS;
5437 case CORS_USE_CREDENTIALS:
5438 return imgILoader::LOAD_CORS_USE_CREDENTIALS;
5439 default:
5440 return 0;
5441 }
5442}
5443
5444// static
5445nsresult nsContentUtils::LoadImage(
5446 nsIURI* aURI, nsINode* aContext, Document* aLoadingDocument,
5447 nsIPrincipal* aLoadingPrincipal, uint64_t aRequestContextID,
5448 nsIReferrerInfo* aReferrerInfo, imgINotificationObserver* aObserver,
5449 int32_t aLoadFlags, const nsAString& initiatorType,
5450 imgRequestProxy** aRequest, nsContentPolicyType aContentPolicyType,
5451 bool aUseUrgentStartForChannel, bool aLinkPreload,
5452 uint64_t aEarlyHintPreloaderId,
5453 mozilla::dom::FetchPriority aFetchPriority) {
5454 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", 5454); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aURI" ") (" "Must have a URI" ")"); do { MOZ_CrashSequence
(__null, 5454); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5455 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", 5455
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContext" ") (" "Must have a context"
")"); do { MOZ_CrashSequence(__null, 5455); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5456 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"
, 5456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingDocument"
") (" "Must have a document" ")"); do { MOZ_CrashSequence(__null
, 5456); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
5457 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"
, 5457); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Must have a principal" ")"); do { MOZ_CrashSequence(__null
, 5457); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
5458 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", 5458
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest" ") (" "Null out param"
")"); do { MOZ_CrashSequence(__null, 5458); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5459
5460 imgLoader* imgLoader = GetImgLoaderForDocument(aLoadingDocument);
5461 if (!imgLoader) {
5462 // nothing we can do here
5463 return NS_ERROR_FAILURE;
5464 }
5465
5466 nsCOMPtr<nsILoadGroup> loadGroup = aLoadingDocument->GetDocumentLoadGroup();
5467
5468 nsIURI* documentURI = aLoadingDocument->GetDocumentURI();
5469
5470 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"
, 5471); MOZ_PretendNoReturn(); } } while (0)
5471 "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"
, 5471); MOZ_PretendNoReturn(); } } while (0)
;
5472
5473 // XXXbz using "documentURI" for the initialDocumentURI is not quite
5474 // right, but the best we can do here...
5475 return imgLoader->LoadImage(aURI, /* uri to load */
5476 documentURI, /* initialDocumentURI */
5477 aReferrerInfo, /* referrerInfo */
5478 aLoadingPrincipal, /* loading principal */
5479 aRequestContextID, /* request context ID */
5480 loadGroup, /* loadgroup */
5481 aObserver, /* imgINotificationObserver */
5482 aContext, /* loading context */
5483 aLoadingDocument, /* uniquification key */
5484 aLoadFlags, /* load flags */
5485 nullptr, /* cache key */
5486 aContentPolicyType, /* content policy type */
5487 initiatorType, /* the load initiator */
5488 aUseUrgentStartForChannel, /* urgent-start flag */
5489 aLinkPreload, /* <link preload> initiator */
5490 aEarlyHintPreloaderId, aFetchPriority, aRequest);
5491}
5492
5493// static
5494already_AddRefed<imgIContainer> nsContentUtils::GetImageFromContent(
5495 nsIImageLoadingContent* aContent, imgIRequest** aRequest) {
5496 if (aRequest) {
5497 *aRequest = nullptr;
5498 }
5499
5500 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", 5500); return
nullptr; } } while (false)
;
5501
5502 nsCOMPtr<imgIRequest> imgRequest;
5503 aContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
5504 getter_AddRefs(imgRequest));
5505 if (!imgRequest) {
5506 return nullptr;
5507 }
5508
5509 nsCOMPtr<imgIContainer> imgContainer;
5510 imgRequest->GetImage(getter_AddRefs(imgContainer));
5511
5512 if (!imgContainer) {
5513 return nullptr;
5514 }
5515
5516 if (aRequest) {
5517 // If the consumer wants the request, verify it has actually loaded
5518 // successfully.
5519 uint32_t imgStatus;
5520 imgRequest->GetImageStatus(&imgStatus);
5521 if (imgStatus & imgIRequest::STATUS_FRAME_COMPLETE &&
5522 !(imgStatus & imgIRequest::STATUS_ERROR)) {
5523 imgRequest.swap(*aRequest);
5524 }
5525 }
5526
5527 return imgContainer.forget();
5528}
5529
5530static bool IsLinkWithURI(const nsIContent& aContent) {
5531 const auto* element = Element::FromNode(aContent);
5532 if (!element || !element->IsLink()) {
5533 return false;
5534 }
5535 nsCOMPtr<nsIURI> absURI = element->GetHrefURI();
5536 return !!absURI;
5537}
5538
5539static bool HasImageRequest(nsIContent& aContent) {
5540 nsCOMPtr<nsIImageLoadingContent> imageContent(do_QueryInterface(&aContent));
5541 if (!imageContent) {
5542 return false;
5543 }
5544
5545 nsCOMPtr<imgIRequest> imgRequest;
5546 imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
5547 getter_AddRefs(imgRequest));
5548
5549 // XXXbz It may be draggable even if the request resulted in an error. Why?
5550 // Not sure; that's what the old nsContentAreaDragDrop/nsFrame code did.
5551 return !!imgRequest;
5552}
5553
5554static Maybe<bool> DraggableOverride(const nsIContent& aContent) {
5555 if (auto* el = nsGenericHTMLElement::FromNode(aContent)) {
5556 if (el->Draggable()) {
5557 return Some(true);
5558 }
5559
5560 if (el->AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable,
5561 nsGkAtoms::_false, eIgnoreCase)) {
5562 return Some(false);
5563 }
5564 }
5565 if (aContent.IsSVGElement()) {
5566 return Some(false);
5567 }
5568 return Nothing();
5569}
5570
5571// static
5572bool nsContentUtils::ContentIsDraggable(nsIContent* aContent) {
5573 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"
, 5573); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { MOZ_CrashSequence(__null, 5573); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5574
5575 if (auto draggable = DraggableOverride(*aContent)) {
5576 return *draggable;
5577 }
5578
5579 // special handling for content area image and link dragging
5580 return HasImageRequest(*aContent) || IsLinkWithURI(*aContent);
5581}
5582
5583// static
5584bool nsContentUtils::IsDraggableImage(nsIContent* aContent) {
5585 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"
, 5585); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { MOZ_CrashSequence(__null, 5585); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5586 return HasImageRequest(*aContent) &&
5587 DraggableOverride(*aContent).valueOr(true);
5588}
5589
5590// static
5591bool nsContentUtils::IsDraggableLink(const nsIContent* aContent) {
5592 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"
, 5592); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { MOZ_CrashSequence(__null, 5592); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5593 return IsLinkWithURI(*aContent) && DraggableOverride(*aContent).valueOr(true);
5594}
5595
5596// static
5597nsresult nsContentUtils::QNameChanged(mozilla::dom::NodeInfo* aNodeInfo,
5598 nsAtom* aName,
5599 mozilla::dom::NodeInfo** aResult) {
5600 nsNodeInfoManager* niMgr = aNodeInfo->NodeInfoManager();
5601
5602 *aResult = niMgr
5603 ->GetNodeInfo(aName, nullptr, aNodeInfo->NamespaceID(),
5604 aNodeInfo->NodeType(), aNodeInfo->GetExtraName())
5605 .take();
5606 return NS_OK;
5607}
5608
5609static bool TestSitePerm(nsIPrincipal* aPrincipal, const nsACString& aType,
5610 uint32_t aPerm, bool aExactHostMatch) {
5611 if (!aPrincipal) {
5612 // We always deny (i.e. don't allow) the permission if we don't have a
5613 // principal.
5614 return aPerm != nsIPermissionManager::ALLOW_ACTION;
5615 }
5616
5617 nsCOMPtr<nsIPermissionManager> permMgr =
5618 components::PermissionManager::Service();
5619 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", 5619); return
false; } } while (false)
;
5620
5621 uint32_t perm;
5622 nsresult rv;
5623 if (aExactHostMatch) {
5624 rv = permMgr->TestExactPermissionFromPrincipal(aPrincipal, aType, &perm);
5625 } else {
5626 rv = permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &perm);
5627 }
5628 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"
, 5628); return false; } } while (false)
;
5629
5630 return perm == aPerm;
5631}
5632
5633bool nsContentUtils::IsSitePermAllow(nsIPrincipal* aPrincipal,
5634 const nsACString& aType) {
5635 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION,
5636 false);
5637}
5638
5639bool nsContentUtils::IsSitePermDeny(nsIPrincipal* aPrincipal,
5640 const nsACString& aType) {
5641 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION,
5642 false);
5643}
5644
5645bool nsContentUtils::IsExactSitePermAllow(nsIPrincipal* aPrincipal,
5646 const nsACString& aType) {
5647 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION,
5648 true);
5649}
5650
5651bool nsContentUtils::IsExactSitePermDeny(nsIPrincipal* aPrincipal,
5652 const nsACString& aType) {
5653 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION,
5654 true);
5655}
5656
5657bool nsContentUtils::HasSitePerm(nsIPrincipal* aPrincipal,
5658 const nsACString& aType) {
5659 if (!aPrincipal) {
5660 return false;
5661 }
5662
5663 nsCOMPtr<nsIPermissionManager> permMgr =
5664 components::PermissionManager::Service();
5665 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", 5665); return
false; } } while (false)
;
5666
5667 uint32_t perm;
5668 nsresult rv = permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &perm);
5669 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"
, 5669); return false; } } while (false)
;
5670
5671 return perm != nsIPermissionManager::UNKNOWN_ACTION;
5672}
5673
5674static const char* gEventNames[] = {"event"};
5675static const char* gSVGEventNames[] = {"evt"};
5676// for b/w compat, the first name to onerror is still 'event', even though it
5677// is actually the error message
5678static const char* gOnErrorNames[] = {"event", "source", "lineno", "colno",
5679 "error"};
5680
5681// static
5682void nsContentUtils::GetEventArgNames(int32_t aNameSpaceID, nsAtom* aEventName,
5683 bool aIsForWindow, uint32_t* aArgCount,
5684 const char*** aArgArray) {
5685#define SET_EVENT_ARG_NAMES(names)*aArgCount = sizeof(names) / sizeof(names[0]); *aArgArray = names
;
\
5686 *aArgCount = sizeof(names) / sizeof(names[0]); \
5687 *aArgArray = names;
5688
5689 // JSEventHandler is what does the arg magic for onerror, and it does
5690 // not seem to take the namespace into account. So we let onerror in all
5691 // namespaces get the 3 arg names.
5692 if (aEventName == nsGkAtoms::onerror && aIsForWindow) {
5693 SET_EVENT_ARG_NAMES(gOnErrorNames)*aArgCount = sizeof(gOnErrorNames) / sizeof(gOnErrorNames[0])
; *aArgArray = gOnErrorNames;
;
5694 } else if (aNameSpaceID == kNameSpaceID_SVG9) {
5695 SET_EVENT_ARG_NAMES(gSVGEventNames)*aArgCount = sizeof(gSVGEventNames) / sizeof(gSVGEventNames[0
]); *aArgArray = gSVGEventNames;
;
5696 } else {
5697 SET_EVENT_ARG_NAMES(gEventNames)*aArgCount = sizeof(gEventNames) / sizeof(gEventNames[0]); *aArgArray
= gEventNames;
;
5698 }
5699}
5700
5701// Note: The list of content bundles in nsStringBundle.cpp should be updated
5702// whenever entries are added or removed from this list.
5703static const char* gPropertiesFiles[kPropertiesFileCount] = {
5704 // Must line up with the enum values in |PropertiesFile| enum.
5705 "chrome://global/locale/css.properties",
5706 "chrome://global/locale/xul.properties",
5707 "chrome://global/locale/layout_errors.properties",
5708 "chrome://global/locale/layout/HtmlForm.properties",
5709 "chrome://global/locale/printing.properties",
5710 "chrome://global/locale/dom/dom.properties",
5711 "chrome://global/locale/layout/htmlparser.properties",
5712 "chrome://global/locale/svg/svg.properties",
5713 "chrome://branding/locale/brand.properties",
5714 "chrome://global/locale/commonDialogs.properties",
5715 "chrome://global/locale/mathml/mathml.properties",
5716 "chrome://global/locale/security/security.properties",
5717 "chrome://necko/locale/necko.properties",
5718 "resource://gre/res/locale/layout/HtmlForm.properties",
5719 "resource://gre/res/locale/dom/dom.properties",
5720 "resource://gre/res/locale/necko/necko.properties",
5721};
5722
5723/* static */
5724nsresult nsContentUtils::EnsureStringBundle(PropertiesFile aFile) {
5725 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"
, 5726); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "NS_IsMainThread()"
") (" "Should not create bundles off main thread." ")"); do {
MOZ_CrashSequence(__null, 5726); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5726 "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"
, 5726); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "NS_IsMainThread()"
") (" "Should not create bundles off main thread." ")"); do {
MOZ_CrashSequence(__null, 5726); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5727 if (!sStringBundles[size_t(aFile)]) {
5728 if (!sStringBundleService) {
5729 nsresult rv =
5730 CallGetService(NS_STRINGBUNDLE_CONTRACTID"@mozilla.org/intl/stringbundle;1", &sStringBundleService);
5731 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"
, 5731); return rv; } } while (false)
;
5732 }
5733 RefPtr<nsIStringBundle> bundle;
5734 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(); })
5735 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(); })
;
5736 sStringBundles[size_t(aFile)] = bundle.forget();
5737 }
5738 return NS_OK;
5739}
5740
5741/* static */
5742void nsContentUtils::AsyncPrecreateStringBundles() {
5743 // We only ever want to pre-create bundles in the parent process.
5744 //
5745 // All nsContentUtils bundles are shared between the parent and child
5746 // precesses, and the shared memory regions that back them *must* be created
5747 // in the parent, and then sent to all children.
5748 //
5749 // If we attempt to create a bundle in the child before its memory region is
5750 // available, we need to create a temporary non-shared bundle, and later
5751 // replace that with the shared memory copy. So attempting to pre-load in the
5752 // child is wasteful and unnecessary.
5753 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", 5753); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "XRE_IsParentProcess()" ")"); do { MOZ_CrashSequence
(__null, 5753); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5754
5755 for (size_t bundleIndex = 0; bundleIndex < kPropertiesFileCount;
5756 ++bundleIndex) {
5757 nsresult rv = NS_DispatchToCurrentThreadQueue(
5758 NS_NewRunnableFunction("AsyncPrecreateStringBundles",
5759 [bundleIndex]() {
5760 PropertiesFile file =
5761 static_cast<PropertiesFile>(bundleIndex);
5762 EnsureStringBundle(file);
5763 nsIStringBundle* bundle =
5764 sStringBundles[size_t(file)];
5765 bundle->AsyncPreload();
5766 }),
5767 EventQueuePriority::Idle);
5768 (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"
, 5768)
;
5769 }
5770}
5771
5772static PropertiesFile GetMaybeSpoofedPropertiesFile(PropertiesFile aFile,
5773 const char* aKey,
5774 const Document* aDocument) {
5775 // When we spoof English, use en-US properties in strings that are accessible
5776 // by content.
5777 bool spoofLocale = nsContentUtils::ShouldResistFingerprinting(
5778 aDocument, RFPTarget::JSLocale);
5779 if (spoofLocale) {
5780 switch (aFile) {
5781 case PropertiesFile::FORMS_PROPERTIES:
5782 return PropertiesFile::FORMS_PROPERTIES_en_US;
5783 case PropertiesFile::DOM_PROPERTIES:
5784 return PropertiesFile::DOM_PROPERTIES_en_US;
5785 default:
5786 break;
5787 }
5788 }
5789 return aFile;
5790}
5791
5792/* static */
5793nsresult nsContentUtils::GetMaybeLocalizedString(PropertiesFile aFile,
5794 const char* aKey,
5795 const Document* aDocument,
5796 nsAString& aResult) {
5797 return GetLocalizedString(
5798 GetMaybeSpoofedPropertiesFile(aFile, aKey, aDocument), aKey, aResult);
5799}
5800
5801/* static */
5802nsresult nsContentUtils::GetLocalizedString(PropertiesFile aFile,
5803 const char* aKey,
5804 nsAString& aResult) {
5805 return FormatLocalizedString(aFile, aKey, {}, aResult);
5806}
5807
5808/* static */
5809nsresult nsContentUtils::FormatMaybeLocalizedString(
5810 PropertiesFile aFile, const char* aKey, Document* aDocument,
5811 const nsTArray<nsString>& aParams, nsAString& aResult) {
5812 return FormatLocalizedString(
5813 GetMaybeSpoofedPropertiesFile(aFile, aKey, aDocument), aKey, aParams,
5814 aResult);
5815}
5816
5817class FormatLocalizedStringRunnable final : public WorkerMainThreadRunnable {
5818 public:
5819 FormatLocalizedStringRunnable(WorkerPrivate* aWorkerPrivate,
5820 PropertiesFile aFile, const char* aKey,
5821 const nsTArray<nsString>& aParams,
5822 nsAString& aLocalizedString)
5823 : WorkerMainThreadRunnable(aWorkerPrivate,
5824 "FormatLocalizedStringRunnable"_ns),
5825 mFile(aFile),
5826 mKey(aKey),
5827 mParams(aParams),
5828 mLocalizedString(aLocalizedString) {
5829 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", 5829); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aWorkerPrivate" ")"); do { MOZ_CrashSequence
(__null, 5829); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5830 aWorkerPrivate->AssertIsOnWorkerThread();
5831 }
5832
5833 bool MainThreadRun() override {
5834 AssertIsOnMainThread();
5835
5836 mResult = nsContentUtils::FormatLocalizedString(mFile, mKey, mParams,
5837 mLocalizedString);
5838 (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"
, 5838)
;
5839 return true;
5840 }
5841
5842 nsresult GetResult() const { return mResult; }
5843
5844 private:
5845 const PropertiesFile mFile;
5846 const char* mKey;
5847 const nsTArray<nsString>& mParams;
5848 nsresult mResult = NS_ERROR_FAILURE;
5849 nsAString& mLocalizedString;
5850};
5851
5852/* static */
5853nsresult nsContentUtils::FormatLocalizedString(
5854 PropertiesFile aFile, const char* aKey, const nsTArray<nsString>& aParams,
5855 nsAString& aResult) {
5856 if (!NS_IsMainThread()) {
5857 // nsIStringBundle is thread-safe but its creation is not, and in particular
5858 // we don't create and store nsIStringBundle objects in a thread-safe way.
5859 //
5860 // TODO(emilio): Maybe if we already have the right bundle created we could
5861 // just call into it, but we should make sure that Shutdown() doesn't get
5862 // called on the main thread when that happens which is a bit tricky to
5863 // prove?
5864 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
5865 if (NS_WARN_IF(!workerPrivate)NS_warn_if_impl(!workerPrivate, "!workerPrivate", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5865)
) {
5866 return NS_ERROR_UNEXPECTED;
5867 }
5868
5869 auto runnable = MakeRefPtr<FormatLocalizedStringRunnable>(
5870 workerPrivate, aFile, aKey, aParams, aResult);
5871
5872 runnable->Dispatch(workerPrivate, Canceling, IgnoreErrors());
5873 return runnable->GetResult();
5874 }
5875
5876 MOZ_TRY(EnsureStringBundle(aFile))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(EnsureStringBundle(aFile)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
;
5877 nsIStringBundle* bundle = sStringBundles[size_t(aFile)];
5878 if (aParams.IsEmpty()) {
5879 return bundle->GetStringFromName(aKey, aResult);
5880 }
5881 return bundle->FormatStringFromName(aKey, aParams, aResult);
5882}
5883
5884/* static */
5885void nsContentUtils::LogSimpleConsoleError(const nsAString& aErrorText,
5886 const nsACString& aCategory,
5887 bool aFromPrivateWindow,
5888 bool aFromChromeContext,
5889 uint32_t aErrorFlags) {
5890 nsCOMPtr<nsIScriptError> scriptError =
5891 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1");
5892 if (scriptError) {
5893 nsCOMPtr<nsIConsoleService> console =
5894 do_GetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1");
5895 if (console && NS_SUCCEEDED(scriptError->Init(((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init
( aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow
, aFromChromeContext))), 1)))
5896 aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory,((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init
( aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow
, aFromChromeContext))), 1)))
5897 aFromPrivateWindow, aFromChromeContext))((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init
( aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow
, aFromChromeContext))), 1)))
) {
5898 console->LogMessage(scriptError);
5899 }
5900 }
5901}
5902
5903/* static */
5904nsresult nsContentUtils::ReportToConsole(
5905 uint32_t aErrorFlags, const nsACString& aCategory,
5906 const Document* aDocument, PropertiesFile aFile, const char* aMessageName,
5907 const nsTArray<nsString>& aParams, const SourceLocation& aLoc) {
5908 nsresult rv;
5909 nsAutoString errorText;
5910 if (!aParams.IsEmpty()) {
5911 rv = FormatLocalizedString(aFile, aMessageName, aParams, errorText);
5912 } else {
5913 rv = GetLocalizedString(aFile, aMessageName, errorText);
5914 }
5915 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"
, 5915); return rv; } } while (false)
;
5916 return ReportToConsoleNonLocalized(errorText, aErrorFlags, aCategory,
5917 aDocument, aLoc);
5918}
5919
5920/* static */
5921void nsContentUtils::ReportEmptyGetElementByIdArg(const Document* aDoc) {
5922 ReportToConsole(nsIScriptError::warningFlag, "DOM"_ns, aDoc,
5923 PropertiesFile::DOM_PROPERTIES, "EmptyGetElementByIdParam");
5924}
5925
5926/* static */
5927nsresult nsContentUtils::ReportToConsoleNonLocalized(
5928 const nsAString& aErrorText, uint32_t aErrorFlags,
5929 const nsACString& aCategory, const Document* aDocument,
5930 const SourceLocation& aLoc) {
5931 uint64_t innerWindowID = aDocument ? aDocument->InnerWindowID() : 0;
5932 if (aLoc || !aDocument || !aDocument->GetDocumentURI()) {
5933 return ReportToConsoleByWindowID(aErrorText, aErrorFlags, aCategory,
5934 innerWindowID, aLoc);
5935 }
5936 return ReportToConsoleByWindowID(aErrorText, aErrorFlags, aCategory,
5937 innerWindowID,
5938 SourceLocation(aDocument->GetDocumentURI()));
5939}
5940
5941/* static */
5942nsresult nsContentUtils::ReportToConsoleByWindowID(
5943 const nsAString& aErrorText, uint32_t aErrorFlags,
5944 const nsACString& aCategory, uint64_t aInnerWindowID,
5945 const SourceLocation& aLocation) {
5946 nsresult rv;
5947 if (!sConsoleService) { // only need to bother null-checking here
5948 rv = CallGetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1", &sConsoleService);
5949 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"
, 5949); return rv; } } while (false)
;
5950 }
5951
5952 nsCOMPtr<nsIScriptError> errorObject =
5953 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1", &rv);
5954 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"
, 5954); return rv; } } while (false)
;
5955
5956 if (aLocation.mResource.is<nsCOMPtr<nsIURI>>()) {
5957 nsIURI* uri = aLocation.mResource.as<nsCOMPtr<nsIURI>>();
5958 rv = errorObject->InitWithSourceURI(aErrorText, uri, aLocation.mLine,
5959 aLocation.mColumn, aErrorFlags,
5960 aCategory, aInnerWindowID);
5961 } else {
5962 rv = errorObject->InitWithWindowID(
5963 aErrorText, aLocation.mResource.as<nsCString>(), aLocation.mLine,
5964 aLocation.mColumn, aErrorFlags, aCategory, aInnerWindowID);
5965 }
5966 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"
, 5966); return rv; } } while (false)
;
5967
5968 return sConsoleService->LogMessage(errorObject);
5969}
5970
5971namespace {
5972
5973#define DEPRECATED_OPERATION(_op) #_op,
5974static const char* kDeprecatedOperations[] = {
5975#include "nsDeprecatedOperationList.inc"
5976 nullptr};
5977#undef DEPRECATED_OPERATION
5978
5979} // anonymous namespace
5980
5981/* static */
5982void nsContentUtils::ReportDeprecation(
5983 nsIGlobalObject* aGlobal, const Document* aDoc, nsIURI* aURI,
5984 DeprecatedOperations aOperation,
5985 const mozilla::JSCallingLocation& aLocation) {
5986 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"
, 5986); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aGlobal" ")"
); do { MOZ_CrashSequence(__null, 5986); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5987 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"
, 5987); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")");
do { MOZ_CrashSequence(__null, 5987); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5988
5989 nsAutoCString url;
5990 ReportingUtils::StripURL(aURI, url);
5991
5992 const char* operation =
5993 kDeprecatedOperations[static_cast<size_t>(aOperation)];
5994 nsAutoString type;
5995 type.AppendASCII(operation);
5996
5997 nsAutoCString key;
5998 key.AssignLiteral(operation, strlen(operation));
5999 key.AppendLiteral("Warning");
6000
6001 // XXX do we really want the localized string for deprecation report?
6002 nsAutoString msg;
6003 nsresult rv = nsContentUtils::GetMaybeLocalizedString(
6004 PropertiesFile::DOM_PROPERTIES, key.get(), aDoc, msg);
6005 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"
, 6005)
) {
6006 return;
6007 }
6008
6009 Nullable<uint32_t> lineNumber;
6010 Nullable<uint32_t> columnNumber;
6011 nsAutoCString sourceFile;
6012 if (aLocation) {
6013 lineNumber.SetValue(aLocation.mLine);
6014 columnNumber.SetValue(aLocation.mColumn);
6015 ReportingUtils::StripLocationFileName(aLocation, sourceFile);
6016 }
6017
6018 RefPtr<DeprecationReportBody> body =
6019 new DeprecationReportBody(aGlobal, type, nullptr /* date */, msg,
6020 sourceFile, lineNumber, columnNumber);
6021
6022 ReportingUtils::Report(aGlobal, nsGkAtoms::deprecation, "default"_ns, url,
6023 body);
6024}
6025
6026void nsContentUtils::LogMessageToConsole(const char* aMsg) {
6027 if (!sConsoleService) { // only need to bother null-checking here
6028 CallGetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1", &sConsoleService);
6029 if (!sConsoleService) {
6030 return;
6031 }
6032 }
6033 sConsoleService->LogStringMessage(NS_ConvertUTF8toUTF16(aMsg).get());
6034}
6035
6036bool nsContentUtils::IsChromeDoc(const Document* aDocument) {
6037 return aDocument && aDocument->NodePrincipal() == sSystemPrincipal;
6038}
6039
6040bool nsContentUtils::IsAddonDoc(const Document* aDocument) {
6041 return aDocument &&
6042 aDocument->NodePrincipal()->GetIsAddonOrExpandedAddonPrincipal();
6043}
6044
6045bool nsContentUtils::IsChildOfSameType(Document* aDoc) {
6046 if (BrowsingContext* bc = aDoc->GetBrowsingContext()) {
6047 return bc->GetParent();
6048 }
6049 return false;
6050}
6051
6052static bool IsJSONType(const nsACString& aContentType) {
6053 return aContentType.EqualsLiteral(TEXT_JSON"text/json") ||
6054 aContentType.EqualsLiteral(APPLICATION_JSON"application/json");
6055}
6056
6057static bool IsNonPlainTextType(const nsACString& aContentType) {
6058 // MIME type suffixes which should not be plain text.
6059 static constexpr std::string_view kNonPlainTextTypes[] = {
6060 "html",
6061 "xml",
6062 "xsl",
6063 "calendar",
6064 "x-calendar",
6065 "x-vcalendar",
6066 "vcalendar",
6067 "vcard",
6068 "x-vcard",
6069 "directory",
6070 "ldif",
6071 "qif",
6072 "x-qif",
6073 "x-csv",
6074 "x-vcf",
6075 "rtf",
6076 "comma-separated-values",
6077 "csv",
6078 "tab-separated-values",
6079 "tsv",
6080 "ofx",
6081 "vnd.sun.j2me.app-descriptor",
6082 "x-ms-iqy",
6083 "x-ms-odc",
6084 "x-ms-rqy",
6085 "x-ms-contact"};
6086
6087 // Trim off the "text/" prefix for comparison.
6088 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", 6088); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "StringBeginsWith(aContentType, \"text/\"_ns)"
")"); do { MOZ_CrashSequence(__null, 6088); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6089 std::string_view suffix = aContentType;
6090 suffix.remove_prefix(5);
6091
6092 for (std::string_view type : kNonPlainTextTypes) {
6093 if (type == suffix) {
6094 return true;
6095 }
6096 }
6097 return false;
6098}
6099
6100bool nsContentUtils::IsPlainTextType(const nsACString& aContentType) {
6101 // All `text/*`, any JSON type and any JavaScript type are considered "plain
6102 // text" types for the purposes of how to render them as a document.
6103 return (StringBeginsWith(aContentType, "text/"_ns) &&
6104 !IsNonPlainTextType(aContentType)) ||
6105 IsJSONType(aContentType) || IsJavascriptMIMEType(aContentType);
6106}
6107
6108bool nsContentUtils::IsUtf8OnlyPlainTextType(const nsACString& aContentType) {
6109 // NOTE: This must be a subset of the list in IsPlainTextType().
6110 return IsJSONType(aContentType) ||
6111 aContentType.EqualsLiteral(TEXT_CACHE_MANIFEST"text/cache-manifest") ||
6112 aContentType.EqualsLiteral(TEXT_VTT"text/vtt");
6113}
6114
6115bool nsContentUtils::IsInChromeDocshell(const Document* aDocument) {
6116 return aDocument && aDocument->IsInChromeDocShell();
6117}
6118
6119// static
6120nsIContentPolicy* nsContentUtils::GetContentPolicy() {
6121 if (!sTriedToGetContentPolicy) {
6122 CallGetService(NS_CONTENTPOLICY_CONTRACTID"@mozilla.org/layout/content-policy;1", &sContentPolicyService);
6123 // It's OK to not have a content policy service
6124 sTriedToGetContentPolicy = true;
6125 }
6126
6127 return sContentPolicyService;
6128}
6129
6130// static
6131bool nsContentUtils::IsEventAttributeName(nsAtom* aName, int32_t aType) {
6132 const char16_t* name = aName->GetUTF16String();
6133 if (name[0] != 'o' || name[1] != 'n') {
6134 return false;
6135 }
6136
6137 EventNameMapping mapping;
6138 return (sAtomEventTable->Get(aName, &mapping) && mapping.mType & aType);
6139}
6140
6141// static
6142EventMessage nsContentUtils::GetEventMessage(nsAtom* aName) {
6143 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"
, 6143); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "sAtomEventTable is not threadsafe" ")"); do { MOZ_CrashSequence
(__null, 6143); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6144 if (aName) {
6145 EventNameMapping mapping;
6146 if (sAtomEventTable->Get(aName, &mapping)) {
6147 return mapping.mMessage;
6148 }
6149 }
6150
6151 return eUnidentifiedEvent;
6152}
6153
6154// static
6155void nsContentUtils::ForEachEventAttributeName(
6156 int32_t aType, const FunctionRef<void(nsAtom*)> aFunc) {
6157 for (auto iter = sAtomEventTable->ConstIter(); !iter.Done(); iter.Next()) {
6158 if (iter.Data().mType & aType) {
6159 aFunc(iter.Key());
6160 }
6161 }
6162}
6163
6164// static
6165mozilla::EventClassID nsContentUtils::GetEventClassID(const nsAString& aName) {
6166 EventNameMapping mapping;
6167 if (sStringEventTable->Get(aName, &mapping)) return mapping.mEventClassID;
6168
6169 return eBasicEventClass;
6170}
6171
6172nsAtom* nsContentUtils::GetEventMessageAndAtom(
6173 const nsAString& aName, mozilla::EventClassID aEventClassID,
6174 EventMessage* aEventMessage) {
6175 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"
, 6175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Our hashtables are not threadsafe" ")"); do { MOZ_CrashSequence
(__null, 6175); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6176 EventNameMapping mapping;
6177 if (sStringEventTable->Get(aName, &mapping)) {
6178 *aEventMessage = mapping.mEventClassID == aEventClassID
6179 ? mapping.mMessage
6180 : eUnidentifiedEvent;
6181 return mapping.mAtom;
6182 }
6183
6184 // If we have cached lots of user defined event names, clear some of them.
6185 if (sUserDefinedEvents->Length() > 127) {
6186 while (sUserDefinedEvents->Length() > 64) {
6187 nsAtom* first = sUserDefinedEvents->ElementAt(0);
6188 sStringEventTable->Remove(Substring(nsDependentAtomString(first), 2));
6189 sUserDefinedEvents->RemoveElementAt(0);
6190 }
6191 }
6192
6193 *aEventMessage = eUnidentifiedEvent;
6194 RefPtr<nsAtom> atom = NS_AtomizeMainThread(u"on"_ns + aName);
6195 sUserDefinedEvents->AppendElement(atom);
6196 mapping.mAtom = atom;
6197 mapping.mMessage = eUnidentifiedEvent;
6198 mapping.mType = EventNameType_None;
6199 mapping.mEventClassID = eBasicEventClass;
6200 sStringEventTable->InsertOrUpdate(aName, mapping);
6201 return mapping.mAtom;
6202}
6203
6204// static
6205EventMessage nsContentUtils::GetEventMessageAndAtomForListener(
6206 const nsAString& aName, nsAtom** aOnName) {
6207 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"
, 6207); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Our hashtables are not threadsafe" ")"); do { MOZ_CrashSequence
(__null, 6207); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6208
6209 // Check sStringEventTable for a matching entry. This will only fail for
6210 // user-defined event types.
6211 EventNameMapping mapping;
6212 if (sStringEventTable->Get(aName, &mapping)) {
6213 RefPtr<nsAtom> atom = mapping.mAtom;
6214 atom.forget(aOnName);
6215 return mapping.mMessage;
6216 }
6217
6218 // sStringEventTable did not contain an entry for this event type string.
6219 // Call GetEventMessageAndAtom, which will create an event type atom and
6220 // cache it in sStringEventTable for future calls.
6221 EventMessage msg = eUnidentifiedEvent;
6222 RefPtr<nsAtom> atom = GetEventMessageAndAtom(aName, eBasicEventClass, &msg);
6223 atom.forget(aOnName);
6224 return msg;
6225}
6226
6227static already_AddRefed<Event> GetEventWithTarget(
6228 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
6229 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
6230 Trusted aTrusted, ErrorResult& aErrorResult) {
6231 RefPtr<Event> event =
6232 aDoc->CreateEvent(u"Events"_ns, CallerType::System, aErrorResult);
6233 if (aErrorResult.Failed()) {
6234 return nullptr;
6235 }
6236
6237 event->InitEvent(aEventName, aCanBubble, aCancelable, aComposed);
6238 event->SetTrusted(aTrusted == Trusted::eYes);
6239
6240 event->SetTarget(aTarget);
6241
6242 return event.forget();
6243}
6244
6245// static
6246nsIContent* nsContentUtils::GetEventTargetContent(
6247 nsIContent* aExplicitEventTargetContent, const WidgetEvent* aEvent) {
6248 if (!aExplicitEventTargetContent ||
6249 aExplicitEventTargetContent->IsElement() || !aEvent ||
6250 !IsForbiddenDispatchingToNonElementContent(aEvent->mMessage)) {
6251 return aExplicitEventTargetContent;
6252 }
6253 Element* const ancestorElement =
6254 aExplicitEventTargetContent->GetInclusiveFlattenedTreeAncestorElement();
6255 return ancestorElement ? ancestorElement : aExplicitEventTargetContent;
6256}
6257
6258// static
6259nsresult nsContentUtils::DispatchTrustedEvent(
6260 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
6261 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
6262 bool* aDefaultAction, SystemGroupOnly aSystemGroupOnly) {
6263 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"
, 6265); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
") (" "Use DispatchInputEvent() instead" ")"); do { MOZ_CrashSequence
(__null, 6265); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6264 !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"
, 6265); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
") (" "Use DispatchInputEvent() instead" ")"); do { MOZ_CrashSequence
(__null, 6265); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6265 "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"
, 6265); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
") (" "Use DispatchInputEvent() instead" ")"); do { MOZ_CrashSequence
(__null, 6265); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6266 return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
6267 aComposed, Trusted::eYes, aDefaultAction,
6268 ChromeOnlyDispatch::eNo, aSystemGroupOnly);
6269}
6270
6271// static
6272nsresult nsContentUtils::DispatchUntrustedEvent(
6273 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
6274 CanBubble aCanBubble, Cancelable aCancelable, bool* aDefaultAction) {
6275 return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
6276 Composed::eDefault, Trusted::eNo, aDefaultAction);
6277}
6278
6279// static
6280nsresult nsContentUtils::DispatchEvent(
6281 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
6282 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
6283 Trusted aTrusted, bool* aDefaultAction,
6284 ChromeOnlyDispatch aOnlyChromeDispatch, SystemGroupOnly aSystemGroupOnly) {
6285 if (!aDoc || !aTarget) {
6286 return NS_ERROR_INVALID_ARG;
6287 }
6288
6289 ErrorResult err;
6290 RefPtr<Event> event =
6291 GetEventWithTarget(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
6292 aComposed, aTrusted, err);
6293 if (err.Failed()) {
6294 return err.StealNSResult();
6295 }
6296 event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch =
6297 aOnlyChromeDispatch == ChromeOnlyDispatch::eYes;
6298 event->WidgetEventPtr()->mFlags.mOnlySystemGroupDispatch =
6299 aSystemGroupOnly == SystemGroupOnly::eYes;
6300
6301 // For the performance reason, aDoc may be set to a raw pointer because it's
6302 // used only before dispatching the event. Therefore, we should not use aDoc
6303 // anymore.
6304 aDoc = nullptr;
6305 bool doDefault = aTarget->DispatchEvent(*event, CallerType::System, err);
6306 if (aDefaultAction) {
6307 *aDefaultAction = doDefault;
6308 }
6309 return err.StealNSResult();
6310}
6311
6312// static
6313nsresult nsContentUtils::DispatchEvent(
6314 EventTarget* aTarget, WidgetEvent& aEvent, EventMessage aEventMessage,
6315 CanBubble aCanBubble, Cancelable aCancelable, Trusted aTrusted,
6316 bool* aDefaultAction, ChromeOnlyDispatch aOnlyChromeDispatch) {
6317 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", 6318); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aTrusted == Trusted::eYes" ")"); do { MOZ_CrashSequence
(__null, 6318); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
6318 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", 6318); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aTrusted == Trusted::eYes" ")"); do { MOZ_CrashSequence
(__null, 6318); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
6319
6320 aEvent.mSpecifiedEventType = GetEventTypeFromMessage(aEventMessage);
6321 aEvent.SetDefaultComposed();
6322 aEvent.SetDefaultComposedInNativeAnonymousContent();
6323
6324 aEvent.mFlags.mBubbles = aCanBubble == CanBubble::eYes;
6325 aEvent.mFlags.mCancelable = aCancelable == Cancelable::eYes;
6326 aEvent.mFlags.mOnlyChromeDispatch =
6327 aOnlyChromeDispatch == ChromeOnlyDispatch::eYes;
6328
6329 aEvent.mTarget = aTarget;
6330
6331 nsEventStatus status = nsEventStatus_eIgnore;
6332 nsresult rv = EventDispatcher::DispatchDOMEvent(aTarget, &aEvent, nullptr,
6333 nullptr, &status);
6334 if (aDefaultAction) {
6335 *aDefaultAction = (status != nsEventStatus_eConsumeNoDefault);
6336 }
6337 return rv;
6338}
6339
6340// static
6341nsresult nsContentUtils::DispatchInputEvent(Element* aEventTarget) {
6342 return DispatchInputEvent(aEventTarget, mozilla::eEditorInput,
6343 mozilla::EditorInputType::eUnknown, nullptr,
6344 InputEventOptions());
6345}
6346
6347// static
6348nsresult nsContentUtils::DispatchInputEvent(
6349 Element* aEventTargetElement, EventMessage aEventMessage,
6350 EditorInputType aEditorInputType, EditorBase* aEditorBase,
6351 InputEventOptions&& aOptions, nsEventStatus* aEventStatus /* = nullptr */) {
6352 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", 6353); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput"
")"); do { MOZ_CrashSequence(__null, 6353); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6353 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", 6353); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput"
")"); do { MOZ_CrashSequence(__null, 6353); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6354
6355 if (NS_WARN_IF(!aEventTargetElement)NS_warn_if_impl(!aEventTargetElement, "!aEventTargetElement",
"/root/firefox-clang/dom/base/nsContentUtils.cpp", 6355)
) {
6356 return NS_ERROR_INVALID_ARG;
6357 }
6358
6359 // If this is called from editor, the instance should be set to aEditorBase.
6360 // Otherwise, we need to look for an editor for aEventTargetElement.
6361 // However, we don't need to do it for HTMLEditor since nobody shouldn't
6362 // dispatch "beforeinput" nor "input" event for HTMLEditor except HTMLEditor
6363 // itself.
6364 bool useInputEvent = false;
6365 if (aEditorBase) {
6366 useInputEvent = true;
6367 } else if (const HTMLTextAreaElement* const textAreaElement =
6368 HTMLTextAreaElement::FromNode(aEventTargetElement)) {
6369 aEditorBase = textAreaElement->GetExtantTextEditor();
6370 useInputEvent = true;
6371 } else if (const HTMLInputElement* const inputElement =
6372 HTMLInputElement::FromNode(aEventTargetElement)) {
6373 if (inputElement->IsInputEventTarget()) {
6374 aEditorBase = inputElement->GetExtantTextEditor();
6375 useInputEvent = true;
6376 }
6377 }
6378#ifdef DEBUG1
6379 else {
6380 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", 6381
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventTargetElement->IsTextControlElement()"
") (" "The event target may have editor, but we've not known it yet."
")"); do { MOZ_CrashSequence(__null, 6381); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6381 "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", 6381
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventTargetElement->IsTextControlElement()"
") (" "The event target may have editor, but we've not known it yet."
")"); do { MOZ_CrashSequence(__null, 6381); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6382 }
6383#endif // #ifdef DEBUG
6384
6385 if (!useInputEvent) {
6386 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"
, 6386); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEventMessage == eEditorInput"
")"); do { MOZ_CrashSequence(__null, 6386); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6387 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", 6387); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eUnknown"
")"); do { MOZ_CrashSequence(__null, 6387); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6388 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", 6388); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable" ")"); do { MOZ_CrashSequence
(__null, 6388); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6389 // Dispatch "input" event with Event instance.
6390 WidgetEvent widgetEvent(true, eUnidentifiedEvent);
6391 widgetEvent.mSpecifiedEventType = nsGkAtoms::oninput;
6392 widgetEvent.mFlags.mCancelable = false;
6393 widgetEvent.mFlags.mComposed = true;
6394 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)
6395 ("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)
6396 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)
6397 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)
6398 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)
;
6399 return AsyncEventDispatcher::RunDOMEventWhenSafe(*aEventTargetElement,
6400 widgetEvent, aEventStatus);
6401 }
6402
6403 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", 6404); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable" ")"); do { MOZ_CrashSequence
(__null, 6404); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
6404 !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", 6404); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable" ")"); do { MOZ_CrashSequence
(__null, 6404); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
6405 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", 6407); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText"
")"); do { MOZ_CrashSequence(__null, 6407); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
6406 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", 6407); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText"
")"); do { MOZ_CrashSequence(__null, 6407); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
6407 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", 6407); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText"
")"); do { MOZ_CrashSequence(__null, 6407); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6408
6409 nsCOMPtr<nsIWidget> widget;
6410 if (aEditorBase) {
6411 widget = aEditorBase->GetWidget();
6412 if (NS_WARN_IF(!widget)NS_warn_if_impl(!widget, "!widget", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6412)
) {
6413 return NS_ERROR_FAILURE;
6414 }
6415 } else {
6416 Document* document = aEventTargetElement->OwnerDoc();
6417 if (NS_WARN_IF(!document)NS_warn_if_impl(!document, "!document", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6417)
) {
6418 return NS_ERROR_FAILURE;
6419 }
6420 // If we're running xpcshell tests, we fail to get presShell here.
6421 // Even in such case, we need to dispatch "input" event without widget.
6422 PresShell* presShell = document->GetPresShell();
6423 if (presShell) {
6424 nsPresContext* presContext = presShell->GetPresContext();
6425 if (NS_WARN_IF(!presContext)NS_warn_if_impl(!presContext, "!presContext", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6425)
) {
6426 return NS_ERROR_FAILURE;
6427 }
6428 widget = presContext->GetRootWidget();
6429 if (NS_WARN_IF(!widget)NS_warn_if_impl(!widget, "!widget", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6429)
) {
6430 return NS_ERROR_FAILURE;
6431 }
6432 }
6433 }
6434
6435 // Dispatch "input" event with InputEvent instance.
6436 InternalEditorInputEvent inputEvent(true, aEventMessage, widget);
6437
6438 inputEvent.mFlags.mCancelable =
6439 !aOptions.mNeverCancelable && aEventMessage == eEditorBeforeInput &&
6440 IsCancelableBeforeInputEvent(aEditorInputType);
6441 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", 6441); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!inputEvent.mFlags.mCancelable || aEventStatus"
")"); do { MOZ_CrashSequence(__null, 6441); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6442
6443 // If there is an editor, set isComposing to true when it has composition.
6444 // Note that EditorBase::IsIMEComposing() may return false even when we
6445 // need to set it to true.
6446 // Otherwise, i.e., editor hasn't been created for the element yet,
6447 // we should set isComposing to false since the element can never has
6448 // composition without editor.
6449 inputEvent.mIsComposing = aEditorBase && aEditorBase->GetComposition();
6450
6451 if (!aEditorBase || aEditorBase->IsTextEditor()) {
6452 if (IsDataAvailableOnTextEditor(aEditorInputType)) {
6453 inputEvent.mData = std::move(aOptions.mData);
6454 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"
, 6455); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { MOZ_CrashSequence
(__null, 6455); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6455 "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"
, 6455); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { MOZ_CrashSequence
(__null, 6455); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6456 }
6457#ifdef DEBUG1
6458 else {
6459 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"
, 6459); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mData.IsVoid()"
") (" "inputEvent.mData should be void" ")"); do { MOZ_CrashSequence
(__null, 6459); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6460 }
6461#endif // #ifdef DEBUG
6462 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", 6464
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges for <input> and <textarea> should always be empty"
")"); do { MOZ_CrashSequence(__null, 6464); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6463 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", 6464
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges for <input> and <textarea> should always be empty"
")"); do { MOZ_CrashSequence(__null, 6464); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6464 "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", 6464
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges for <input> and <textarea> should always be empty"
")"); do { MOZ_CrashSequence(__null, 6464); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6465 } else {
6466 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"
, 6466); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorBase->IsHTMLEditor()"
")"); do { MOZ_CrashSequence(__null, 6466); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6467 if (IsDataAvailableOnHTMLEditor(aEditorInputType)) {
6468 inputEvent.mData = std::move(aOptions.mData);
6469 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"
, 6470); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { MOZ_CrashSequence
(__null, 6470); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6470 "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"
, 6470); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { MOZ_CrashSequence
(__null, 6470); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6471 } else {
6472 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"
, 6472); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mData.IsVoid()"
") (" "inputEvent.mData should be void" ")"); do { MOZ_CrashSequence
(__null, 6472); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6473 if (IsDataTransferAvailableOnHTMLEditor(aEditorInputType)) {
6474 inputEvent.mDataTransfer = std::move(aOptions.mDataTransfer);
6475 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"
, 6476); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer shouldn't be nullptr" ")"); do
{ MOZ_CrashSequence(__null, 6476); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6476 "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"
, 6476); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer shouldn't be nullptr" ")"); do
{ MOZ_CrashSequence(__null, 6476); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6477 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"
, 6478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer->IsReadOnly()"
") (" "inputEvent.mDataTransfer should be read only" ")"); do
{ MOZ_CrashSequence(__null, 6478); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6478 "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"
, 6478); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer->IsReadOnly()"
") (" "inputEvent.mDataTransfer should be read only" ")"); do
{ MOZ_CrashSequence(__null, 6478); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6479 }
6480#ifdef DEBUG1
6481 else {
6482 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"
, 6483); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer should be nullptr" ")"); do {
MOZ_CrashSequence(__null, 6483); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6483 "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"
, 6483); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer should be nullptr" ")"); do {
MOZ_CrashSequence(__null, 6483); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6484 }
6485#endif // #ifdef DEBUG
6486 }
6487 if (aEventMessage == eEditorBeforeInput &&
6488 MayHaveTargetRangesOnHTMLEditor(aEditorInputType)) {
6489 inputEvent.mTargetRanges = std::move(aOptions.mTargetRanges);
6490 }
6491#ifdef DEBUG1
6492 else {
6493 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", 6494
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges shouldn't be set for the dispatching event"
")"); do { MOZ_CrashSequence(__null, 6494); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6494 "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", 6494
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges shouldn't be set for the dispatching event"
")"); do { MOZ_CrashSequence(__null, 6494); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6495 }
6496#endif // #ifdef DEBUG
6497 }
6498
6499 inputEvent.mInputType = aEditorInputType;
6500
6501 // If we cannot dispatch an event right now, we cannot make it cancelable.
6502 if (!nsContentUtils::IsSafeToRunScript()) {
6503 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"
, 6505); MOZ_PretendNoReturn(); } } while (0)
6504 !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"
, 6505); MOZ_PretendNoReturn(); } } while (0)
6505 "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"
, 6505); MOZ_PretendNoReturn(); } } while (0)
;
6506 inputEvent.mFlags.mCancelable = false;
6507 }
6508 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)
6509 ("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)
6510 "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)
6511 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)
6512 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)
6513 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)
6514 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)
;
6515 return AsyncEventDispatcher::RunDOMEventWhenSafe(*aEventTargetElement,
6516 inputEvent, aEventStatus);
6517}
6518
6519nsresult nsContentUtils::DispatchChromeEvent(
6520 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
6521 CanBubble aCanBubble, Cancelable aCancelable, bool* aDefaultAction) {
6522 if (!aDoc || !aTarget) {
6523 return NS_ERROR_INVALID_ARG;
6524 }
6525
6526 if (!aDoc->GetWindow()) {
6527 return NS_ERROR_INVALID_ARG;
6528 }
6529
6530 EventTarget* piTarget = aDoc->GetWindow()->GetParentTarget();
6531 if (!piTarget) {
6532 return NS_ERROR_INVALID_ARG;
6533 }
6534
6535 ErrorResult err;
6536 RefPtr<Event> event =
6537 GetEventWithTarget(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
6538 Composed::eDefault, Trusted::eYes, err);
6539 if (err.Failed()) {
6540 return err.StealNSResult();
6541 }
6542
6543 bool defaultActionEnabled =
6544 piTarget->DispatchEvent(*event, CallerType::System, err);
6545 if (aDefaultAction) {
6546 *aDefaultAction = defaultActionEnabled;
6547 }
6548 return err.StealNSResult();
6549}
6550
6551void nsContentUtils::RequestFrameFocus(Element& aFrameElement, bool aCanRaise,
6552 CallerType aCallerType) {
6553 RefPtr<Element> target = &aFrameElement;
6554 bool defaultAction = true;
6555 if (aCanRaise) {
6556 RefPtr<Document> doc = target->OwnerDoc();
6557 DispatchEventOnlyToChrome(doc, target, u"framefocusrequested"_ns,
6558 CanBubble::eYes, Cancelable::eYes,
6559 &defaultAction);
6560 }
6561 if (!defaultAction) {
6562 return;
6563 }
6564
6565 RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager();
6566 if (!fm) {
6567 return;
6568 }
6569
6570 uint32_t flags = nsIFocusManager::FLAG_NOSCROLL;
6571 if (aCanRaise) {
6572 flags |= nsIFocusManager::FLAG_RAISE;
6573 }
6574
6575 if (aCallerType == CallerType::NonSystem) {
6576 flags |= nsIFocusManager::FLAG_NONSYSTEMCALLER;
6577 }
6578
6579 fm->SetFocus(target, flags);
6580}
6581
6582nsresult nsContentUtils::DispatchEventOnlyToChrome(
6583 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
6584 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
6585 bool* aDefaultAction) {
6586 return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
6587 aComposed, Trusted::eYes, aDefaultAction,
6588 ChromeOnlyDispatch::eYes);
6589}
6590
6591/* static */
6592Element* nsContentUtils::MatchElementId(nsIContent* aContent,
6593 const nsAtom* aId) {
6594 for (nsIContent* cur = aContent; cur; cur = cur->GetNextNode(aContent)) {
6595 if (aId == cur->GetID()) {
6596 return cur->AsElement();
6597 }
6598 }
6599
6600 return nullptr;
6601}
6602
6603/* static */
6604Element* nsContentUtils::MatchElementId(nsIContent* aContent,
6605 const nsAString& aId) {
6606 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"
, 6606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aId.IsEmpty()"
") (" "Will match random elements" ")"); do { MOZ_CrashSequence
(__null, 6606); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6607
6608 // ID attrs are generally stored as atoms, so just atomize this up front
6609 RefPtr<nsAtom> id(NS_Atomize(aId));
6610 if (!id) {
6611 // OOM, so just bail
6612 return nullptr;
6613 }
6614
6615 return MatchElementId(aContent, id);
6616}
6617
6618/* static */
6619void nsContentUtils::RegisterShutdownObserver(nsIObserver* aObserver) {
6620 nsCOMPtr<nsIObserverService> observerService =
6621 mozilla::services::GetObserverService();
6622 if (observerService) {
6623 observerService->AddObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown",
6624 false);
6625 }
6626}
6627
6628/* static */
6629void nsContentUtils::UnregisterShutdownObserver(nsIObserver* aObserver) {
6630 nsCOMPtr<nsIObserverService> observerService =
6631 mozilla::services::GetObserverService();
6632 if (observerService) {
6633 observerService->RemoveObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown");
6634 }
6635}
6636
6637/* static */
6638bool nsContentUtils::HasNonEmptyAttr(const nsIContent* aContent,
6639 int32_t aNameSpaceID, nsAtom* aName) {
6640 static AttrArray::AttrValuesArray strings[] = {nsGkAtoms::_empty, nullptr};
6641 return aContent->IsElement() &&
6642 aContent->AsElement()->FindAttrValueIn(aNameSpaceID, aName, strings,
6643 eCaseMatters) ==
6644 AttrArray::ATTR_VALUE_NO_MATCH;
6645}
6646
6647void nsContentUtils::NotifyDevToolsOfNodeRemoval(nsINode& aRemovingNode) {
6648 // Having an explicit check here since it's an easy mistake to fall into,
6649 // and there might be existing code with problems. We'd rather be safe
6650 // than fire a chrome only event in all corner cases. We also rely on it for
6651 // nsAutoScriptBlockerSuppressNodeRemoved.
6652 if (!IsSafeToRunScript()) {
6653 // This checks that IsSafeToRunScript is true since we don't want to fire
6654 // events when that is false. We can't rely on EventDispatcher to assert
6655 // this in this situation since most of the time DevTools is not observing
6656 // the mutations, in which case we won't even attempt to dispatch events.
6657 // However this also allows for two exceptions. First off, we don't assert
6658 // if the mutation happens to native anonymous content since we never fire
6659 // mutation events on such content anyway.
6660 // Second, we don't assert if sDOMNodeRemovedSuppressCount is true since
6661 // that is a know case when we'd normally fire a mutation event, but can't
6662 // make that safe and so we suppress it at this time. Ideally this should
6663 // go away eventually.
6664 if (!aRemovingNode.IsInNativeAnonymousSubtree() &&
6665 !sDOMNodeRemovedSuppressCount) {
6666 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",
6667); MOZ_PretendNoReturn(); } while (0)
6667 "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",
6667); MOZ_PretendNoReturn(); } while (0)
;
6668 WarnScriptWasIgnored(aRemovingNode.OwnerDoc());
6669 }
6670 return;
6671 }
6672
6673 if (MOZ_UNLIKELY(aRemovingNode.DevToolsShouldBeNotifiedOfThisRemoval())(__builtin_expect(!!(aRemovingNode.DevToolsShouldBeNotifiedOfThisRemoval
()), 0))
) {
6674 const RefPtr<Document> doc = aRemovingNode.OwnerDoc();
6675 DispatchChromeEvent(doc, &aRemovingNode, u"devtoolschildremoved"_ns,
6676 CanBubble::eNo, Cancelable::eNo);
6677 }
6678}
6679
6680void nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments() {
6681 for (EventListenerManager& mgr : sNodeEventListenerManagers) {
6682 nsINode* n = static_cast<nsINode*>(mgr.GetTarget());
6683 if (n && n->IsInComposedDoc() &&
6684 nsCCUncollectableMarker::InGeneration(
6685 n->OwnerDoc()->GetMarkedCCGeneration())) {
6686 mgr.MarkForCC();
6687 }
6688 }
6689}
6690
6691/* static */
6692void nsContentUtils::AddNodeListenerManager(EventListenerManager* aManager) {
6693 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", 6693); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 6693); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6694 sNodeEventListenerManagers.pushBack(aManager);
6695}
6696
6697/* static */
6698void nsContentUtils::RemoveNodeListenerManager(EventListenerManager* aManager) {
6699 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", 6699); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 6699); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6700 // ~EventListenerManager passes here managers which are not in the list.
6701 if (sNodeEventListenerManagers.ElementProbablyInList(aManager)) {
6702 sNodeEventListenerManagers.remove(aManager);
6703 }
6704}
6705
6706void nsContentUtils::AddEntryToDOMArenaTable(nsINode* aNode,
6707 DOMArena* aDOMArena) {
6708 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"
, 6708); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sDOMArenaHashtable->Contains(aNode)"
")"); do { MOZ_CrashSequence(__null, 6708); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6709 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", 6709); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aNode->HasFlag(NODE_KEEPS_DOMARENA)" ")"
); do { MOZ_CrashSequence(__null, 6709); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6710 if (!sDOMArenaHashtable) {
6711 sDOMArenaHashtable =
6712 new nsRefPtrHashtable<nsPtrHashKey<const nsINode>, dom::DOMArena>();
6713 }
6714 aNode->SetFlags(NODE_KEEPS_DOMARENA);
6715 sDOMArenaHashtable->InsertOrUpdate(aNode, RefPtr<DOMArena>(aDOMArena));
6716}
6717
6718DOMArena* nsContentUtils::GetEntryFromDOMArenaTable(const nsINode* aNode) {
6719 if (!sDOMArenaHashtable) {
6720 return nullptr;
6721 }
6722 return sDOMArenaHashtable->MaybeGet(aNode).valueOr(nullptr);
6723}
6724
6725already_AddRefed<DOMArena> nsContentUtils::TakeEntryFromDOMArenaTable(
6726 const nsINode* aNode) {
6727 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", 6727); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sDOMArenaHashtable->Contains(aNode)" ")"
); do { MOZ_CrashSequence(__null, 6727); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6728 RefPtr<DOMArena> arena;
6729 sDOMArenaHashtable->Remove(aNode, getter_AddRefs(arena));
6730 return arena.forget();
6731}
6732
6733/* static */
6734bool nsContentUtils::IsValidNodeName(nsAtom* aLocalName, nsAtom* aPrefix,
6735 int32_t aNamespaceID) {
6736 if (aNamespaceID == kNameSpaceID_Unknown-1) {
6737 return false;
6738 }
6739
6740 if (!aPrefix) {
6741 // If the prefix is null, then either the QName must be xmlns or the
6742 // namespace must not be XMLNS.
6743 return (aLocalName == nsGkAtoms::xmlns) ==
6744 (aNamespaceID == kNameSpaceID_XMLNS1);
6745 }
6746
6747 // If the prefix is non-null then the namespace must not be null.
6748 if (aNamespaceID == kNameSpaceID_None) {
6749 return false;
6750 }
6751
6752 // If the namespace is the XMLNS namespace then the prefix must be xmlns,
6753 // but the localname must not be xmlns.
6754 if (aNamespaceID == kNameSpaceID_XMLNS1) {
6755 return aPrefix == nsGkAtoms::xmlns && aLocalName != nsGkAtoms::xmlns;
6756 }
6757
6758 // If the namespace is not the XMLNS namespace then the prefix must not be
6759 // xmlns.
6760 // If the namespace is the XML namespace then the prefix can be anything.
6761 // If the namespace is not the XML namespace then the prefix must not be xml.
6762 return aPrefix != nsGkAtoms::xmlns &&
6763 (aNamespaceID == kNameSpaceID_XML2 || aPrefix != nsGkAtoms::xml);
6764}
6765
6766already_AddRefed<DocumentFragment> nsContentUtils::CreateContextualFragment(
6767 nsINode* aContextNode, const nsAString& aFragment,
6768 bool aPreventScriptExecution,
6769 Maybe<RefPtr<CustomElementRegistry>> aCustomElementRegistry,
6770 ErrorResult& aRv) {
6771 if (!aContextNode) {
6772 aRv.Throw(NS_ERROR_INVALID_ARG);
6773 return nullptr;
6774 }
6775
6776 // If we don't have a document here, we can't get the right security context
6777 // for compiling event handlers... so just bail out.
6778 RefPtr<Document> document = aContextNode->OwnerDoc();
6779 bool isHTML = document->IsHTMLDocument();
6780
6781 if (isHTML) {
6782 RefPtr<DocumentFragment> frag = new (document->NodeInfoManager())
6783 DocumentFragment(document->NodeInfoManager());
6784
6785 Element* element = aContextNode->GetAsElementOrParentElement();
6786 if (element && !element->IsHTMLElement(nsGkAtoms::html)) {
6787 aRv = ParseFragmentHTML(
6788 aFragment, frag, element->NodeInfo()->NameAtom(),
6789 element->GetNameSpaceID(),
6790 (document->GetCompatibilityMode() == eCompatibility_NavQuirks),
6791 aPreventScriptExecution, kParseFragmentPrivilegedDefaultSanitization,
6792 std::move(aCustomElementRegistry));
6793 } else {
6794 aRv = ParseFragmentHTML(
6795 aFragment, frag, nsGkAtoms::body, kNameSpaceID_XHTML3,
6796 (document->GetCompatibilityMode() == eCompatibility_NavQuirks),
6797 aPreventScriptExecution, kParseFragmentPrivilegedDefaultSanitization,
6798 std::move(aCustomElementRegistry));
6799 }
6800
6801 return frag.forget();
6802 }
6803
6804 AutoTArray<nsString, 32> tagStack;
6805 nsAutoString uriStr, nameStr;
6806 for (Element* element : aContextNode->InclusiveAncestorsOfType<Element>()) {
6807 nsString& tagName = *tagStack.AppendElement();
6808 // It mostly doesn't actually matter what tag name we use here: XML doesn't
6809 // have parsing that depends on the open tag stack, apart from namespace
6810 // declarations. So this whole tagStack bit is just there to get the right
6811 // namespace declarations to the XML parser. That said, the parser _is_
6812 // going to create elements with the tag names we provide here, so we need
6813 // to make sure they are not names that can trigger custom element
6814 // constructors. Just make up a name that is never going to be a valid
6815 // custom element name.
6816 //
6817 // The principled way to do this would probably be to add a new FromParser
6818 // value and make sure we use it when creating the context elements, then
6819 // make sure we teach all FromParser consumers (and in particular the custom
6820 // element code) about it as needed. But right now the XML parser never
6821 // actually uses FromParser values other than NOT_FROM_PARSER, and changing
6822 // that is pretty complicated.
6823 tagName.AssignLiteral("notacustomelement");
6824
6825 // see if we need to add xmlns declarations
6826 uint32_t count = element->GetAttrCount();
6827 bool setDefaultNamespace = false;
6828 if (count > 0) {
6829 uint32_t index;
6830
6831 for (index = 0; index < count; index++) {
6832 const BorrowedAttrInfo info = element->GetAttrInfoAt(index);
6833 const nsAttrName* name = info.mName;
6834 if (name->NamespaceEquals(kNameSpaceID_XMLNS1)) {
6835 info.mValue->ToString(uriStr);
6836
6837 // really want something like nsXMLContentSerializer::SerializeAttr
6838 tagName.AppendLiteral(" xmlns"); // space important
6839 if (name->GetPrefix()) {
6840 tagName.Append(char16_t(':'));
6841 name->LocalName()->ToString(nameStr);
6842 tagName.Append(nameStr);
6843 } else {
6844 setDefaultNamespace = true;
6845 }
6846 tagName.AppendLiteral(R"(=")");
6847 tagName.Append(uriStr);
6848 tagName.Append('"');
6849 }
6850 }
6851 }
6852
6853 if (!setDefaultNamespace) {
6854 mozilla::dom::NodeInfo* info = element->NodeInfo();
6855 if (!info->GetPrefixAtom() && info->NamespaceID() != kNameSpaceID_None) {
6856 // We have no namespace prefix, but have a namespace ID. Push
6857 // default namespace attr in, so that our kids will be in our
6858 // namespace.
6859 info->GetNamespaceURI(uriStr);
6860 tagName.AppendLiteral(R"( xmlns=")");
6861 tagName.Append(uriStr);
6862 tagName.Append('"');
6863 }
6864 }
6865 }
6866
6867 RefPtr<DocumentFragment> frag;
6868 aRv = ParseFragmentXML(aFragment, document, tagStack, aPreventScriptExecution,
6869 kParseFragmentPrivilegedDefaultSanitization,
6870 getter_AddRefs(frag));
6871 return frag.forget();
6872}
6873
6874/* static */
6875void nsContentUtils::DropFragmentParsers() {
6876 NS_IF_RELEASE(sHTMLFragmentParser)do { if (sHTMLFragmentParser) { (sHTMLFragmentParser)->Release
(); (sHTMLFragmentParser) = 0; } } while (0)
;
6877 NS_IF_RELEASE(sXMLFragmentParser)do { if (sXMLFragmentParser) { (sXMLFragmentParser)->Release
(); (sXMLFragmentParser) = 0; } } while (0)
;
6878 NS_IF_RELEASE(sXMLFragmentSink)do { if (sXMLFragmentSink) { (sXMLFragmentSink)->Release()
; (sXMLFragmentSink) = 0; } } while (0)
;
6879}
6880
6881/* static */
6882void nsContentUtils::XPCOMShutdown() { nsContentUtils::DropFragmentParsers(); }
6883
6884// https://wicg.github.io/sanitizer-api/#set-and-filter-html
6885static void SetAndFilterHTML(
6886 FragmentOrElement* aTarget, Element* aContext, const nsAString& aHTML,
6887 const OwningSanitizerOrSanitizerConfigOrSanitizerPresets& aSanitizerOptions,
6888 const bool aSafe, ErrorResult& aError) {
6889 const RefPtr<Document> doc = aTarget->OwnerDoc();
6890
6891 // Step 1. If safe and contextElement’s local name is "script" and
6892 // contextElement’s namespace is the HTML namespace or the SVG namespace, then
6893 // return.
6894 if (aSafe && (aContext->IsHTMLElement(nsGkAtoms::script) ||
6895 aContext->IsSVGElement(nsGkAtoms::script))) {
6896 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "DOM"_ns, doc,
6897 PropertiesFile::DOM_PROPERTIES,
6898 "SetHTMLScript");
6899 return;
6900 }
6901
6902 // Step 2. Let sanitizer be the result of calling get a sanitizer instance
6903 // from options with options and safe.
6904 nsCOMPtr<nsPIDOMWindowInner> window =
6905 do_QueryInterface(aTarget->GetRelevantGlobal());
6906 if (!window) {
6907 aError.ThrowInvalidStateError("Missing owner global.");
6908 return;
6909 }
6910 RefPtr<Sanitizer> sanitizer =
6911 Sanitizer::GetInstance(window, aSanitizerOptions, aSafe, aError);
6912 if (aError.Failed()) {
6913 return;
6914 }
6915
6916 aTarget->NotifyDevToolsOfRemovalsOfChildren();
6917
6918 // Needed when innerHTML is used in combination with contenteditable
6919 mozAutoDocUpdate updateBatch(doc, true);
6920
6921 // Remove childnodes.
6922 nsAutoMutationBatch mb(aTarget, true, false);
6923 aTarget->RemoveAllChildren(true);
6924 mb.RemovalDone();
6925
6926 nsAutoScriptLoaderDisabler sld(doc);
6927
6928 // Step 3. Let newChildren be the result of the HTML fragment parsing
6929 // algorithm steps given contextElement, html, and true.
6930 // Step 4. Let fragment be a new DocumentFragment whose node document is
6931 // contextElement’s node document.
6932 // Step 5. For each node in newChildren, append node to fragment.
6933
6934 // We MUST NOT cause any requests during parsing, so we'll
6935 // create an inert Document and parse into a new DocumentFragment.
6936
6937 RefPtr<Document> inertDoc = nsContentUtils::CreateInertHTMLDocument(doc);
6938 if (!inertDoc) {
6939 aError = NS_ERROR_FAILURE;
6940 return;
6941 }
6942
6943 RefPtr<DocumentFragment> fragment = new (inertDoc->NodeInfoManager())
6944 DocumentFragment(inertDoc->NodeInfoManager());
6945
6946 nsAtom* contextLocalName = aContext->NodeInfo()->NameAtom();
6947 int32_t contextNameSpaceID = aContext->GetNameSpaceID();
6948 int32_t flags =
6949 aSafe ? nsContentUtils::kParseFragmentNoSanitization
6950 : nsContentUtils::kParseFragmentPrivilegedDefaultSanitization;
6951
6952 const bool sanitizeWhileParsing =
6953 StaticPrefs::dom_security_sanitizer_while_parsing();
6954
6955 aError = nsContentUtils::ParseFragmentHTML(
6956 aHTML, fragment, contextLocalName, contextNameSpaceID,
6957 /* aQuirks */ false, /* aPreventScriptExecution */ true, flags,
6958 mozilla::Nothing(), sanitizeWhileParsing ? sanitizer.get() : nullptr,
6959 aSafe);
6960 if (aError.Failed()) {
6961 return;
6962 }
6963
6964 // Suppress assertion about node removal mutation events that can't have
6965 // listeners anyway, because no one has had the chance to register
6966 // mutation listeners on the fragment that comes from the parser.
6967 nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
6968
6969 if (!sanitizeWhileParsing) {
6970 // Step 6. Run sanitize on fragment using sanitizer and safe.
6971 sanitizer->Sanitize(fragment, aSafe, aError);
6972 if (aError.Failed()) {
6973 return;
6974 }
6975 }
6976
6977 // Step 7. Replace all with fragment within target.
6978 aTarget->AppendChild(*fragment, aError);
6979 if (aError.Failed()) {
6980 return;
6981 }
6982
6983 mb.NodesAdded();
6984}
6985
6986/* static */
6987void nsContentUtils::SetHTML(FragmentOrElement* aTarget, Element* aContext,
6988 const nsAString& aHTML,
6989 const SetHTMLOptions& aOptions,
6990 ErrorResult& aError) {
6991 SetAndFilterHTML(aTarget, aContext, aHTML, aOptions.mSanitizer,
6992 /* aSafe */ true, aError);
6993}
6994
6995/* https://html.spec.whatwg.org/#unsafely-set-html */
6996/* https://html.spec.whatwg.org/#dom-shadowroot-sethtmlunsafe */
6997/* https://html.spec.whatwg.org/#dom-element-sethtmlunsafe */
6998/* static */
6999void nsContentUtils::SetHTMLUnsafe(
7000 FragmentOrElement* aTarget, Element* aContext,
7001 const TrustedHTMLOrString& aSource, const SetHTMLUnsafeOptions& aOptions,
7002 bool aIsShadowRoot, nsIPrincipal* aSubjectPrincipal, ErrorResult& aError) {
7003 // Element's setHTMLUnsafe() step 1 / ShadowRoot's setHTMLUnsafe() step 1.
7004 // "Let compliantHTML be the result of invoking the get trusted type compliant
7005 // string algorithm with TrustedHTML, this's relevant global object, html,
7006 // «Element setHTMLUnsafe» or «ShadowRoot setHTMLUnsafe», and «script»."
7007 constexpr nsLiteralString elementSink = u"Element setHTMLUnsafe"_ns;
7008 constexpr nsLiteralString shadowRootSink = u"ShadowRoot setHTMLUnsafe"_ns;
7009 Maybe<nsAutoString> compliantStringHolder;
7010 const nsAString* compliantString =
7011 TrustedTypeUtils::GetTrustedTypesCompliantString(
7012 aSource, aIsShadowRoot ? shadowRootSink : elementSink,
7013 kTrustedTypesOnlySinkGroup, *aContext, aSubjectPrincipal,
7014 compliantStringHolder, aError);
7015 if (aError.Failed()) {
7016 return;
7017 }
7018
7019 // Fallback to the more optimized code below without a sanitizer.
7020 if (aOptions.mSanitizer.WasPassed()) {
7021 return SetAndFilterHTML(aTarget, aContext, *compliantString,
7022 aOptions.mSanitizer.Value(), /* aSafe */ false,
7023 aError);
7024 }
7025
7026 RefPtr<DocumentFragment> fragment;
7027 {
7028 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"
, 7029); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sFragmentParsingActive"
") (" "Re-entrant fragment parsing attempted." ")"); do { MOZ_CrashSequence
(__null, 7029); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
7029 "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"
, 7029); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sFragmentParsingActive"
") (" "Re-entrant fragment parsing attempted." ")"); do { MOZ_CrashSequence
(__null, 7029); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7030 mozilla::AutoRestore<bool> guard(sFragmentParsingActive);
7031 sFragmentParsingActive = true;
7032 if (!sHTMLFragmentParser) {
7033 NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef(
)
;
7034 // Now sHTMLFragmentParser owns the object
7035 }
7036
7037 nsAtom* contextLocalName = aContext->NodeInfo()->NameAtom();
7038 int32_t contextNameSpaceID = aContext->GetNameSpaceID();
7039
7040 // https://html.spec.whatwg.org/#html-fragment-parsing-algorithm
7041 // 11. Let root be the result of creating an element given document,
7042 // 'html', the HTML namespace, null, null, false, and context's
7043 // custom element registry.
7044 Maybe<RefPtr<CustomElementRegistry>> customElementRegistry;
7045 if (StaticPrefs::dom_scoped_custom_element_registries_enabled()) {
7046 customElementRegistry.emplace(aContext->GetCustomElementRegistry());
7047 }
7048
7049 RefPtr<Document> doc = aTarget->OwnerDoc();
7050 fragment = doc->CreateDocumentFragment();
7051
7052 // XXX: Steps 1-3 are performed together by ParseFragment, which parses
7053 // directly into the DocumentFragment.
7054 nsresult rv = sHTMLFragmentParser->ParseFragment(
7055 *compliantString, fragment, contextLocalName, contextNameSpaceID,
7056 fragment->OwnerDoc()->GetCompatibilityMode() ==
7057 eCompatibility_NavQuirks,
7058 true, true, std::move(customElementRegistry));
7059 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7060 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",
7060)
;
7061 }
7062 }
7063
7064 // Step 4. "Replace all with fragment within target."
7065 aTarget->ReplaceChildren(fragment, IgnoreErrors());
7066}
7067
7068// We sanitize if the fragment occurs in a system privileged
7069// context, an about: page, or if there are explicit sanitization flags.
7070// Please note that about:blank and about:srcdoc inherit the security
7071// context from the embedding context and hence are not loaded using
7072// an about: scheme principal.
7073bool ShouldSanitize(nsIPrincipal* aPrincipal, int32_t aFlags) {
7074 // We don't need to sanitize for setHTML(), which uses
7075 // kParseFragmentNoSanitization.
7076 if (aFlags == nsContentUtils::kParseFragmentNoSanitization) {
7077 return false;
7078 }
7079
7080 if (aFlags >= 0) {
7081 return true;
7082 }
7083
7084 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", 7085); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization"
")"); do { MOZ_CrashSequence(__null, 7085); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7085 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", 7085); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization"
")"); do { MOZ_CrashSequence(__null, 7085); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7086 return aPrincipal->IsSystemPrincipal() || aPrincipal->SchemeIs("about");
7087}
7088
7089// Helper function to compuate Sanitization Flags for ParseFramentHTML/XML
7090uint32_t ComputeSanitizationFlags(nsIPrincipal* aPrincipal, int32_t aFlags) {
7091 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", 7093); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0"
")"); do { MOZ_CrashSequence(__null, 7093); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7092 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", 7093); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0"
")"); do { MOZ_CrashSequence(__null, 7093); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7093 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", 7093); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0"
")"); do { MOZ_CrashSequence(__null, 7093); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7094
7095 if (aPrincipal->IsSystemPrincipal() || aPrincipal->SchemeIs("about")) {
7096 if (aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization) {
7097 // If this is a chrome-privileged document and no explicit flags
7098 // were passed, then use these sanitization flags.
7099 return nsIParserUtils::SanitizerAllowStyle |
7100 nsIParserUtils::SanitizerAllowComments |
7101 // Don't drop forms in about: to avoid breaking existing users
7102 (aPrincipal->IsSystemPrincipal()
7103 ? nsIParserUtils::SanitizerDropForms
7104 : 0) |
7105 nsIParserUtils::SanitizerLogRemovals;
7106 }
7107
7108 // If the caller explicitly passes flags, then we use those
7109 // flags but additionally drop forms.
7110 return aFlags | nsIParserUtils::SanitizerDropForms;
7111 }
7112
7113 if (aFlags >= 0) {
7114 // aFlags by default is -1 and is only ever non equal to -1 if the
7115 // caller of ParseFragmentHTML/ParseFragmentXML is
7116 // ParserUtils::ParseFragment(). Only in that case we should use
7117 // the sanitization flags passed within aFlags.
7118 return aFlags;
7119 }
7120
7121 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"
, 7121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "We should have explicit flags" ")"
); do { MOZ_CrashSequence(__null, 7121); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7122 return 0;
7123}
7124
7125/* https://html.spec.whatwg.org/#html-fragment-parsing-algorithm */
7126/* static */
7127nsresult nsContentUtils::ParseFragmentHTML(
7128 const nsAString& aSourceBuffer, nsIContent* aTargetNode,
7129 nsAtom* aContextLocalName, int32_t aContextNamespace, bool aQuirks,
7130 bool aPreventScriptExecution, int32_t aFlags,
7131 mozilla::Maybe<RefPtr<mozilla::dom::CustomElementRegistry>>
7132 aCustomElementRegistry,
7133 Sanitizer* aSanitizer, bool aSanitizerSafe) {
7134 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", 7135); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing()"
")"); do { MOZ_CrashSequence(__null, 7135); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7135 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", 7135); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing()"
")"); do { MOZ_CrashSequence(__null, 7135); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7136 if (nsContentUtils::sFragmentParsingActive) {
7137 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"
, 7137); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted."
")"); do { MOZ_CrashSequence(__null, 7137); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7138 return NS_ERROR_DOM_INVALID_STATE_ERR;
7139 }
7140 mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
7141 nsContentUtils::sFragmentParsingActive = true;
7142 if (!sHTMLFragmentParser) {
7143 NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef(
)
;
7144 // Now sHTMLFragmentParser owns the object
7145 }
7146
7147 nsCOMPtr<nsIPrincipal> nodePrincipal = aTargetNode->NodePrincipal();
7148
7149#ifdef DEBUG1
7150 // aFlags should always be kParseFragmentPrivilegedDefaultSanitization unless
7151 // the caller of ParseFragmentHTML is ParserUtils::ParseFragment() which is
7152 // the only caller that intends sanitization. For all other callers we need to
7153 // ensure to call AuditParsingOfHTMLXMLFragments.
7154 //
7155 // For SetHTML the flag is kParseFragmentNoSanitization, because that function
7156 // already sanitizes.
7157 if (aFlags == kParseFragmentPrivilegedDefaultSanitization) {
7158 DOMSecurityMonitor::AuditParsingOfHTMLXMLFragments(nodePrincipal,
7159 aSourceBuffer);
7160 }
7161#endif
7162
7163 nsIContent* target = aTargetNode;
7164
7165 RefPtr<Document> doc = aTargetNode->OwnerDoc();
7166 RefPtr<DocumentFragment> fragment;
7167
7168 if (ShouldSanitize(nodePrincipal, aFlags)) {
7169 if (!doc->IsLoadedAsData()) {
7170 doc = nsContentUtils::CreateInertHTMLDocument(doc);
7171 if (!doc) {
7172 return NS_ERROR_FAILURE;
7173 }
7174 }
7175 fragment =
7176 new (doc->NodeInfoManager()) DocumentFragment(doc->NodeInfoManager());
7177 target = fragment;
7178 }
7179
7180 nsresult rv = sHTMLFragmentParser->ParseFragment(
7181 aSourceBuffer, target, aContextLocalName, aContextNamespace, aQuirks,
7182 aPreventScriptExecution, false, std::move(aCustomElementRegistry),
7183 aSanitizer, aSanitizerSafe);
7184 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"
, 7184); return rv; } } while (false)
;
7185
7186 if (fragment) {
7187 uint32_t sanitizationFlags =
7188 ComputeSanitizationFlags(nodePrincipal, aFlags);
7189 // Don't fire mutation events for nodes removed by the sanitizer.
7190 nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
7191 nsTreeSanitizer sanitizer(sanitizationFlags);
7192 sanitizer.Sanitize(fragment);
7193
7194 ErrorResult error;
7195 aTargetNode->AppendChild(*fragment, error);
7196 rv = error.StealNSResult();
7197 }
7198
7199 return rv;
7200}
7201
7202/* static */
7203nsresult nsContentUtils::ParseDocumentHTML(
7204 const nsAString& aSourceBuffer, Document* aTargetDocument,
7205 bool aScriptingEnabledForNoscriptParsing, Sanitizer* aSanitizer,
7206 bool aSanitizerSafe) {
7207 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", 7208); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing()"
")"); do { MOZ_CrashSequence(__null, 7208); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7208 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", 7208); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aSanitizer || StaticPrefs::dom_security_sanitizer_while_parsing()"
")"); do { MOZ_CrashSequence(__null, 7208); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7209 if (nsContentUtils::sFragmentParsingActive) {
7210 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"
, 7210); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted."
")"); do { MOZ_CrashSequence(__null, 7210); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7211 return NS_ERROR_DOM_INVALID_STATE_ERR;
7212 }
7213 mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
7214 nsContentUtils::sFragmentParsingActive = true;
7215 if (!sHTMLFragmentParser) {
7216 NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef(
)
;
7217 // Now sHTMLFragmentParser owns the object
7218 }
7219 nsresult rv = sHTMLFragmentParser->ParseDocument(
7220 aSourceBuffer, aTargetDocument, aScriptingEnabledForNoscriptParsing,
7221 aSanitizer, aSanitizerSafe);
7222 return rv;
7223}
7224
7225/* static */
7226nsresult nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer,
7227 Document* aDocument,
7228 nsTArray<nsString>& aTagStack,
7229 bool aPreventScriptExecution,
7230 int32_t aFlags,
7231 DocumentFragment** aReturn) {
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 (!sXMLFragmentParser) {
7239 RefPtr<nsParser> parser = new nsParser();
7240 parser.forget(&sXMLFragmentParser);
7241 // sXMLFragmentParser now owns the parser
7242 }
7243 if (!sXMLFragmentSink) {
7244 NS_NewXMLFragmentContentSink(&sXMLFragmentSink);
7245 // sXMLFragmentSink now owns the sink
7246 }
7247 nsCOMPtr<nsIContentSink> contentsink = do_QueryInterface(sXMLFragmentSink);
7248 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"
, 7248); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentsink"
") (" "Sink doesn't QI to nsIContentSink!" ")"); do { MOZ_CrashSequence
(__null, 7248); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7249 sXMLFragmentParser->SetContentSink(contentsink);
7250
7251 RefPtr<Document> doc;
7252 nsCOMPtr<nsIPrincipal> nodePrincipal = aDocument->NodePrincipal();
7253
7254#ifdef DEBUG1
7255 // aFlags should always be kParseFragmentPrivilegedDefaultSanitization unless
7256 // the caller of ParseFragmentXML is ParserUtils::ParseFragment() which is the
7257 // only caller that intends sanitization. For all other callers we need to
7258 // ensure to call AuditParsingOfHTMLXMLFragments.
7259 if (aFlags == kParseFragmentPrivilegedDefaultSanitization) {
7260 DOMSecurityMonitor::AuditParsingOfHTMLXMLFragments(nodePrincipal,
7261 aSourceBuffer);
7262 }
7263#endif
7264
7265 bool shouldSanitize = ShouldSanitize(nodePrincipal, aFlags);
7266 if (shouldSanitize && !aDocument->IsLoadedAsData()) {
7267 doc = nsContentUtils::CreateInertXMLDocument(aDocument);
7268 } else {
7269 doc = aDocument;
7270 }
7271
7272 sXMLFragmentSink->SetTargetDocument(doc);
7273 sXMLFragmentSink->SetPreventScriptExecution(aPreventScriptExecution);
7274
7275 nsresult rv = sXMLFragmentParser->ParseFragment(aSourceBuffer, aTagStack);
7276 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7277 // Drop the fragment parser and sink that might be in an inconsistent state
7278 NS_IF_RELEASE(sXMLFragmentParser)do { if (sXMLFragmentParser) { (sXMLFragmentParser)->Release
(); (sXMLFragmentParser) = 0; } } while (0)
;
7279 NS_IF_RELEASE(sXMLFragmentSink)do { if (sXMLFragmentSink) { (sXMLFragmentSink)->Release()
; (sXMLFragmentSink) = 0; } } while (0)
;
7280 return rv;
7281 }
7282
7283 rv = sXMLFragmentSink->FinishFragmentParsing(aReturn);
7284
7285 sXMLFragmentParser->Reset();
7286 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"
, 7286); return rv; } } while (false)
;
7287
7288 if (shouldSanitize) {
7289 uint32_t sanitizationFlags =
7290 ComputeSanitizationFlags(nodePrincipal, aFlags);
7291 // Don't fire mutation events for nodes removed by the sanitizer.
7292 nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
7293 nsTreeSanitizer sanitizer(sanitizationFlags);
7294 sanitizer.Sanitize(*aReturn);
7295 }
7296
7297 return rv;
7298}
7299
7300/* static */
7301nsresult nsContentUtils::ConvertToPlainText(const nsAString& aSourceBuffer,
7302 nsAString& aResultBuffer,
7303 uint32_t aFlags,
7304 uint32_t aWrapCol) {
7305 RefPtr<Document> document = nsContentUtils::CreateInertHTMLDocument(nullptr);
7306 if (!document) {
7307 return NS_ERROR_FAILURE;
7308 }
7309
7310 nsresult rv = nsContentUtils::ParseDocumentHTML(
7311 aSourceBuffer, document,
7312 !(aFlags & nsIDocumentEncoder::OutputNoScriptContent));
7313 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"
, 7313); return rv; } } while (false)
;
7314
7315 nsCOMPtr<nsIDocumentEncoder> encoder = do_createDocumentEncoder("text/plain");
7316
7317 rv = encoder->Init(document, u"text/plain"_ns, aFlags);
7318 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"
, 7318); return rv; } } while (false)
;
7319
7320 encoder->SetWrapColumn(aWrapCol);
7321
7322 return encoder->EncodeToString(aResultBuffer);
7323}
7324
7325static already_AddRefed<Document> CreateInertDocument(const Document* aTemplate,
7326 DocumentFlavor aFlavor) {
7327 if (aTemplate) {
7328 bool hasHad = true;
7329 nsIScriptGlobalObject* sgo = aTemplate->GetScriptHandlingObject(hasHad);
7330 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",
7330); return nullptr; } } while (false)
;
7331
7332 nsCOMPtr<Document> doc;
7333 nsresult rv = NS_NewDOMDocument(
7334 getter_AddRefs(doc), u""_ns, u""_ns, nullptr,
7335 aTemplate->GetDocumentURI(), aTemplate->GetDocBaseURI(),
7336 aTemplate->NodePrincipal(), LoadedAsData::AsData, sgo, aFlavor);
7337 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7338 return nullptr;
7339 }
7340 return doc.forget();
7341 }
7342 nsCOMPtr<nsIURI> uri;
7343 NS_NewURI(getter_AddRefs(uri), "about:blank"_ns);
7344 if (!uri) {
7345 return nullptr;
7346 }
7347
7348 RefPtr<NullPrincipal> nullPrincipal =
7349 NullPrincipal::CreateWithoutOriginAttributes();
7350 if (!nullPrincipal) {
7351 return nullptr;
7352 }
7353
7354 nsCOMPtr<Document> doc;
7355 nsresult rv =
7356 NS_NewDOMDocument(getter_AddRefs(doc), u""_ns, u""_ns, nullptr, uri, uri,
7357 nullPrincipal, LoadedAsData::AsData, nullptr, aFlavor);
7358 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7359 return nullptr;
7360 }
7361 return doc.forget();
7362}
7363
7364/* static */
7365already_AddRefed<Document> nsContentUtils::CreateInertXMLDocument(
7366 const Document* aTemplate) {
7367 return CreateInertDocument(aTemplate, DocumentFlavor::XML);
7368}
7369
7370/* static */
7371already_AddRefed<Document> nsContentUtils::CreateInertHTMLDocument(
7372 const Document* aTemplate) {
7373 return CreateInertDocument(aTemplate, DocumentFlavor::HTML);
7374}
7375
7376/* static */
7377nsresult nsContentUtils::SetNodeTextContent(
7378 nsIContent* aContent, const nsAString& aValue, bool aTryReuse,
7379 MutationEffectOnScript aMutationEffectOnScript) {
7380 // Optimize the common case of there being no observers
7381 if (MOZ_UNLIKELY((__builtin_expect(!!(aContent->MaybeNeedsToNotifyDevToolsOfNodeRemovalsInOwnerDoc
()), 0))
7382 aContent->MaybeNeedsToNotifyDevToolsOfNodeRemovalsInOwnerDoc())(__builtin_expect(!!(aContent->MaybeNeedsToNotifyDevToolsOfNodeRemovalsInOwnerDoc
()), 0))
) {
7383 if (aTryReuse) {
7384 bool skipFirstText = true;
7385 for (nsCOMPtr<nsINode> child = aContent->GetFirstChild();
7386 child && child->GetParentNode() == aContent;
7387 child = child->GetNextSibling()) {
7388 if (skipFirstText && child->IsText()) {
7389 skipFirstText = false;
7390 continue;
7391 }
7392 nsContentUtils::NotifyDevToolsOfNodeRemoval(*child);
7393 }
7394 } else {
7395 aContent->NotifyDevToolsOfRemovalsOfChildren();
7396 }
7397 }
7398
7399 // Might as well stick a batch around this since we're performing several
7400 // mutations.
7401 mozAutoDocUpdate updateBatch(aContent->GetComposedDoc(), true);
7402 nsAutoMutationBatch mb;
7403
7404 if (aTryReuse && !aValue.IsEmpty()) {
7405 // Let's remove nodes until we find a eTEXT.
7406 while (aContent->HasChildren()) {
7407 nsIContent* child = aContent->GetFirstChild();
7408 if (child->IsText()) {
7409 break;
7410 }
7411 aContent->RemoveChildNode(child, true, nullptr, nullptr,
7412 aMutationEffectOnScript);
7413 }
7414
7415 // If we have a node, it must be a eTEXT and we reuse it.
7416 if (aContent->HasChildren()) {
7417 nsIContent* child = aContent->GetFirstChild();
7418 nsresult rv = child->AsText()->SetText(aValue, true);
7419 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"
, 7419); return rv; } } while (false)
;
7420
7421 // All the following nodes, if they exist, must be deleted.
7422 while (nsIContent* lastChild = aContent->GetLastChild()) {
7423 if (lastChild == child) {
7424 break;
7425 }
7426 aContent->RemoveChildNode(lastChild, true, nullptr, nullptr,
7427 aMutationEffectOnScript);
7428 }
7429 }
7430
7431 if (aContent->HasChildren()) {
7432 return NS_OK;
7433 }
7434 } else {
7435 mb.Init(aContent, true, false);
7436 aContent->RemoveAllChildren(true);
7437 }
7438 mb.RemovalDone();
7439
7440 if (aValue.IsEmpty()) {
7441 return NS_OK;
7442 }
7443
7444 RefPtr<nsTextNode> textContent = new (aContent->NodeInfo()->NodeInfoManager())
7445 nsTextNode(aContent->NodeInfo()->NodeInfoManager());
7446
7447 textContent->SetText(aValue, true);
7448
7449 ErrorResult rv;
7450 aContent->AppendChildTo(textContent, true, rv, aMutationEffectOnScript);
7451 mb.NodesAdded();
7452 return rv.StealNSResult();
7453}
7454
7455template <typename CharT>
7456static bool AppendNodeTextContentsRecurse(const nsINode* aNode,
7457 nsTSubstring<CharT>& aResult,
7458 const fallible_t& aFallible) {
7459 for (nsIContent* child = aNode->GetFirstChild(); child;
7460 child = child->GetNextSibling()) {
7461 if (child->IsElement()) {
7462 if (!AppendNodeTextContentsRecurse(child, aResult, aFallible)) {
7463 return false;
7464 }
7465 } else if (Text* text = child->GetAsText()) {
7466 if (!text->AppendTextTo(aResult, aFallible)) {
7467 return false;
7468 }
7469 }
7470 }
7471 return true;
7472}
7473
7474template <typename CharT>
7475static bool AppendNodeTextContent(const nsINode* aNode, bool aDeep,
7476 nsTSubstring<CharT>& aResult,
7477 const fallible_t& aFallible) {
7478 if (const Text* text = aNode->GetAsText()) {
7479 return text->AppendTextTo(aResult, aFallible);
7480 }
7481 if (aDeep) {
7482 return AppendNodeTextContentsRecurse(aNode, aResult, aFallible);
7483 }
7484 for (nsIContent* child = aNode->GetFirstChild(); child;
7485 child = child->GetNextSibling()) {
7486 if (Text* text = child->GetAsText()) {
7487 bool ok = text->AppendTextTo(aResult, fallible);
7488 if (!ok) {
7489 return false;
7490 }
7491 }
7492 }
7493 return true;
7494}
7495
7496/* static */
7497bool nsContentUtils::AppendNodeTextContent(const nsINode* aNode, bool aDeep,
7498 nsAString& aResult,
7499 const fallible_t& aFallible) {
7500 return ::AppendNodeTextContent(aNode, aDeep, aResult, aFallible);
7501}
7502
7503bool nsContentUtils::AppendNodeTextContent(const nsINode* aNode, bool aDeep,
7504 nsACString& aResult,
7505 const fallible_t& aFallible) {
7506 return ::AppendNodeTextContent(aNode, aDeep, aResult, aFallible);
7507}
7508
7509bool nsContentUtils::HasNonEmptyTextContent(
7510 nsINode* aNode, TextContentDiscoverMode aDiscoverMode) {
7511 for (nsIContent* child = aNode->GetFirstChild(); child;
7512 child = child->GetNextSibling()) {
7513 if (child->IsText() && child->TextLength() > 0) {
7514 return true;
7515 }
7516
7517 if (aDiscoverMode == eRecurseIntoChildren &&
7518 HasNonEmptyTextContent(child, aDiscoverMode)) {
7519 return true;
7520 }
7521 }
7522
7523 return false;
7524}
7525
7526/* static */
7527bool nsContentUtils::IsInSameAnonymousTree(const nsINode* aNode,
7528 const nsINode* aOtherNode) {
7529 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", 7529
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode" ") (" "Must have a node to work with"
")"); do { MOZ_CrashSequence(__null, 7529); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7530 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", 7530
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOtherNode" ") ("
"Must have a content to work with" ")"); do { MOZ_CrashSequence
(__null, 7530); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7531
7532 const bool anon = aNode->IsInNativeAnonymousSubtree();
7533 if (anon != aOtherNode->IsInNativeAnonymousSubtree()) {
7534 return false;
7535 }
7536
7537 if (anon) {
7538 return aOtherNode->GetClosestNativeAnonymousSubtreeRoot() ==
7539 aNode->GetClosestNativeAnonymousSubtreeRoot();
7540 }
7541
7542 // FIXME: This doesn't deal with disconnected nodes whatsoever, but it didn't
7543 // use to either. Maybe that's fine.
7544 return aNode->GetContainingShadow() == aOtherNode->GetContainingShadow();
7545}
7546
7547/* static */
7548bool nsContentUtils::IsInInteractiveHTMLContent(const Element* aElement,
7549 const Element* aStop) {
7550 const Element* element = aElement;
7551 while (element && element != aStop) {
7552 if (element->IsInteractiveHTMLContent()) {
7553 return true;
7554 }
7555 element = element->GetFlattenedTreeParentElement();
7556 }
7557 return false;
7558}
7559
7560/* static */
7561void nsContentUtils::NotifyInstalledMenuKeyboardListener(bool aInstalling) {
7562 IMEStateManager::OnInstalledMenuKeyboardListener(aInstalling);
7563}
7564
7565/* static */
7566bool nsContentUtils::SchemeIs(nsIURI* aURI, const char* aScheme) {
7567 nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
7568 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", 7568); return
false; } } while (false)
;
7569 return baseURI->SchemeIs(aScheme);
7570}
7571
7572bool nsContentUtils::IsExpandedPrincipal(nsIPrincipal* aPrincipal) {
7573 return aPrincipal && aPrincipal->GetIsExpandedPrincipal();
7574}
7575
7576bool nsContentUtils::IsSystemOrExpandedPrincipal(nsIPrincipal* aPrincipal) {
7577 return (aPrincipal && aPrincipal->IsSystemPrincipal()) ||
7578 IsExpandedPrincipal(aPrincipal);
7579}
7580
7581nsIPrincipal* nsContentUtils::GetSystemPrincipal() {
7582 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", 7582); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInitialized()" ")"); do { MOZ_CrashSequence
(__null, 7582); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7583 return sSystemPrincipal;
7584}
7585
7586bool nsContentUtils::CombineResourcePrincipals(
7587 nsCOMPtr<nsIPrincipal>* aResourcePrincipal, nsIPrincipal* aExtraPrincipal) {
7588 if (!aExtraPrincipal) {
7589 return false;
7590 }
7591 if (!*aResourcePrincipal) {
7592 *aResourcePrincipal = aExtraPrincipal;
7593 return true;
7594 }
7595 if (*aResourcePrincipal == aExtraPrincipal) {
7596 return false;
7597 }
7598 bool subsumes;
7599 if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl((*aResourcePrincipal
)->Subsumes(aExtraPrincipal, &subsumes))), 1)))
7600 (*aResourcePrincipal)->Subsumes(aExtraPrincipal, &subsumes))((bool)(__builtin_expect(!!(!NS_FAILED_impl((*aResourcePrincipal
)->Subsumes(aExtraPrincipal, &subsumes))), 1)))
&&
7601 subsumes) {
7602 return false;
7603 }
7604 *aResourcePrincipal = sSystemPrincipal;
7605 return true;
7606}
7607
7608/* static */
7609void nsContentUtils::TriggerLinkClick(
7610 nsIContent* aContent, nsIURI* aLinkURI, const nsString& aTargetSpec,
7611 UserNavigationInvolvement aUserInvolvement) {
7612 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", 7612
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLinkURI" ") (" "No link URI"
")"); do { MOZ_CrashSequence(__null, 7612); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7613
7614 if (aContent->IsEditable() || !aContent->OwnerDoc()->LinkHandlingEnabled()) {
7615 return;
7616 }
7617
7618 RefPtr<nsDocShell> docShell =
7619 nsDocShell::Cast(aContent->OwnerDoc()->GetDocShell());
7620 if (!docShell) {
7621 return;
7622 }
7623
7624 // Check that this page is allowed to load this URI.
7625 nsresult proceed = NS_OK;
7626
7627 if (sSecurityManager) {
7628 uint32_t flag = static_cast<uint32_t>(nsIScriptSecurityManager::STANDARD);
7629 proceed = sSecurityManager->CheckLoadURIWithPrincipal(
7630 aContent->NodePrincipal(), aLinkURI, flag,
7631 aContent->OwnerDoc()->InnerWindowID());
7632 }
7633
7634 // Only pass off the click event if the script security manager says it's ok.
7635 // We need to rest aTargetSpec for forced downloads.
7636 if (NS_SUCCEEDED(proceed)((bool)(__builtin_expect(!!(!NS_FAILED_impl(proceed)), 1)))) {
7637 // A link/area element with a download attribute is allowed to set
7638 // a pseudo Content-Disposition header.
7639 // For security reasons we only allow websites to declare same-origin
7640 // resources as downloadable. If this check fails we will just do the normal
7641 // thing (i.e. navigate to the resource).
7642 nsAutoString fileName;
7643 if ((!aContent->IsHTMLElement(nsGkAtoms::a) &&
7644 !aContent->IsHTMLElement(nsGkAtoms::area) &&
7645 !aContent->IsSVGElement(nsGkAtoms::a) &&
7646 !(aContent->IsMathMLElement(nsGkAtoms::a) &&
7647 StaticPrefs::mathml_a_element_enabled())) ||
7648 !aContent->AsElement()->GetAttr(nsGkAtoms::download, fileName) ||
7649 NS_FAILED(aContent->NodePrincipal()->CheckMayLoad(aLinkURI, true))((bool)(__builtin_expect(!!(NS_FAILED_impl(aContent->NodePrincipal
()->CheckMayLoad(aLinkURI, true))), 0)))
) {
7650 fileName.SetIsVoid(true); // No actionable download attribute was found.
7651 }
7652
7653 nsCOMPtr<nsIPrincipal> triggeringPrincipal = aContent->NodePrincipal();
7654 nsCOMPtr<nsIPolicyContainer> policyContainer =
7655 aContent->GetPolicyContainer();
7656
7657 // Sanitize fileNames containing null characters by replacing them with
7658 // underscores.
7659 if (!fileName.IsVoid()) {
7660 fileName.ReplaceChar(char16_t(0), '_');
7661 }
7662
7663 docShell->OnLinkClick(
7664 aContent, aLinkURI, fileName.IsVoid() ? aTargetSpec : u""_ns, fileName,
7665 nullptr, nullptr, UserActivation::IsHandlingUserInput(),
7666 aUserInvolvement, triggeringPrincipal, policyContainer);
7667 }
7668}
7669
7670/* static */
7671void nsContentUtils::TriggerLinkMouseOver(nsIContent* aContent,
7672 nsIURI* aLinkURI,
7673 const nsString& aTargetSpec) {
7674 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", 7674
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLinkURI" ") (" "No link URI"
")"); do { MOZ_CrashSequence(__null, 7674); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7675
7676 if (aContent->IsEditable() || !aContent->OwnerDoc()->LinkHandlingEnabled()) {
7677 return;
7678 }
7679
7680 RefPtr<nsDocShell> docShell =
7681 nsDocShell::Cast(aContent->OwnerDoc()->GetDocShell());
7682 if (!docShell) {
7683 return;
7684 }
7685
7686 docShell->OnOverLink(aContent, aLinkURI, aTargetSpec);
7687
7688 if (nsPresContext* pc = aContent->OwnerDoc()->GetPresContext()) {
7689 pc->EventStateManager()->SetLinkOverFrame(aContent->GetPrimaryFrame());
7690 }
7691}
7692
7693/* static */
7694void nsContentUtils::GetLinkLocation(Element* aElement,
7695 nsString& aLocationString) {
7696 nsCOMPtr<nsIURI> hrefURI = aElement->GetHrefURI();
7697 if (hrefURI) {
7698 nsAutoCString specUTF8;
7699 nsresult rv = hrefURI->GetSpec(specUTF8);
7700 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) CopyUTF8toUTF16(specUTF8, aLocationString);
7701 }
7702}
7703
7704/* static */
7705nsIWidget* nsContentUtils::GetTopLevelWidget(nsIWidget* aWidget) {
7706 if (!aWidget) return nullptr;
7707
7708 return aWidget->GetTopLevelWidget();
7709}
7710
7711/* static */
7712const nsDependentString nsContentUtils::GetLocalizedEllipsis() {
7713 static char16_t sBuf[4] = {0, 0, 0, 0};
7714 if (!sBuf[0]) {
7715 if (!nsContentUtils::ShouldResistFingerprinting("No context",
7716 RFPTarget::JSLocale)) {
7717 nsAutoString tmp;
7718 intl::LocaleService::GetInstance()->GetEllipsis(tmp);
7719 uint32_t len =
7720 std::min(uint32_t(tmp.Length()), uint32_t(std::size(sBuf) - 1));
7721 CopyUnicodeTo(tmp, 0, sBuf, len);
7722 }
7723 if (!sBuf[0]) {
7724 sBuf[0] = char16_t(0x2026);
7725 }
7726 }
7727 return nsDependentString(sBuf);
7728}
7729
7730/* static */
7731void nsContentUtils::AddScriptBlocker() {
7732 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", 7732); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 7732); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7733 if (!sScriptBlockerCount) {
7734 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", 7735
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sRunnersCountAtFirstBlocker == 0"
") (" "Should not already have a count" ")"); do { MOZ_CrashSequence
(__null, 7735); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
7735 "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", 7735
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sRunnersCountAtFirstBlocker == 0"
") (" "Should not already have a count" ")"); do { MOZ_CrashSequence
(__null, 7735); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7736 sRunnersCountAtFirstBlocker =
7737 sBlockedScriptRunners ? sBlockedScriptRunners->Length() : 0;
7738 }
7739 ++sScriptBlockerCount;
7740}
7741
7742#ifdef DEBUG1
7743static bool sRemovingScriptBlockers = false;
7744#endif
7745
7746/* static */
7747void nsContentUtils::RemoveScriptBlocker() {
7748 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", 7748); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 7748); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7749 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", 7749); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!sRemovingScriptBlockers" ")"); do { MOZ_CrashSequence
(__null, 7749); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7750 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"
, 7750); MOZ_PretendNoReturn(); } } while (0)
;
7751 --sScriptBlockerCount;
7752 if (sScriptBlockerCount) {
7753 return;
7754 }
7755
7756 if (!sBlockedScriptRunners) {
7757 return;
7758 }
7759
7760 uint32_t firstBlocker = sRunnersCountAtFirstBlocker;
7761 uint32_t lastBlocker = sBlockedScriptRunners->Length();
7762 uint32_t originalFirstBlocker = firstBlocker;
7763 uint32_t blockersCount = lastBlocker - firstBlocker;
7764 sRunnersCountAtFirstBlocker = 0;
7765 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", 7765); MOZ_PretendNoReturn
(); } } while (0)
;
7766
7767 while (firstBlocker < lastBlocker) {
7768 nsCOMPtr<nsIRunnable> runnable;
7769 runnable.swap((*sBlockedScriptRunners)[firstBlocker]);
7770 ++firstBlocker;
7771
7772 // Calling the runnable can reenter us
7773 {
7774 AUTO_PROFILE_FOLLOWING_RUNNABLE(runnable)mozilla::Maybe<mozilla::AutoProfileRunnable> raiiRunnableMarker
; if (profiler_thread_is_profiling_runnables()) { raiiRunnableMarker
.emplace(runnable); }
;
7775 runnable->Run();
7776 }
7777 // So can dropping the reference to the runnable
7778 runnable = nullptr;
7779
7780 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", 7780); MOZ_PretendNoReturn
(); } } while (0)
;
7781 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"
, 7781); MOZ_PretendNoReturn(); } } while (0)
;
7782 }
7783#ifdef DEBUG1
7784 AutoRestore<bool> removingScriptBlockers(sRemovingScriptBlockers);
7785 sRemovingScriptBlockers = true;
7786#endif
7787 sBlockedScriptRunners->RemoveElementsAt(originalFirstBlocker, blockersCount);
7788}
7789
7790nsAutoMicroTaskForDocument::nsAutoMicroTaskForDocument(
7791 const Document* aDocument)
7792 : mContext(aDocument && aDocument->GetInnerWindow()
7793 ? CycleCollectedJSContext::Get()
7794 : nullptr) {
7795 if (mContext) {
7796 mContext->EnterMicroTask();
7797 }
7798}
7799
7800nsAutoMicroTaskForDocument::~nsAutoMicroTaskForDocument() {
7801 if (mContext) {
7802 mContext->LeaveMicroTask();
7803 }
7804}
7805
7806/* static */
7807already_AddRefed<nsPIDOMWindowOuter>
7808nsContentUtils::GetMostRecentNonPBWindow() {
7809 nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID"@mozilla.org/appshell/window-mediator;1");
7810
7811 nsCOMPtr<mozIDOMWindowProxy> window;
7812 wm->GetMostRecentNonPBWindow(u"navigator:browser", getter_AddRefs(window));
7813 nsCOMPtr<nsPIDOMWindowOuter> pwindow;
7814 pwindow = do_QueryInterface(window);
7815
7816 return pwindow.forget();
7817}
7818
7819/* static */
7820already_AddRefed<nsPIDOMWindowOuter> nsContentUtils::GetMostRecentWindowBy(
7821 WindowMediatorFilter aFilter) {
7822 nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID"@mozilla.org/appshell/window-mediator;1");
7823
7824 nsCOMPtr<mozIDOMWindowProxy> window;
7825 wm->GetMostRecentWindowBy(u"navigator:browser", static_cast<uint8_t>(aFilter),
7826 getter_AddRefs(window));
7827 nsCOMPtr<nsPIDOMWindowOuter> pwindow;
7828 pwindow = do_QueryInterface(window);
7829
7830 return pwindow.forget();
7831}
7832
7833/* static */
7834void nsContentUtils::WarnScriptWasIgnored(Document* aDocument) {
7835 nsAutoString msg;
7836 bool privateBrowsing = false;
7837 bool chromeContext = false;
7838
7839 if (aDocument) {
7840 nsCOMPtr<nsIURI> uri = aDocument->GetDocumentURI();
7841 if (uri) {
7842 msg.Append(NS_ConvertUTF8toUTF16(uri->GetSpecOrDefault()));
7843 msg.AppendLiteral(" : ");
7844 }
7845 privateBrowsing =
7846 aDocument->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing();
7847 chromeContext = aDocument->NodePrincipal()->IsSystemPrincipal();
7848 }
7849
7850 msg.AppendLiteral(
7851 "Unable to run script because scripts are blocked internally.");
7852 LogSimpleConsoleError(msg, "DOM"_ns, privateBrowsing, chromeContext);
7853}
7854
7855/* static */
7856void nsContentUtils::AddScriptRunner(already_AddRefed<nsIRunnable> aRunnable) {
7857 nsCOMPtr<nsIRunnable> runnable = aRunnable;
7858 if (!runnable) {
7859 return;
7860 }
7861
7862 if (sScriptBlockerCount) {
7863 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)
7864 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)
;
7865 sBlockedScriptRunners->AppendElement(runnable.forget());
7866 return;
7867 }
7868
7869 AUTO_PROFILE_FOLLOWING_RUNNABLE(runnable)mozilla::Maybe<mozilla::AutoProfileRunnable> raiiRunnableMarker
; if (profiler_thread_is_profiling_runnables()) { raiiRunnableMarker
.emplace(runnable); }
;
7870 runnable->Run();
7871}
7872
7873/* static */
7874void nsContentUtils::AddScriptRunner(nsIRunnable* aRunnable) {
7875 nsCOMPtr<nsIRunnable> runnable = aRunnable;
7876 AddScriptRunner(runnable.forget());
7877}
7878
7879/* static */ bool nsContentUtils::IsSafeToRunScript() {
7880 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", 7881
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "This static variable only makes sense on the main thread!"
")"); do { MOZ_CrashSequence(__null, 7881); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7881 "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", 7881
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "This static variable only makes sense on the main thread!"
")"); do { MOZ_CrashSequence(__null, 7881); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7882 return sScriptBlockerCount == 0;
7883}
7884
7885/* static */
7886void nsContentUtils::RunInStableState(already_AddRefed<nsIRunnable> aRunnable) {
7887 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", 7887
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()"
") (" "Must be on a script thread!" ")"); do { MOZ_CrashSequence
(__null, 7887); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7888 CycleCollectedJSContext::Get()->RunInStableState(std::move(aRunnable));
7889}
7890
7891/* static */
7892void nsContentUtils::AddPendingIDBTransaction(
7893 already_AddRefed<nsIRunnable> aTransaction) {
7894 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", 7894
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()"
") (" "Must be on a script thread!" ")"); do { MOZ_CrashSequence
(__null, 7894); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7895 CycleCollectedJSContext::Get()->AddPendingIDBTransaction(
7896 std::move(aTransaction));
7897}
7898
7899/* static */
7900bool nsContentUtils::IsInStableOrMetaStableState() {
7901 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", 7901
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()"
") (" "Must be on a script thread!" ")"); do { MOZ_CrashSequence
(__null, 7901); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7902 return CycleCollectedJSContext::Get()->IsInStableOrMetaStableState();
7903}
7904
7905/* static */
7906void nsContentUtils::HidePopupsInDocument(Document* aDocument) {
7907 RefPtr<nsXULPopupManager> pm = nsXULPopupManager::GetInstance();
7908 if (!pm || !aDocument) {
7909 return;
7910 }
7911 nsCOMPtr<nsIDocShellTreeItem> docShellToHide = aDocument->GetDocShell();
7912 if (docShellToHide) {
7913 pm->HidePopupsInDocShell(docShellToHide);
7914 }
7915}
7916
7917/* static */
7918already_AddRefed<nsIDragSession> nsContentUtils::GetDragSession(
7919 nsIWidget* aWidget) {
7920 nsCOMPtr<nsIDragSession> dragSession;
7921 nsCOMPtr<nsIDragService> dragService =
7922 do_GetService("@mozilla.org/widget/dragservice;1");
7923 if (dragService) {
7924 dragSession = dragService->GetCurrentSession(aWidget);
7925 }
7926 return dragSession.forget();
7927}
7928
7929/* static */
7930already_AddRefed<nsIDragSession> nsContentUtils::GetDragSession(
7931 nsPresContext* aPC) {
7932 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"
, 7932); return nullptr; } } while (false)
;
7933 auto* widget = aPC->GetRootWidget();
7934 if (!widget) {
7935 return nullptr;
7936 }
7937 return GetDragSession(widget);
7938}
7939
7940/* static */
7941nsresult nsContentUtils::SetDataTransferInEvent(WidgetDragEvent* aDragEvent) {
7942 if (aDragEvent->mDataTransfer || !aDragEvent->IsTrusted()) {
7943 return NS_OK;
7944 }
7945
7946 // For dragstart events, the data transfer object is
7947 // created before the event fires, so it should already be set. For other
7948 // drag events, get the object from the drag session.
7949 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"
, 7950); MOZ_PretendNoReturn(); } } while (0)
7950 "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"
, 7950); MOZ_PretendNoReturn(); } } while (0)
;
7951
7952 nsCOMPtr<nsIDragSession> dragSession = GetDragSession(aDragEvent->mWidget);
7953 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",
7953); return NS_OK; } } while (false)
; // no drag in progress
7954
7955 RefPtr<DataTransfer> initialDataTransfer = dragSession->GetDataTransfer();
7956 if (!initialDataTransfer) {
7957 // A dataTransfer won't exist when a drag was started by some other
7958 // means, for instance calling the drag service directly, or a drag
7959 // from another application. In either case, a new dataTransfer should
7960 // be created that reflects the data.
7961 initialDataTransfer = new DataTransfer(
7962 aDragEvent->mTarget, aDragEvent->mMessage, true, Nothing());
7963
7964 // now set it in the drag session so we don't need to create it again
7965 dragSession->SetDataTransfer(initialDataTransfer);
7966 }
7967
7968 bool isCrossDomainSubFrameDrop = false;
7969 if (aDragEvent->mMessage == eDrop) {
7970 isCrossDomainSubFrameDrop = CheckForSubFrameDrop(dragSession, aDragEvent);
7971 }
7972
7973 // each event should use a clone of the original dataTransfer.
7974 initialDataTransfer->Clone(
7975 aDragEvent->mTarget, aDragEvent->mMessage, aDragEvent->mUserCancelled,
7976 isCrossDomainSubFrameDrop, getter_AddRefs(aDragEvent->mDataTransfer));
7977 if (NS_WARN_IF(!aDragEvent->mDataTransfer)NS_warn_if_impl(!aDragEvent->mDataTransfer, "!aDragEvent->mDataTransfer"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7977)
) {
7978 return NS_ERROR_OUT_OF_MEMORY;
7979 }
7980
7981 // for the dragenter and dragover events, initialize the drop effect
7982 // from the drop action, which platform specific widget code sets before
7983 // the event is fired based on the keyboard state.
7984 if (aDragEvent->mMessage == eDragEnter || aDragEvent->mMessage == eDragOver) {
7985 uint32_t action;
7986 dragSession->GetDragAction(&action);
7987 uint32_t effectAllowed = aDragEvent->mDataTransfer->EffectAllowedInt();
7988 aDragEvent->mDataTransfer->SetDropEffectInt(
7989 FilterDropEffect(action, effectAllowed));
7990 } else if (aDragEvent->mMessage == eDrop ||
7991 aDragEvent->mMessage == eDragEnd) {
7992 // For the drop and dragend events, set the drop effect based on the
7993 // last value that the dropEffect had. This will have been set in
7994 // EventStateManager::PostHandleEvent for the last dragenter or
7995 // dragover event.
7996 aDragEvent->mDataTransfer->SetDropEffectInt(
7997 initialDataTransfer->DropEffectInt());
7998 }
7999
8000 return NS_OK;
8001}
8002
8003/* static */
8004uint32_t nsContentUtils::FilterDropEffect(uint32_t aAction,
8005 uint32_t aEffectAllowed) {
8006 // It is possible for the drag action to include more than one action, but
8007 // the widget code which sets the action from the keyboard state should only
8008 // be including one. If multiple actions were set, we just consider them in
8009 // the following order:
8010 // copy, link, move
8011 if (aAction & nsIDragService::DRAGDROP_ACTION_COPY)
8012 aAction = nsIDragService::DRAGDROP_ACTION_COPY;
8013 else if (aAction & nsIDragService::DRAGDROP_ACTION_LINK)
8014 aAction = nsIDragService::DRAGDROP_ACTION_LINK;
8015 else if (aAction & nsIDragService::DRAGDROP_ACTION_MOVE)
8016 aAction = nsIDragService::DRAGDROP_ACTION_MOVE;
8017
8018 // Filter the action based on the effectAllowed. If the effectAllowed
8019 // doesn't include the action, then that action cannot be done, so adjust
8020 // the action to something that is allowed. For a copy, adjust to move or
8021 // link. For a move, adjust to copy or link. For a link, adjust to move or
8022 // link. Otherwise, use none.
8023 if (aAction & aEffectAllowed ||
8024 aEffectAllowed == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED)
8025 return aAction;
8026 if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_MOVE)
8027 return nsIDragService::DRAGDROP_ACTION_MOVE;
8028 if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_COPY)
8029 return nsIDragService::DRAGDROP_ACTION_COPY;
8030 if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_LINK)
8031 return nsIDragService::DRAGDROP_ACTION_LINK;
8032 return nsIDragService::DRAGDROP_ACTION_NONE;
8033}
8034
8035/* static */
8036bool nsContentUtils::CheckForSubFrameDrop(nsIDragSession* aDragSession,
8037 WidgetDragEvent* aDropEvent) {
8038 nsCOMPtr<nsIContent> target =
8039 nsIContent::FromEventTargetOrNull(aDropEvent->mOriginalTarget);
8040 if (!target) {
8041 return true;
8042 }
8043
8044 // Always allow dropping onto chrome shells.
8045 BrowsingContext* targetBC = target->OwnerDoc()->GetBrowsingContext();
8046 if (targetBC->IsChrome()) {
8047 return false;
8048 }
8049
8050 WindowContext* targetWC = target->OwnerDoc()->GetWindowContext();
8051
8052 // If there is no source browsing context, then this is a drag from another
8053 // application, which should be allowed.
8054 RefPtr<WindowContext> sourceWC;
8055 aDragSession->GetSourceWindowContext(getter_AddRefs(sourceWC));
8056 if (sourceWC) {
8057 // Get each successive parent of the source document and compare it to
8058 // the drop document. If they match, then this is a drag from a child frame.
8059 for (sourceWC = sourceWC->GetParentWindowContext(); sourceWC;
8060 sourceWC = sourceWC->GetParentWindowContext()) {
8061 // If the source and the target match, then the drag started in a
8062 // descendant frame. If the source is discarded, err on the side of
8063 // caution and treat it as a subframe drag.
8064 if (sourceWC == targetWC || sourceWC->IsDiscarded()) {
8065 return true;
8066 }
8067 }
8068 }
8069
8070 return false;
8071}
8072
8073/* static */
8074bool nsContentUtils::URIIsLocalFile(nsIURI* aURI) {
8075 bool isFile;
8076 nsCOMPtr<nsINetUtil> util = mozilla::components::IO::Service();
8077
8078 // Important: we do NOT test the entire URI chain here!
8079 return util &&
8080 NS_SUCCEEDED(util->ProtocolHasFlags(((bool)(__builtin_expect(!!(!NS_FAILED_impl(util->ProtocolHasFlags
( aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile)))
, 1)))
8081 aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile))((bool)(__builtin_expect(!!(!NS_FAILED_impl(util->ProtocolHasFlags
( aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile)))
, 1)))
&&
8082 isFile;
8083}
8084
8085/* static */
8086JSContext* nsContentUtils::GetCurrentJSContext() {
8087 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", 8087); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInitialized()" ")"); do { MOZ_CrashSequence
(__null, 8087); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8088 if (!IsJSAPIActive()) {
8089 return nullptr;
8090 }
8091 return danger::GetJSContext();
8092}
8093
8094template <typename StringType, typename CharType>
8095void _ASCIIToLowerInSitu(StringType& aStr) {
8096 CharType* iter = aStr.BeginWriting();
8097 CharType* end = aStr.EndWriting();
8098 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", 8098); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "iter && end" ")"); do { MOZ_CrashSequence
(__null, 8098); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8099
8100 while (iter != end) {
8101 CharType c = *iter;
8102 if (c >= 'A' && c <= 'Z') {
8103 *iter = c + ('a' - 'A');
8104 }
8105 ++iter;
8106 }
8107}
8108
8109/* static */
8110void nsContentUtils::ASCIIToLower(nsAString& aStr) {
8111 return _ASCIIToLowerInSitu<nsAString, char16_t>(aStr);
8112}
8113
8114/* static */
8115void nsContentUtils::ASCIIToLower(nsACString& aStr) {
8116 return _ASCIIToLowerInSitu<nsACString, char>(aStr);
8117}
8118
8119template <typename StringType, typename CharType>
8120void _ASCIIToLowerCopy(const StringType& aSource, StringType& aDest) {
8121 uint32_t len = aSource.Length();
8122 aDest.SetLength(len);
8123 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", 8123); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aDest.Length() == len" ")"); do { MOZ_CrashSequence
(__null, 8123); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8124
8125 CharType* dest = aDest.BeginWriting();
8126 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"
, 8126); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dest" ")");
do { MOZ_CrashSequence(__null, 8126); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8127
8128 const CharType* iter = aSource.BeginReading();
8129 const CharType* end = aSource.EndReading();
8130 while (iter != end) {
8131 CharType c = *iter;
8132 *dest = (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
8133 ++iter;
8134 ++dest;
8135 }
8136}
8137
8138/* static */
8139void nsContentUtils::ASCIIToLower(const nsAString& aSource, nsAString& aDest) {
8140 return _ASCIIToLowerCopy<nsAString, char16_t>(aSource, aDest);
8141}
8142
8143/* static */
8144void nsContentUtils::ASCIIToLower(const nsACString& aSource,
8145 nsACString& aDest) {
8146 return _ASCIIToLowerCopy<nsACString, char>(aSource, aDest);
8147}
8148
8149template <typename StringType, typename CharType>
8150void _ASCIIToUpperInSitu(StringType& aStr) {
8151 CharType* iter = aStr.BeginWriting();
8152 CharType* end = aStr.EndWriting();
8153 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", 8153); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "iter && end" ")"); do { MOZ_CrashSequence
(__null, 8153); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8154
8155 while (iter != end) {
8156 CharType c = *iter;
8157 if (c >= 'a' && c <= 'z') {
8158 *iter = c + ('A' - 'a');
8159 }
8160 ++iter;
8161 }
8162}
8163
8164/* static */
8165void nsContentUtils::ASCIIToUpper(nsAString& aStr) {
8166 return _ASCIIToUpperInSitu<nsAString, char16_t>(aStr);
8167}
8168
8169/* static */
8170void nsContentUtils::ASCIIToUpper(nsACString& aStr) {
8171 return _ASCIIToUpperInSitu<nsACString, char>(aStr);
8172}
8173
8174template <typename StringType, typename CharType>
8175void _ASCIIToUpperCopy(const StringType& aSource, StringType& aDest) {
8176 uint32_t len = aSource.Length();
8177 aDest.SetLength(len);
8178 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", 8178); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aDest.Length() == len" ")"); do { MOZ_CrashSequence
(__null, 8178); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8179
8180 CharType* dest = aDest.BeginWriting();
8181 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"
, 8181); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dest" ")");
do { MOZ_CrashSequence(__null, 8181); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8182
8183 const CharType* iter = aSource.BeginReading();
8184 const CharType* end = aSource.EndReading();
8185 while (iter != end) {
8186 CharType c = *iter;
8187 *dest = (c >= 'a' && c <= 'z') ? c + ('A' - 'a') : c;
8188 ++iter;
8189 ++dest;
8190 }
8191}
8192
8193/* static */
8194void nsContentUtils::ASCIIToUpper(const nsAString& aSource, nsAString& aDest) {
8195 return _ASCIIToUpperCopy<nsAString, char16_t>(aSource, aDest);
8196}
8197
8198/* static */
8199void nsContentUtils::ASCIIToUpper(const nsACString& aSource,
8200 nsACString& aDest) {
8201 return _ASCIIToUpperCopy<nsACString, char>(aSource, aDest);
8202}
8203
8204/* static */
8205bool nsContentUtils::EqualsIgnoreASCIICase(nsAtom* aAtom1, nsAtom* aAtom2) {
8206 if (aAtom1 == aAtom2) {
8207 return true;
8208 }
8209
8210 // If both are ascii lowercase already, we know that the slow comparison
8211 // below is going to return false.
8212 if (aAtom1->IsAsciiLowercase() && aAtom2->IsAsciiLowercase()) {
8213 return false;
8214 }
8215
8216 return EqualsIgnoreASCIICase(nsDependentAtomString(aAtom1),
8217 nsDependentAtomString(aAtom2));
8218}
8219
8220/* static */
8221bool nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1,
8222 const nsAString& aStr2) {
8223 uint32_t len = aStr1.Length();
8224 if (len != aStr2.Length()) {
8225 return false;
8226 }
8227
8228 const char16_t* str1 = aStr1.BeginReading();
8229 const char16_t* str2 = aStr2.BeginReading();
8230 const char16_t* end = str1 + len;
8231
8232 while (str1 < end) {
8233 char16_t c1 = *str1++;
8234 char16_t c2 = *str2++;
8235
8236 // First check if any bits other than the 0x0020 differs
8237 if ((c1 ^ c2) & 0xffdf) {
8238 return false;
8239 }
8240
8241 // We know they can only differ in the 0x0020 bit.
8242 // Likely the two chars are the same, so check that first
8243 if (c1 != c2) {
8244 // They do differ, but since it's only in the 0x0020 bit, check if it's
8245 // the same ascii char, but just differing in case
8246 char16_t c1Upper = c1 & 0xffdf;
8247 if (!('A' <= c1Upper && c1Upper <= 'Z')) {
8248 return false;
8249 }
8250 }
8251 }
8252
8253 return true;
8254}
8255
8256/* static */
8257bool nsContentUtils::StringContainsASCIIUpper(const nsAString& aStr) {
8258 const char16_t* iter = aStr.BeginReading();
8259 const char16_t* end = aStr.EndReading();
8260 while (iter != end) {
8261 char16_t c = *iter;
8262 if (c >= 'A' && c <= 'Z') {
8263 return true;
8264 }
8265 ++iter;
8266 }
8267
8268 return false;
8269}
8270
8271/* static */
8272nsIInterfaceRequestor* nsContentUtils::SameOriginChecker() {
8273 if (!sSameOriginChecker) {
8274 sSameOriginChecker = new SameOriginCheckerImpl();
8275 NS_ADDREF(sSameOriginChecker)(sSameOriginChecker)->AddRef();
8276 }
8277 return sSameOriginChecker;
8278}
8279
8280/* static */
8281nsresult nsContentUtils::CheckSameOrigin(nsIChannel* aOldChannel,
8282 nsIChannel* aNewChannel) {
8283 if (!nsContentUtils::GetSecurityManager()) return NS_ERROR_NOT_AVAILABLE;
8284
8285 nsCOMPtr<nsIPrincipal> oldPrincipal;
8286 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
8287 aOldChannel, getter_AddRefs(oldPrincipal));
8288
8289 nsCOMPtr<nsIURI> newURI;
8290 aNewChannel->GetURI(getter_AddRefs(newURI));
8291 nsCOMPtr<nsIURI> newOriginalURI;
8292 aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
8293
8294 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"
, 8294); return NS_ERROR_UNEXPECTED; } } while (false)
;
8295
8296 nsresult rv = oldPrincipal->CheckMayLoad(newURI, false);
8297 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && newOriginalURI != newURI) {
8298 rv = oldPrincipal->CheckMayLoad(newOriginalURI, false);
8299 }
8300
8301 return rv;
8302}
8303
8304NS_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"
, 8305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 8305
); __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"
, 8305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 8305); __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", 8305
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 8305
); __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"
, 8305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 8305); __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"
, 8305); 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; }
8305 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"
, 8305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 8305
); __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"
, 8305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 8305); __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", 8305
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 8305
); __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"
, 8305); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 8305); __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"
, 8305); 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; }
8306
8307NS_IMETHODIMPnsresult
8308SameOriginCheckerImpl::AsyncOnChannelRedirect(
8309 nsIChannel* aOldChannel, nsIChannel* aNewChannel, uint32_t aFlags,
8310 nsIAsyncVerifyRedirectCallback* cb) {
8311 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"
, 8311); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewChannel"
") (" "Redirecting to null channel?" ")"); do { MOZ_CrashSequence
(__null, 8311); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8312
8313 nsresult rv = nsContentUtils::CheckSameOrigin(aOldChannel, aNewChannel);
8314 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
8315 cb->OnRedirectVerifyCallback(NS_OK);
8316 }
8317
8318 return rv;
8319}
8320
8321NS_IMETHODIMPnsresult
8322SameOriginCheckerImpl::GetInterface(const nsIID& aIID, void** aResult) {
8323 return QueryInterface(aIID, aResult);
8324}
8325
8326/* static */
8327nsresult nsContentUtils::GetWebExposedOriginSerialization(nsIURI* aURI,
8328 nsACString& aOrigin) {
8329 nsresult rv;
8330 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"
, 8330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"missing uri" ")"); do { MOZ_CrashSequence(__null, 8330); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
8331
8332 // For Blob URI, the path is the URL of the owning page.
8333 if (aURI->SchemeIs(BLOBURI_SCHEME"blob")) {
8334 nsAutoCString path;
8335 rv = aURI->GetPathQueryRef(path);
8336 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"
, 8336); return rv; } } while (false)
;
8337
8338 nsCOMPtr<nsIURI> uri;
8339 rv = NS_NewURI(getter_AddRefs(uri), path);
8340 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8341 aOrigin.AssignLiteral("null");
8342 return NS_OK;
8343 }
8344
8345 if (
8346 // Schemes in spec. https://url.spec.whatwg.org/#origin
8347 !net::SchemeIsHttpOrHttps(uri) && !uri->SchemeIs("file") &&
8348 !uri->SchemeIs("resource") &&
8349 // Our own schemes.
8350 !uri->SchemeIs("moz-extension")) {
8351 aOrigin.AssignLiteral("null");
8352 return NS_OK;
8353 }
8354
8355 return GetWebExposedOriginSerialization(uri, aOrigin);
8356 }
8357
8358 nsAutoCString scheme;
8359 aURI->GetScheme(scheme);
8360
8361 // If the protocol doesn't have URI_HAS_WEB_EXPOSED_ORIGIN, then
8362 // return "null" as the origin serialization.
8363 // We make an exception for "ftp" since we don't have a protocol handler
8364 // for this scheme
8365 uint32_t flags = 0;
8366 nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service(&rv);
8367 if (!scheme.Equals("ftp") && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) &&
8368 NS_SUCCEEDED(io->GetProtocolFlags(scheme.get(), &flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(io->GetProtocolFlags
(scheme.get(), &flags))), 1)))
) {
8369 if (!(flags & nsIProtocolHandler::URI_HAS_WEB_EXPOSED_ORIGIN)) {
8370 aOrigin.AssignLiteral("null");
8371 return NS_OK;
8372 }
8373 }
8374
8375 aOrigin.Truncate();
8376
8377 nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
8378 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"
, 8378); return NS_ERROR_UNEXPECTED; } } while (false)
;
8379
8380 nsAutoCString host;
8381 rv = uri->GetAsciiHost(host);
8382
8383 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !host.IsEmpty()) {
8384 nsAutoCString userPass;
8385 uri->GetUserPass(userPass);
8386
8387 nsAutoCString prePath;
8388 if (!userPass.IsEmpty()) {
8389 rv = NS_MutateURI(uri).SetUserPass(""_ns).Finalize(uri);
8390 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"
, 8390); return rv; } } while (false)
;
8391 }
8392
8393 rv = uri->GetPrePath(prePath);
8394 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"
, 8394); return rv; } } while (false)
;
8395
8396 aOrigin = std::move(prePath);
8397 } else {
8398 aOrigin.AssignLiteral("null");
8399 }
8400
8401 return NS_OK;
8402}
8403
8404/* static */
8405nsresult nsContentUtils::GetWebExposedOriginSerialization(
8406 nsIPrincipal* aPrincipal, nsAString& aOrigin) {
8407 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", 8407
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal" ") ("
"missing principal" ")"); do { MOZ_CrashSequence(__null, 8407
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
8408
8409 aOrigin.Truncate();
8410 nsAutoCString webExposedOriginSerialization;
8411
8412 nsresult rv = aPrincipal->GetWebExposedOriginSerialization(
8413 webExposedOriginSerialization);
8414 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8415 webExposedOriginSerialization.AssignLiteral("null");
8416 }
8417
8418 CopyUTF8toUTF16(webExposedOriginSerialization, aOrigin);
8419 return NS_OK;
8420}
8421
8422/* static */
8423nsresult nsContentUtils::GetWebExposedOriginSerialization(nsIURI* aURI,
8424 nsAString& aOrigin) {
8425 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"
, 8425); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"missing uri" ")"); do { MOZ_CrashSequence(__null, 8425); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
8426 nsresult rv;
8427
8428#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
8429 // Check if either URI has a special origin.
8430 nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin =
8431 do_QueryInterface(aURI);
8432 if (uriWithSpecialOrigin) {
8433 nsCOMPtr<nsIURI> origin;
8434 rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
8435 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"
, 8435); return rv; } } while (false)
;
8436
8437 return GetWebExposedOriginSerialization(origin, aOrigin);
8438 }
8439#endif
8440
8441 nsAutoCString webExposedOriginSerialization;
8442 rv = GetWebExposedOriginSerialization(aURI, webExposedOriginSerialization);
8443 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"
, 8443); return rv; } } while (false)
;
8444
8445 CopyUTF8toUTF16(webExposedOriginSerialization, aOrigin);
8446 return NS_OK;
8447}
8448
8449/* static */
8450bool nsContentUtils::CheckMayLoad(nsIPrincipal* aPrincipal,
8451 nsIChannel* aChannel,
8452 bool aAllowIfInheritsPrincipal) {
8453 nsCOMPtr<nsIURI> channelURI;
8454 nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
8455 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"
, 8455); return false; } } while (false)
;
8456
8457 return NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->CheckMayLoad
(channelURI, aAllowIfInheritsPrincipal))), 1)))
8458 aPrincipal->CheckMayLoad(channelURI, aAllowIfInheritsPrincipal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->CheckMayLoad
(channelURI, aAllowIfInheritsPrincipal))), 1)))
;
8459}
8460
8461/* static */
8462bool nsContentUtils::CanAccessNativeAnon() {
8463 return LegacyIsCallerChromeOrNativeCode();
8464}
8465
8466/* static */
8467nsresult nsContentUtils::DispatchXULCommand(nsIContent* aTarget, bool aTrusted,
8468 Event* aSourceEvent,
8469 PresShell* aPresShell, bool aCtrl,
8470 bool aAlt, bool aShift, bool aMeta,
8471 uint16_t aInputSource,
8472 int16_t aButton) {
8473 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", 8473); return
NS_ERROR_UNEXPECTED; } } while (false)
;
8474 Document* doc = aTarget->OwnerDoc();
8475 nsPresContext* presContext = doc->GetPresContext();
8476
8477 RefPtr<XULCommandEvent> xulCommand =
8478 new XULCommandEvent(doc, presContext, nullptr);
8479 xulCommand->InitCommandEvent(u"command"_ns, true, true,
8480 nsGlobalWindowInner::Cast(doc->GetInnerWindow()),
8481 0, aCtrl, aAlt, aShift, aMeta, aButton,
8482 aSourceEvent, aInputSource, IgnoreErrors());
8483
8484 if (aPresShell) {
8485 nsEventStatus status = nsEventStatus_eIgnore;
8486 return aPresShell->HandleDOMEventWithTarget(aTarget, xulCommand, &status);
8487 }
8488
8489 ErrorResult rv;
8490 aTarget->DispatchEvent(*xulCommand, rv);
8491 return rv.StealNSResult();
8492}
8493
8494// static
8495nsresult nsContentUtils::WrapNative(JSContext* cx, nsISupports* native,
8496 nsWrapperCache* cache, const nsIID* aIID,
8497 JS::MutableHandle<JS::Value> vp,
8498 bool aAllowWrapping) {
8499 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", 8499); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "cx == GetCurrentJSContext()" ")"); do { MOZ_CrashSequence
(__null, 8499); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8500
8501 if (!native) {
8502 vp.setNull();
8503
8504 return NS_OK;
8505 }
8506
8507 JSObject* wrapper = xpc_FastGetCachedWrapper(cx, cache, vp);
8508 if (wrapper) {
8509 return NS_OK;
8510 }
8511
8512 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", 8512
); return NS_ERROR_UNEXPECTED; } } while (false)
;
8513
8514 if (!NS_IsMainThread()) {
8515 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8515); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { MOZ_CrashSequence
(__null, 8515); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
8516 }
8517
8518 JS::Rooted<JSObject*> scope(cx, JS::CurrentGlobalOrNull(cx));
8519 nsresult rv = sXPConnect->WrapNativeToJSVal(cx, scope, native, cache, aIID,
8520 aAllowWrapping, vp);
8521 return rv;
8522}
8523
8524void nsContentUtils::StripNullChars(const nsAString& aInStr,
8525 nsAString& aOutStr) {
8526 // In common cases where we don't have nulls in the
8527 // string we can simple simply bypass the checking code.
8528 int32_t firstNullPos = aInStr.FindChar('\0');
8529 if (firstNullPos == kNotFound) {
8530 aOutStr.Assign(aInStr);
8531 return;
8532 }
8533
8534 aOutStr.SetCapacity(aInStr.Length() - 1);
8535 nsAString::const_iterator start, end;
8536 aInStr.BeginReading(start);
8537 aInStr.EndReading(end);
8538 while (start != end) {
8539 if (*start != '\0') aOutStr.Append(*start);
8540 ++start;
8541 }
8542}
8543
8544struct ClassMatchingInfo {
8545 AtomArray mClasses;
8546 nsCaseTreatment mCaseTreatment;
8547};
8548
8549// static
8550bool nsContentUtils::MatchClassNames(Element* aElement, int32_t aNamespaceID,
8551 nsAtom* aAtom, void* aData) {
8552 // We can't match if there are no class names
8553 const nsAttrValue* classAttr = aElement->GetClasses();
8554 if (!classAttr) {
8555 return false;
8556 }
8557
8558 // need to match *all* of the classes
8559 ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
8560 if (info->mClasses.IsEmpty()) {
8561 // If we actually had no classes, don't match.
8562 return false;
8563 }
8564
8565 for (nsAtom* cls : info->mClasses) {
8566 if (!classAttr->Contains(cls, info->mCaseTreatment)) {
8567 return false;
8568 }
8569 }
8570 return true;
8571}
8572
8573// static
8574void nsContentUtils::DestroyClassNameArray(void* aData) {
8575 ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
8576 delete info;
8577}
8578
8579// static
8580void* nsContentUtils::AllocClassMatchingInfo(nsINode* aRootNode,
8581 const nsString* aClasses) {
8582 nsAttrValue attrValue;
8583 attrValue.ParseAtomArray(*aClasses);
8584 // nsAttrValue::Equals is sensitive to order, so we'll send an array
8585 auto* info = new ClassMatchingInfo;
8586 if (attrValue.Type() == nsAttrValue::eAtomArray) {
8587 info->mClasses.AppendElements(attrValue.GetAtomArrayValue()->Array());
8588 } else if (attrValue.Type() == nsAttrValue::eAtom) {
8589 info->mClasses.AppendElement(attrValue.GetAtomValue());
8590 }
8591
8592 info->mCaseTreatment =
8593 aRootNode->OwnerDoc()->GetCompatibilityMode() == eCompatibility_NavQuirks
8594 ? eIgnoreCase
8595 : eCaseMatters;
8596 return info;
8597}
8598
8599void nsContentUtils::FlushLayoutForTree(nsPIDOMWindowOuter* aWindow) {
8600 if (!aWindow) {
8601 return;
8602 }
8603
8604 // Note that because FlushPendingNotifications flushes parents, this
8605 // is O(N^2) in docshell tree depth. However, the docshell tree is
8606 // usually pretty shallow.
8607
8608 if (RefPtr<Document> doc = aWindow->GetDoc()) {
8609 doc->FlushPendingNotifications(FlushType::Layout);
8610 }
8611
8612 if (nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell()) {
8613 int32_t i = 0, i_end;
8614 docShell->GetInProcessChildCount(&i_end);
8615 for (; i < i_end; ++i) {
8616 nsCOMPtr<nsIDocShellTreeItem> item;
8617 if (docShell->GetInProcessChildAt(i, getter_AddRefs(item)) == NS_OK &&
8618 item) {
8619 if (nsCOMPtr<nsPIDOMWindowOuter> win = item->GetWindow()) {
8620 FlushLayoutForTree(win);
8621 }
8622 }
8623 }
8624 }
8625}
8626
8627void nsContentUtils::RemoveNewlines(nsAString& aString) { aString.StripCRLF(); }
8628
8629void nsContentUtils::PlatformToDOMLineBreaks(nsAString& aString) {
8630 if (!PlatformToDOMLineBreaks(aString, fallible)) {
8631 aString.AllocFailed(aString.Length());
8632 }
8633}
8634
8635bool nsContentUtils::PlatformToDOMLineBreaks(nsAString& aString,
8636 const fallible_t& aFallible) {
8637 if (aString.FindChar(char16_t('\r')) != -1) {
8638 // Windows linebreaks: Map CRLF to LF:
8639 if (!aString.ReplaceSubstring(u"\r\n", u"\n", aFallible)) {
8640 return false;
8641 }
8642
8643 // Mac linebreaks: Map any remaining CR to LF:
8644 if (!aString.ReplaceSubstring(u"\r", u"\n", aFallible)) {
8645 return false;
8646 }
8647 }
8648
8649 return true;
8650}
8651
8652already_AddRefed<ContentList> nsContentUtils::GetElementsByClassName(
8653 nsINode* aRootNode, const nsAString& aClasses) {
8654 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", 8654
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRootNode" ") (" "Must have root node"
")"); do { MOZ_CrashSequence(__null, 8654); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8655
8656 return GetFuncStringContentList<CacheableFuncStringHTMLCollection>(
8657 aRootNode, MatchClassNames, DestroyClassNameArray, AllocClassMatchingInfo,
8658 aClasses);
8659}
8660
8661PresShell* nsContentUtils::FindPresShellForDocument(const Document* aDocument) {
8662 const Document* doc = aDocument;
8663 Document* displayDoc = doc->GetDisplayDocument();
8664 if (displayDoc) {
8665 doc = displayDoc;
8666 }
8667
8668 PresShell* presShell = doc->GetPresShell();
8669 if (presShell) {
8670 return presShell;
8671 }
8672
8673 nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = doc->GetDocShell();
8674 while (docShellTreeItem) {
8675 // We may be in a display:none subdocument, or we may not have a presshell
8676 // created yet.
8677 // Walk the docshell tree to find the nearest container that has a
8678 // presshell, and return that.
8679 nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(docShellTreeItem);
8680 if (PresShell* presShell = docShell->GetPresShell()) {
8681 return presShell;
8682 }
8683 nsCOMPtr<nsIDocShellTreeItem> parent;
8684 docShellTreeItem->GetInProcessParent(getter_AddRefs(parent));
8685 docShellTreeItem = parent;
8686 }
8687
8688 return nullptr;
8689}
8690
8691/* static */
8692nsPresContext* nsContentUtils::FindPresContextForDocument(
8693 const Document* aDocument) {
8694 if (PresShell* presShell = FindPresShellForDocument(aDocument)) {
8695 return presShell->GetPresContext();
8696 }
8697 return nullptr;
8698}
8699
8700nsIWidget* nsContentUtils::WidgetForDocument(const Document* aDocument) {
8701 PresShell* presShell = FindPresShellForDocument(aDocument);
8702 return presShell ? presShell->GetNearestWidget() : nullptr;
8703}
8704
8705nsIWidget* nsContentUtils::WidgetForContent(const nsIContent* aContent) {
8706 nsIFrame* frame = aContent->GetPrimaryFrame();
8707 if (!frame) {
8708 return nullptr;
8709 }
8710 return frame->GetNearestWidget();
8711}
8712
8713WindowRenderer* nsContentUtils::WindowRendererForContent(
8714 const nsIContent* aContent) {
8715 nsIWidget* widget = nsContentUtils::WidgetForContent(aContent);
8716 if (widget) {
8717 return widget->GetWindowRenderer();
8718 }
8719
8720 return nullptr;
8721}
8722
8723WindowRenderer* nsContentUtils::WindowRendererForDocument(
8724 const Document* aDoc) {
8725 if (nsIWidget* widget = nsContentUtils::WidgetForDocument(aDoc)) {
8726 return widget->GetWindowRenderer();
8727 }
8728 return nullptr;
8729}
8730
8731bool nsContentUtils::AllowXULXBLForPrincipal(nsIPrincipal* aPrincipal) {
8732 if (!aPrincipal) {
8733 return false;
8734 }
8735
8736 if (aPrincipal->IsSystemPrincipal()) {
8737 return true;
8738 }
8739
8740 return xpc::IsInAutomation() && IsSitePermAllow(aPrincipal, "allowXULXBL"_ns);
8741}
8742
8743bool nsContentUtils::IsPDFJSEnabled() { return !StaticPrefs::pdfjs_disabled(); }
8744
8745bool nsContentUtils::IsPDFJS(nsIPrincipal* aPrincipal) {
8746 if (!aPrincipal || !aPrincipal->SchemeIs("resource")) {
8747 return false;
8748 }
8749 nsAutoCString originNoSuffix;
8750 nsresult rv = aPrincipal->GetOriginNoSuffix(originNoSuffix);
8751 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"
, 8751); return false; } } while (false)
;
8752 return originNoSuffix.Equals("resource://pdf.js"_ns);
8753}
8754
8755bool nsContentUtils::IsSystemOrPDFJS(JSContext* aCx, JSObject*) {
8756 nsIPrincipal* principal = SubjectPrincipal(aCx);
8757 return principal && (principal->IsSystemPrincipal() || IsPDFJS(principal));
8758}
8759
8760bool nsContentUtils::IsSecureContextOrWebExtension(JSContext* aCx,
8761 JSObject* aGlobal) {
8762 nsIPrincipal* principal = SubjectPrincipal(aCx);
8763 return mozilla::dom::IsSecureContextOrObjectIsFromSecureContext(aCx,
8764 aGlobal) ||
8765 (principal && principal->GetIsAddonOrExpandedAddonPrincipal());
8766}
8767
8768already_AddRefed<nsIDocumentLoaderFactory>
8769nsContentUtils::FindInternalDocumentViewer(const nsACString& aType,
8770 DocumentViewerType* aLoaderType) {
8771 if (aLoaderType) {
8772 *aLoaderType = TYPE_UNSUPPORTED;
8773 }
8774
8775 // one helper factory, please
8776 nsCOMPtr<nsICategoryManager> catMan(
8777 do_GetService(NS_CATEGORYMANAGER_CONTRACTID"@mozilla.org/categorymanager;1"));
8778 if (!catMan) return nullptr;
8779
8780 nsCOMPtr<nsIDocumentLoaderFactory> docFactory;
8781
8782 nsCString contractID;
8783 nsresult rv =
8784 catMan->GetCategoryEntry("Gecko-Content-Viewers", aType, contractID);
8785 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
8786 docFactory = do_GetService(contractID.get());
8787 if (docFactory && aLoaderType) {
8788 if (contractID.EqualsLiteral(CONTENT_DLF_CONTRACTID"@mozilla.org/content/document-loader-factory;1"))
8789 *aLoaderType = TYPE_CONTENT;
8790 else
8791 *aLoaderType = TYPE_UNKNOWN;
8792 }
8793 return docFactory.forget();
8794 }
8795
8796 // If the type wasn't registered in `Gecko-Content-Viewers`, check if it's
8797 // another type which we may dynamically support, such as `text/*` types or
8798 // video document types. These types are all backed by the nsContentDLF.
8799 if (IsPlainTextType(aType) ||
8800 DecoderTraits::IsSupportedInVideoDocument(aType)) {
8801 docFactory = do_GetService(CONTENT_DLF_CONTRACTID"@mozilla.org/content/document-loader-factory;1");
8802 if (docFactory && aLoaderType) {
8803 *aLoaderType = TYPE_CONTENT;
8804 }
8805 return docFactory.forget();
8806 }
8807
8808 return nullptr;
8809}
8810
8811static void ReportPatternCompileFailure(nsAString& aPattern,
8812 const JS::RegExpFlags& aFlags,
8813 const Document* aDocument,
8814 JS::MutableHandle<JS::Value> error,
8815 JSContext* cx) {
8816 AutoTArray<nsString, 3> strings;
8817
8818 strings.AppendElement(aPattern);
8819
8820 std::stringstream flag_ss;
8821 flag_ss << aFlags;
8822 nsString* flagstr = strings.AppendElement();
8823 AppendUTF8toUTF16(flag_ss.str(), *flagstr);
8824
8825 JS::AutoSaveExceptionState savedExc(cx);
8826 JS::Rooted<JSObject*> exnObj(cx, &error.toObject());
8827 JS::Rooted<JS::Value> messageVal(cx);
8828 if (!JS_GetProperty(cx, exnObj, "message", &messageVal)) {
8829 return;
8830 }
8831 JS::Rooted<JSString*> messageStr(cx, messageVal.toString());
8832 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"
, 8832); AnnotateMozCrashReason("MOZ_ASSERT" "(" "messageStr"
")"); do { MOZ_CrashSequence(__null, 8832); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8833 if (!AssignJSString(cx, *strings.AppendElement(), messageStr)) {
8834 return;
8835 }
8836
8837 nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, "DOM"_ns,
8838 aDocument, PropertiesFile::DOM_PROPERTIES,
8839 "PatternAttributeCompileFailurev2", strings);
8840 savedExc.drop();
8841}
8842
8843// static
8844Maybe<bool> nsContentUtils::IsPatternMatching(const nsAString& aValue,
8845 nsString&& aPattern,
8846 const Document* aDocument,
8847 bool aHasMultiple,
8848 JS::RegExpFlags aFlags) {
8849 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"
, 8849); MOZ_PretendNoReturn(); } } while (0)
;
8850
8851 // The fact that we're using a JS regexp under the hood should not be visible
8852 // to things like window onerror handlers, so we don't initialize our JSAPI
8853 // with the document's window (which may not exist anyway).
8854 AutoJSAPI jsapi;
8855 jsapi.Init();
8856 JSContext* cx = jsapi.cx();
8857 AutoDisableJSInterruptCallback disabler(cx);
8858
8859 // We can use the junk scope here, because we're just using it for regexp
8860 // evaluation, not actual script execution, and we disable statics so that the
8861 // evaluation does not interact with the execution global.
8862 JSAutoRealm ar(cx, xpc::PrivilegedJunkScope());
8863
8864 // Check if the pattern by itself is valid first, and not that it only becomes
8865 // valid once we add ^(?: and )$.
8866 JS::Rooted<JS::Value> error(cx);
8867 if (!JS::CheckRegExpSyntax(cx, aPattern.BeginReading(), aPattern.Length(),
8868 aFlags, &error)) {
8869 return Nothing();
8870 }
8871
8872 if (!error.isUndefined()) {
8873 ReportPatternCompileFailure(aPattern, aFlags, aDocument, &error, cx);
8874 return Some(true);
8875 }
8876
8877 // The pattern has to match the entire value.
8878 aPattern.InsertLiteral(u"^(?:", 0);
8879 aPattern.AppendLiteral(")$");
8880
8881 JS::Rooted<JSObject*> re(
8882 cx, JS::NewUCRegExpObject(cx, aPattern.BeginReading(), aPattern.Length(),
8883 aFlags));
8884 if (!re) {
8885 return Nothing();
8886 }
8887
8888 JS::Rooted<JS::Value> rval(cx, JS::NullValue());
8889 if (!aHasMultiple) {
8890 size_t idx = 0;
8891 if (!JS::ExecuteRegExpNoStatics(cx, re, aValue.BeginReading(),
8892 aValue.Length(), &idx, true, &rval)) {
8893 return Nothing();
8894 }
8895 return Some(!rval.isNull());
8896 }
8897
8898 HTMLSplitOnSpacesTokenizer tokenizer(aValue, ',');
8899 while (tokenizer.hasMoreTokens()) {
8900 const nsAString& value = tokenizer.nextToken();
8901 size_t idx = 0;
8902 if (!JS::ExecuteRegExpNoStatics(cx, re, value.BeginReading(),
8903 value.Length(), &idx, true, &rval)) {
8904 return Nothing();
8905 }
8906 if (rval.isNull()) {
8907 return Some(false);
8908 }
8909 }
8910 return Some(true);
8911}
8912
8913// static
8914nsresult nsContentUtils::URIInheritsSecurityContext(nsIURI* aURI,
8915 bool* aResult) {
8916 // Note: about:blank URIs do NOT inherit the security context from the
8917 // current document, which is what this function tests for...
8918 return NS_URIChainHasFlags(
8919 aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, aResult);
8920}
8921
8922// static
8923bool nsContentUtils::ChannelShouldInheritPrincipal(
8924 nsIPrincipal* aLoadingPrincipal, nsIURI* aURI, bool aInheritForAboutBlank,
8925 bool aForceInherit) {
8926 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"
, 8927); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Can not check inheritance without a principal" ")"); do
{ MOZ_CrashSequence(__null, 8927); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
8927 "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"
, 8927); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Can not check inheritance without a principal" ")"); do
{ MOZ_CrashSequence(__null, 8927); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
8928
8929 // Only tell the channel to inherit if it can't provide its own security
8930 // context.
8931 //
8932 // XXX: If this is ever changed, check all callers for what owners
8933 // they're passing in. In particular, see the code and
8934 // comments in nsDocShell::LoadURI where we fall back on
8935 // inheriting the owner if called from chrome. That would be
8936 // very wrong if this code changed anything but channels that
8937 // can't provide their own security context!
8938 //
8939 // If aForceInherit is true, we will inherit, even for a channel that
8940 // can provide its own security context. This is used for srcdoc loads.
8941 bool inherit = aForceInherit;
8942 if (!inherit) {
8943 bool uriInherits;
8944 // We expect URIInheritsSecurityContext to return success for an
8945 // about:blank URI, so don't call NS_IsAboutBlank() if this call fails.
8946 // This condition needs to match the one in nsDocShell::InternalLoad where
8947 // we're checking for things that will use the owner.
8948 inherit =
8949 (NS_SUCCEEDED(URIInheritsSecurityContext(aURI, &uriInherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(URIInheritsSecurityContext
(aURI, &uriInherits))), 1)))
&&
8950 (uriInherits || (aInheritForAboutBlank &&
8951 NS_IsAboutBlankAllowQueryAndFragment(aURI)))) ||
8952 //
8953 // file: uri special-casing
8954 //
8955 // If this is a file: load opened from another file: then it may need
8956 // to inherit the owner from the referrer so they can script each other.
8957 // If we don't set the owner explicitly then each file: gets an owner
8958 // based on its own codebase later.
8959 //
8960 (URIIsLocalFile(aURI) &&
8961 NS_SUCCEEDED(aLoadingPrincipal->CheckMayLoad(aURI, false))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aLoadingPrincipal
->CheckMayLoad(aURI, false))), 1)))
&&
8962 // One more check here. CheckMayLoad will always return true for the
8963 // system principal, but we do NOT want to inherit in that case.
8964 !aLoadingPrincipal->IsSystemPrincipal());
8965 }
8966 return inherit;
8967}
8968
8969/* static */
8970bool nsContentUtils::IsCutCopyAllowed(Document* aDocument,
8971 nsIPrincipal& aSubjectPrincipal) {
8972 if (StaticPrefs::dom_allow_cut_copy() && aDocument &&
8973 aDocument->HasValidTransientUserGestureActivation()) {
8974 return true;
8975 }
8976
8977 return PrincipalHasPermission(aSubjectPrincipal, nsGkAtoms::clipboardWrite);
8978}
8979
8980/* static */
8981bool nsContentUtils::HaveEqualPrincipals(Document* aDoc1, Document* aDoc2) {
8982 if (!aDoc1 || !aDoc2) {
8983 return false;
8984 }
8985 bool principalsEqual = false;
8986 aDoc1->NodePrincipal()->Equals(aDoc2->NodePrincipal(), &principalsEqual);
8987 return principalsEqual;
8988}
8989
8990/* static */
8991const Document* nsContentUtils::GetInProcessSubtreeRootDocument(
8992 const Document* aDoc) {
8993 if (!aDoc) {
8994 return nullptr;
8995 }
8996 const Document* doc = aDoc;
8997 while (doc->GetInProcessParentDocument()) {
8998 doc = doc->GetInProcessParentDocument();
8999 }
9000 return doc;
9001}
9002
9003// static
9004bool nsContentUtils::IsPointInSelection(
9005 const mozilla::dom::Selection& aSelection, const nsINode& aNode,
9006 const uint32_t aOffset, const bool aAllowCrossShadowBoundary) {
9007 const bool selectionIsCollapsed =
9008 !aAllowCrossShadowBoundary
9009 ? aSelection.IsCollapsed()
9010 : aSelection.AreNormalAndCrossShadowBoundaryRangesCollapsed();
9011 if (selectionIsCollapsed) {
9012 return false;
9013 }
9014
9015 const uint32_t rangeCount = aSelection.RangeCount();
9016 for (const uint32_t i : IntegerRange(rangeCount)) {
9017 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", 9017); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aSelection.RangeCount() == rangeCount" ")"
); do { MOZ_CrashSequence(__null, 9017); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9018 RefPtr<const dom::Range> range = aSelection.GetRangeAt(i);
9019 if (NS_WARN_IF(!range)NS_warn_if_impl(!range, "!range", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 9019)
) {
9020 // Don't bail yet, iterate through them all
9021 continue;
9022 }
9023
9024 // Done when we find a range that we are in
9025 if (range->IsPointInRange(aNode, aOffset, IgnoreErrors(),
9026 aAllowCrossShadowBoundary)) {
9027 return true;
9028 }
9029 }
9030
9031 return false;
9032}
9033
9034// static
9035void nsContentUtils::GetSelectionInTextControl(Selection* aSelection,
9036 Element* aRoot,
9037 uint32_t& aOutStartOffset,
9038 uint32_t& aOutEndOffset) {
9039 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", 9039); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aSelection && aRoot" ")"); do { MOZ_CrashSequence
(__null, 9039); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9040
9041 // We don't care which end of this selection is anchor and which is focus. In
9042 // fact, we explicitly want to know which is the _start_ and which is the
9043 // _end_, not anchor vs focus.
9044 const dom::Range* range = aSelection->GetAnchorFocusRange();
9045 if (!range) {
9046 // Nothing selected
9047 aOutStartOffset = aOutEndOffset = 0;
9048 return;
9049 }
9050
9051 // All the node pointers here are raw pointers for performance. We shouldn't
9052 // be doing anything in this function that invalidates the node tree.
9053 nsINode* startContainer = range->GetStartContainer();
9054 uint32_t startOffset = range->StartOffset();
9055 nsINode* endContainer = range->GetEndContainer();
9056 uint32_t endOffset = range->EndOffset();
9057
9058 // We have at most two children, consisting of an optional text node followed
9059 // by an optional <br>.
9060 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", 9060); MOZ_PretendNoReturn
(); } } while (0)
;
9061 nsIContent* firstChild = aRoot->GetFirstChild();
9062#ifdef DEBUG1
9063 nsCOMPtr<nsIContent> lastChild = aRoot->GetLastChild();
9064 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", 9066); MOZ_PretendNoReturn
(); } } while (0)
9065 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", 9066); MOZ_PretendNoReturn
(); } } while (0)
9066 "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", 9066); MOZ_PretendNoReturn
(); } } while (0)
;
9067 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", 9069); MOZ_PretendNoReturn
(); } } while (0)
9068 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", 9069); MOZ_PretendNoReturn
(); } } while (0)
9069 "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", 9069); MOZ_PretendNoReturn
(); } } while (0)
;
9070 // firstChild is either text or a <br> (hence an element).
9071 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"
, 9071); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstChild->IsText() || firstChild->IsElement()"
")"); do { MOZ_CrashSequence(__null, 9071); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
9072#endif
9073 if (!firstChild || firstChild->IsElement()) {
9074 // No text node, so everything is 0
9075 startOffset = endOffset = 0;
9076 } else {
9077 // First child is text. If the start/end is already in the text node,
9078 // or the start of the root node, no change needed. If it's in the root
9079 // node but not the start, or in the trailing <br>, we need to set the
9080 // offset to the end.
9081 if ((startContainer == aRoot && startOffset != 0) ||
9082 (startContainer != aRoot && startContainer != firstChild)) {
9083 startOffset = firstChild->Length();
9084 }
9085 if ((endContainer == aRoot && endOffset != 0) ||
9086 (endContainer != aRoot && endContainer != firstChild)) {
9087 endOffset = firstChild->Length();
9088 }
9089 }
9090
9091 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", 9091); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "startOffset <= endOffset" ")"); do { MOZ_CrashSequence
(__null, 9091); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9092 aOutStartOffset = startOffset;
9093 aOutEndOffset = endOffset;
9094}
9095
9096// static
9097HTMLEditor* nsContentUtils::GetHTMLEditor(nsPresContext* aPresContext) {
9098 if (!aPresContext) {
9099 return nullptr;
9100 }
9101 return GetHTMLEditor(aPresContext->GetDocShell());
9102}
9103
9104// static
9105HTMLEditor* nsContentUtils::GetHTMLEditor(nsDocShell* aDocShell) {
9106 bool isEditable;
9107 if (!aDocShell || NS_FAILED(aDocShell->GetEditable(&isEditable))((bool)(__builtin_expect(!!(NS_FAILED_impl(aDocShell->GetEditable
(&isEditable))), 0)))
||
9108 !isEditable) {
9109 return nullptr;
9110 }
9111 return aDocShell->GetHTMLEditor();
9112}
9113
9114// static
9115EditorBase* nsContentUtils::GetActiveEditor(nsPresContext* aPresContext) {
9116 if (!aPresContext) {
9117 return nullptr;
9118 }
9119
9120 return GetActiveEditor(aPresContext->Document()->GetWindow());
9121}
9122
9123// static
9124EditorBase* nsContentUtils::GetActiveEditor(nsPIDOMWindowOuter* aWindow) {
9125 if (!aWindow || !aWindow->GetExtantDoc()) {
9126 return nullptr;
9127 }
9128
9129 // If it's in designMode, nobody can have focus. Therefore, the HTMLEditor
9130 // handles all events. I.e., it's focused editor in this case.
9131 if (aWindow->GetExtantDoc()->IsInDesignMode()) {
9132 return GetHTMLEditor(nsDocShell::Cast(aWindow->GetDocShell()));
9133 }
9134
9135 // If focused element is associated with TextEditor, it must be <input>
9136 // element or <textarea> element. Let's return it even if it's in a
9137 // contenteditable element.
9138 nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
9139 if (Element* focusedElement = nsFocusManager::GetFocusedDescendant(
9140 aWindow, nsFocusManager::SearchRange::eOnlyCurrentWindow,
9141 getter_AddRefs(focusedWindow))) {
9142 if (TextEditor* textEditor = focusedElement->GetTextEditorInternal()) {
9143 return textEditor;
9144 }
9145 }
9146
9147 // Otherwise, HTMLEditor may handle inputs even non-editable element has
9148 // focus or nobody has focus.
9149 return GetHTMLEditor(nsDocShell::Cast(aWindow->GetDocShell()));
9150}
9151
9152// static
9153TextEditor* nsContentUtils::GetExtantTextEditorFromAnonymousNode(
9154 const nsIContent* aAnonymousContent) {
9155 if (!aAnonymousContent) {
9156 return nullptr;
9157 }
9158 nsIContent* parent = aAnonymousContent->FindFirstNonChromeOnlyAccessContent();
9159 if (!parent || parent == aAnonymousContent) {
9160 return nullptr;
9161 }
9162 if (const HTMLInputElement* const inputElement =
9163 HTMLInputElement::FromNodeOrNull(parent)) {
9164 return inputElement->GetExtantTextEditor();
9165 }
9166 if (const HTMLTextAreaElement* const textareaElement =
9167 HTMLTextAreaElement::FromNodeOrNull(parent)) {
9168 return textareaElement->GetExtantTextEditor();
9169 }
9170 return nullptr;
9171}
9172
9173// static
9174bool nsContentUtils::IsNodeInEditableRegion(nsINode* aNode) {
9175 while (aNode) {
9176 if (aNode->IsEditable()) {
9177 return true;
9178 }
9179 aNode = aNode->GetParent();
9180 }
9181 return false;
9182}
9183
9184// static
9185bool nsContentUtils::IsForbiddenRequestHeader(const nsACString& aHeader,
9186 const nsACString& aValue) {
9187 if (IsForbiddenSystemRequestHeader(aHeader)) {
9188 return true;
9189 }
9190
9191 if ((nsContentUtils::IsOverrideMethodHeader(aHeader) &&
9192 nsContentUtils::ContainsForbiddenMethod(aValue))) {
9193 return true;
9194 }
9195
9196 if (StringBeginsWith(aHeader, "proxy-"_ns,
9197 nsCaseInsensitiveCStringComparator) ||
9198 StringBeginsWith(aHeader, "sec-"_ns,
9199 nsCaseInsensitiveCStringComparator)) {
9200 return true;
9201 }
9202
9203 return false;
9204}
9205
9206// static
9207bool nsContentUtils::IsForbiddenSystemRequestHeader(const nsACString& aHeader) {
9208 static const char* kInvalidHeaders[] = {"accept-charset",
9209 "accept-encoding",
9210 "access-control-request-headers",
9211 "access-control-request-method",
9212 "connection",
9213 "content-length",
9214 "cookie",
9215 "cookie2",
9216 "date",
9217 "dnt",
9218 "expect",
9219 "host",
9220 "keep-alive",
9221 "origin",
9222 "referer",
9223 "set-cookie",
9224 "te",
9225 "trailer",
9226 "transfer-encoding",
9227 "upgrade",
9228 "via"};
9229 for (auto& kInvalidHeader : kInvalidHeaders) {
9230 if (aHeader.LowerCaseEqualsASCII(kInvalidHeader)) {
9231 return true;
9232 }
9233 }
9234 return false;
9235}
9236
9237// static
9238bool nsContentUtils::IsForbiddenResponseHeader(const nsACString& aHeader) {
9239 return (aHeader.LowerCaseEqualsASCII("set-cookie") ||
9240 aHeader.LowerCaseEqualsASCII("set-cookie2"));
9241}
9242
9243// static
9244bool nsContentUtils::IsOverrideMethodHeader(const nsACString& headerName) {
9245 return headerName.EqualsIgnoreCase("x-http-method-override") ||
9246 headerName.EqualsIgnoreCase("x-http-method") ||
9247 headerName.EqualsIgnoreCase("x-method-override");
9248}
9249
9250// static
9251bool nsContentUtils::ContainsForbiddenMethod(const nsACString& headerValue) {
9252 bool hasInsecureMethod = false;
9253 nsCCharSeparatedTokenizer tokenizer(headerValue, ',');
9254
9255 while (tokenizer.hasMoreTokens()) {
9256 const nsDependentCSubstring& value = tokenizer.nextToken();
9257
9258 if (value.EqualsIgnoreCase("connect") || value.EqualsIgnoreCase("trace") ||
9259 value.EqualsIgnoreCase("track")) {
9260 hasInsecureMethod = true;
9261 break;
9262 }
9263 }
9264
9265 return hasInsecureMethod;
9266}
9267
9268Maybe<nsContentUtils::ParsedRange> nsContentUtils::ParseSingleRangeRequest(
9269 const nsACString& aHeaderValue, bool aAllowWhitespace) {
9270 // See https://fetch.spec.whatwg.org/#simple-range-header-value
9271 mozilla::Tokenizer p(aHeaderValue);
9272 Maybe<uint64_t> rangeStart;
9273 Maybe<uint64_t> rangeEnd;
9274
9275 // Step 2 and 3
9276 if (!p.CheckWord("bytes")) {
9277 return Nothing();
9278 }
9279
9280 // Step 4
9281 if (aAllowWhitespace) {
9282 p.SkipWhites();
9283 }
9284
9285 // Step 5 and 6
9286 if (!p.CheckChar('=')) {
9287 return Nothing();
9288 }
9289
9290 // Step 7
9291 if (aAllowWhitespace) {
9292 p.SkipWhites();
9293 }
9294
9295 // Step 8 and 9
9296 uint64_t res;
9297 if (p.ReadInteger(&res)) {
9298 rangeStart = Some(res);
9299 }
9300
9301 // Step 10
9302 if (aAllowWhitespace) {
9303 p.SkipWhites();
9304 }
9305
9306 // Step 11
9307 if (!p.CheckChar('-')) {
9308 return Nothing();
9309 }
9310
9311 // Step 13
9312 if (aAllowWhitespace) {
9313 p.SkipWhites();
9314 }
9315
9316 // Step 14 and 15
9317 if (p.ReadInteger(&res)) {
9318 rangeEnd = Some(res);
9319 }
9320
9321 // Step 16
9322 if (!p.CheckEOF()) {
9323 return Nothing();
9324 }
9325
9326 // Step 17
9327 if (!rangeStart && !rangeEnd) {
9328 return Nothing();
9329 }
9330
9331 // Step 18
9332 if (rangeStart && rangeEnd && *rangeStart > *rangeEnd) {
9333 return Nothing();
9334 }
9335
9336 return Some(ParsedRange(rangeStart, rangeEnd));
9337}
9338
9339// static
9340bool nsContentUtils::IsCorsUnsafeRequestHeaderValue(
9341 const nsACString& aHeaderValue) {
9342 const char* cur = aHeaderValue.BeginReading();
9343 const char* end = aHeaderValue.EndReading();
9344
9345 while (cur != end) {
9346 // Implementation of
9347 // https://fetch.spec.whatwg.org/#cors-unsafe-request-header-byte Is less
9348 // than a space but not a horizontal tab
9349 if ((*cur < ' ' && *cur != '\t') || *cur == '"' || *cur == '(' ||
9350 *cur == ')' || *cur == ':' || *cur == '<' || *cur == '>' ||
9351 *cur == '?' || *cur == '@' || *cur == '[' || *cur == '\\' ||
9352 *cur == ']' || *cur == '{' || *cur == '}' ||
9353 *cur == 0x7F) { // 0x75 is DEL
9354 return true;
9355 }
9356 cur++;
9357 }
9358 return false;
9359}
9360
9361// static
9362bool nsContentUtils::IsAllowedNonCorsAccept(const nsACString& aHeaderValue) {
9363 if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) {
9364 return false;
9365 }
9366 return true;
9367}
9368
9369// static
9370bool nsContentUtils::IsAllowedNonCorsContentType(
9371 const nsACString& aHeaderValue) {
9372 nsAutoCString contentType;
9373 nsAutoCString unused;
9374
9375 if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) {
9376 return false;
9377 }
9378
9379 nsresult rv = NS_ParseRequestContentType(aHeaderValue, contentType, unused);
9380 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9381 return false;
9382 }
9383
9384 return contentType.LowerCaseEqualsLiteral("text/plain") ||
9385 contentType.LowerCaseEqualsLiteral(
9386 "application/x-www-form-urlencoded") ||
9387 contentType.LowerCaseEqualsLiteral("multipart/form-data");
9388}
9389
9390// static
9391bool nsContentUtils::IsAllowedNonCorsLanguage(const nsACString& aHeaderValue) {
9392 const char* cur = aHeaderValue.BeginReading();
9393 const char* end = aHeaderValue.EndReading();
9394
9395 while (cur != end) {
9396 if ((*cur >= '0' && *cur <= '9') || (*cur >= 'A' && *cur <= 'Z') ||
9397 (*cur >= 'a' && *cur <= 'z') || *cur == ' ' || *cur == '*' ||
9398 *cur == ',' || *cur == '-' || *cur == '.' || *cur == ';' ||
9399 *cur == '=') {
9400 cur++;
9401 continue;
9402 }
9403 return false;
9404 }
9405 return true;
9406}
9407
9408bool nsContentUtils::IsAllowedNonCorsRange(const nsACString& aHeaderValue) {
9409 Maybe<ParsedRange> parsedRange = ParseSingleRangeRequest(aHeaderValue, false);
9410 if (!parsedRange) {
9411 return false;
9412 }
9413
9414 if (!parsedRange->Start()) {
9415 return false;
9416 }
9417
9418 return true;
9419}
9420
9421// static
9422bool nsContentUtils::IsCORSSafelistedRequestHeader(const nsACString& aName,
9423 const nsACString& aValue) {
9424 // see https://fetch.spec.whatwg.org/#cors-safelisted-request-header
9425 if (aValue.Length() > 128) {
9426 return false;
9427 }
9428 return (aName.LowerCaseEqualsLiteral("accept") &&
9429 nsContentUtils::IsAllowedNonCorsAccept(aValue)) ||
9430 (aName.LowerCaseEqualsLiteral("accept-language") &&
9431 nsContentUtils::IsAllowedNonCorsLanguage(aValue)) ||
9432 (aName.LowerCaseEqualsLiteral("content-language") &&
9433 nsContentUtils::IsAllowedNonCorsLanguage(aValue)) ||
9434 (aName.LowerCaseEqualsLiteral("content-type") &&
9435 nsContentUtils::IsAllowedNonCorsContentType(aValue)) ||
9436 (aName.LowerCaseEqualsLiteral("range") &&
9437 nsContentUtils::IsAllowedNonCorsRange(aValue)) ||
9438 (StaticPrefs::network_http_idempotencyKey_enabled() &&
9439 aName.LowerCaseEqualsLiteral("idempotency-key"));
9440}
9441
9442mozilla::LogModule* nsContentUtils::ResistFingerprintingLog() {
9443 return gResistFingerprintingLog;
9444}
9445mozilla::LogModule* nsContentUtils::DOMDumpLog() { return sDOMDumpLog; }
9446
9447bool nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep,
9448 nsAString& aResult,
9449 const fallible_t& aFallible) {
9450 aResult.Truncate();
9451 return AppendNodeTextContent(aNode, aDeep, aResult, aFallible);
9452}
9453
9454bool nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep,
9455 nsACString& aResult,
9456 const fallible_t& aFallible) {
9457 aResult.Truncate();
9458 return AppendNodeTextContent(aNode, aDeep, aResult, aFallible);
9459}
9460
9461void nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep,
9462 nsAString& aResult) {
9463 if (!GetNodeTextContent(aNode, aDeep, aResult, fallible)) {
9464 NS_ABORT_OOM(0); // Unfortunately we don't know the allocation size
9465 }
9466}
9467
9468void nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep,
9469 nsACString& aResult) {
9470 if (!GetNodeTextContent(aNode, aDeep, aResult, fallible)) {
9471 NS_ABORT_OOM(0); // Unfortunately we don't know the allocation size
9472 }
9473}
9474
9475void nsContentUtils::DestroyMatchString(void* aData) {
9476 if (aData) {
9477 nsString* matchString = static_cast<nsString*>(aData);
9478 delete matchString;
9479 }
9480}
9481
9482// Table ordered from most to least likely JS MIME types.
9483static constexpr std::string_view kJavascriptMIMETypes[] = {
9484 "text/javascript",
9485 "text/ecmascript",
9486 "application/javascript",
9487 "application/ecmascript",
9488 "application/x-javascript",
9489 "application/x-ecmascript",
9490 "text/javascript1.0",
9491 "text/javascript1.1",
9492 "text/javascript1.2",
9493 "text/javascript1.3",
9494 "text/javascript1.4",
9495 "text/javascript1.5",
9496 "text/jscript",
9497 "text/livescript",
9498 "text/x-ecmascript",
9499 "text/x-javascript"};
9500
9501bool nsContentUtils::IsJavascriptMIMEType(const nsAString& aMIMEType) {
9502 for (std::string_view type : kJavascriptMIMETypes) {
9503 if (aMIMEType.LowerCaseEqualsASCII(type.data(), type.length())) {
9504 return true;
9505 }
9506 }
9507 return false;
9508}
9509
9510bool nsContentUtils::IsJavascriptMIMEType(const nsACString& aMIMEType) {
9511 for (std::string_view type : kJavascriptMIMETypes) {
9512 if (aMIMEType.LowerCaseEqualsASCII(type.data(), type.length())) {
9513 return true;
9514 }
9515 }
9516 return false;
9517}
9518
9519// https://mimesniff.spec.whatwg.org/#json-mime-type
9520bool nsContentUtils::IsJsonMimeType(const nsAString& aMimeType) {
9521 // Table ordered from most to least likely JSON MIME types.
9522 static constexpr std::string_view jsonTypes[] = {"application/json",
9523 "text/json"};
9524
9525 for (std::string_view type : jsonTypes) {
9526 if (aMimeType.LowerCaseEqualsASCII(type.data(), type.length())) {
9527 return true;
9528 }
9529 }
9530
9531 // Below checks if the 'subtype' ends in "+json".
9532 RefPtr<MimeType> parsed = MimeType::Parse(aMimeType);
9533 if (!parsed) {
9534 return false;
9535 }
9536
9537 nsAutoString subtype;
9538 parsed->GetSubtype(subtype);
9539 return StringEndsWith(subtype, u"+json"_ns);
9540}
9541
9542// https://html.spec.whatwg.org/#fetch-a-single-module-script, 13.7.3
9543bool nsContentUtils::HasCssMimeTypeEssence(const nsAString& aMimeType) {
9544 nsString contentType, contentCharset;
9545 if (MimeType::Parse(aMimeType, contentType, contentCharset)) {
9546 return contentType.LowerCaseEqualsLiteral("text/css");
9547 }
9548 return false;
9549}
9550
9551// https://html.spec.whatwg.org/#fetch-a-single-module-script, 13.6
9552bool nsContentUtils::HasWasmMimeTypeEssence(const nsAString& aMimeType) {
9553 nsString contentType, contentCharset;
9554 if (MimeType::Parse(aMimeType, contentType, contentCharset)) {
9555 return contentType.LowerCaseEqualsLiteral("application/wasm");
9556 }
9557 return false;
9558}
9559
9560bool nsContentUtils::PrefetchPreloadEnabled(nsIDocShell* aDocShell) {
9561 //
9562 // SECURITY CHECK: disable prefetching and preloading from mailnews!
9563 //
9564 // walk up the docshell tree to see if any containing
9565 // docshell are of type MAIL.
9566 //
9567
9568 if (!aDocShell) {
9569 return false;
9570 }
9571
9572 nsCOMPtr<nsIDocShell> docshell = aDocShell;
9573 nsCOMPtr<nsIDocShellTreeItem> parentItem;
9574
9575 do {
9576 auto appType = docshell->GetAppType();
9577 if (appType == nsIDocShell::APP_TYPE_MAIL) {
9578 return false; // do not prefetch, preload, preconnect from mailnews
9579 }
9580
9581 docshell->GetInProcessParent(getter_AddRefs(parentItem));
9582 if (parentItem) {
9583 docshell = do_QueryInterface(parentItem);
9584 if (!docshell) {
9585 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",
9585); MOZ_PretendNoReturn(); } while (0)
;
9586 return false;
9587 }
9588 }
9589 } while (parentItem);
9590
9591 return true;
9592}
9593
9594uint64_t nsContentUtils::GetInnerWindowID(nsIRequest* aRequest) {
9595 // can't do anything if there's no nsIRequest!
9596 if (!aRequest) {
9597 return 0;
9598 }
9599
9600 if (nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest)) {
9601 nsCOMPtr loadInfo = channel->LoadInfo();
9602 if (auto id = loadInfo->GetInnerWindowID()) {
9603 return id;
9604 }
9605 if (auto id = loadInfo->GetTriggeringWindowId()) {
9606 return id;
9607 }
9608 }
9609
9610 nsCOMPtr<nsILoadGroup> loadGroup;
9611 nsresult rv = aRequest->GetLoadGroup(getter_AddRefs(loadGroup));
9612
9613 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadGroup) {
9614 return 0;
9615 }
9616
9617 return GetInnerWindowID(loadGroup);
9618}
9619
9620uint64_t nsContentUtils::GetInnerWindowID(nsILoadGroup* aLoadGroup) {
9621 if (!aLoadGroup) {
9622 return 0;
9623 }
9624
9625 nsCOMPtr<nsIInterfaceRequestor> callbacks;
9626 nsresult rv = aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
9627 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !callbacks) {
9628 return 0;
9629 }
9630
9631 nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
9632 if (!loadContext) {
9633 return 0;
9634 }
9635
9636 nsCOMPtr<mozIDOMWindowProxy> window;
9637 rv = loadContext->GetAssociatedWindow(getter_AddRefs(window));
9638 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !window) {
9639 return 0;
9640 }
9641
9642 auto* pwindow = nsPIDOMWindowOuter::From(window);
9643 if (!pwindow) {
9644 return 0;
9645 }
9646
9647 nsPIDOMWindowInner* inner = pwindow->GetCurrentInnerWindow();
9648 return inner ? inner->WindowID() : 0;
9649}
9650
9651// static
9652void nsContentUtils::MaybeFixIPv6Host(nsACString& aHost) {
9653 if (aHost.FindChar(':') != -1) { // Escape IPv6 address
9654 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", 9654); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aHost.IsEmpty()" ")"); do { MOZ_CrashSequence
(__null, 9654); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9655 if (aHost.Length() >= 2 && aHost[0] != '[' &&
9656 aHost[aHost.Length() - 1] != ']') {
9657 aHost.Insert('[', 0);
9658 aHost.Append(']');
9659 }
9660 }
9661}
9662
9663nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI,
9664 nsACString& aHost) {
9665 aHost.Truncate();
9666 nsresult rv = aURI->GetHost(aHost);
9667 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { // Some URIs do not have a host
9668 return rv;
9669 }
9670
9671 MaybeFixIPv6Host(aHost);
9672
9673 return NS_OK;
9674}
9675
9676nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI,
9677 nsAString& aHost) {
9678 nsAutoCString hostname;
9679 nsresult rv = GetHostOrIPv6WithBrackets(aURI, hostname);
9680 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9681 return rv;
9682 }
9683 CopyUTF8toUTF16(hostname, aHost);
9684 return NS_OK;
9685}
9686
9687nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIPrincipal* aPrincipal,
9688 nsACString& aHost) {
9689 nsresult rv = aPrincipal->GetAsciiHost(aHost);
9690 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { // Some URIs do not have a host
9691 return rv;
9692 }
9693
9694 MaybeFixIPv6Host(aHost);
9695 return NS_OK;
9696}
9697
9698nsresult nsContentUtils::GetAsciiHostOrIPv6WithBrackets(nsIURI* aURI,
9699 nsACString& aHost) {
9700 aHost.Truncate();
9701 nsresult rv = aURI->GetAsciiHost(aHost);
9702 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9703 return rv;
9704 }
9705
9706 MaybeFixIPv6Host(aHost);
9707 return NS_OK;
9708}
9709
9710CallState nsContentUtils::CallOnAllRemoteChildren(
9711 MessageBroadcaster* aManager,
9712 const std::function<CallState(BrowserParent*)>& aCallback) {
9713 uint32_t browserChildCount = aManager->ChildCount();
9714 for (uint32_t j = 0; j < browserChildCount; ++j) {
9715 RefPtr<MessageListenerManager> childMM = aManager->GetChildAt(j);
9716 if (!childMM) {
9717 continue;
9718 }
9719
9720 RefPtr<MessageBroadcaster> nonLeafMM = MessageBroadcaster::From(childMM);
9721 if (nonLeafMM) {
9722 if (CallOnAllRemoteChildren(nonLeafMM, aCallback) == CallState::Stop) {
9723 return CallState::Stop;
9724 }
9725 continue;
9726 }
9727
9728 mozilla::dom::ipc::MessageManagerCallback* cb = childMM->GetCallback();
9729 if (cb) {
9730 nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb);
9731 BrowserParent* remote = BrowserParent::GetFrom(fl);
9732 if (remote && aCallback) {
9733 if (aCallback(remote) == CallState::Stop) {
9734 return CallState::Stop;
9735 }
9736 }
9737 }
9738 }
9739
9740 return CallState::Continue;
9741}
9742
9743void nsContentUtils::CallOnAllRemoteChildren(
9744 nsPIDOMWindowOuter* aWindow,
9745 const std::function<CallState(BrowserParent*)>& aCallback) {
9746 nsGlobalWindowOuter* window = nsGlobalWindowOuter::Cast(aWindow);
9747 if (window->IsChromeWindow()) {
9748 RefPtr<MessageBroadcaster> windowMM = window->GetMessageManager();
9749 if (windowMM) {
9750 CallOnAllRemoteChildren(windowMM, aCallback);
9751 }
9752 }
9753}
9754
9755bool nsContentUtils::IPCTransferableDataItemHasKnownFlavor(
9756 const IPCTransferableDataItem& aItem) {
9757 // Unknown types are converted to kCustomTypesMime.
9758 if (aItem.flavor().EqualsASCII(kCustomTypesMime"application/x-moz-custom-clipdata")) {
9759 return true;
9760 }
9761
9762 for (const char* format : DataTransfer::kKnownFormats) {
9763 if (aItem.flavor().EqualsASCII(format)) {
9764 return true;
9765 }
9766 }
9767
9768 // Clipboard custom type. Only recognise "web foo/bar" as a known flavor
9769 // when the web custom format feature is enabled; otherwise DnD or other
9770 // callers must not be able to slip web custom flavors through this helper.
9771 const nsCString& flavor = aItem.flavor();
9772 if (StaticPrefs::dom_clipboard_customFormatSupport_enabled() &&
9773 StringBeginsWith(flavor, nsLiteralCString(kWebCustomFormatPrefix"web "))) {
9774 if (RefPtr<CMimeType> parsedType = CMimeType::Parse(Substring(
9775 flavor, strlen(kWebCustomFormatPrefix"web "), flavor.Length()))) {
9776 return true;
9777 }
9778 }
9779
9780 return false;
9781}
9782
9783nsresult nsContentUtils::IPCTransferableDataToTransferable(
9784 const IPCTransferableData& aTransferableData, bool aAddDataFlavor,
9785 nsITransferable* aTransferable, const bool aFilterUnknownFlavors) {
9786 nsresult rv;
9787 const nsTArray<IPCTransferableDataItem>& items = aTransferableData.items();
9788 for (const auto& item : items) {
9789 if (aFilterUnknownFlavors) {
9790 if (item.flavor().EqualsLiteral(kFilePromiseDirectoryMime"application/x-moz-file-promise-dir")) {
9791 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9793)
9792 "Ignoring unknown flavor in "NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9793)
9793 "nsContentUtils::IPCTransferableDataToTransferable")NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9793)
;
9794 continue;
9795 }
9796
9797 if ((item.flavor().EqualsLiteral(kFilePromiseMime"application/x-moz-file-promise") ||
9798 item.flavor().EqualsLiteral(kFilePromiseURLMime"application/x-moz-file-promise-url") ||
9799 item.flavor().EqualsLiteral(kFilePromiseDestFilename"application/x-moz-file-promise-dest-filename"))
9800#ifdef XP_WIN
9801 && !StaticPrefs::clipboard_imageAsFile_enabled()
9802#endif
9803 ) {
9804 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9806)
9805 "Ignoring unknown flavor in "NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9806)
9806 "nsContentUtils::IPCTransferableDataToTransferable")NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9806)
;
9807 continue;
9808 }
9809
9810 if (!IPCTransferableDataItemHasKnownFlavor(item)) {
9811 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9813)
9812 "Ignoring unknown flavor in "NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9813)
9813 "nsContentUtils::IPCTransferableDataToTransferable")NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9813)
;
9814 continue;
9815 }
9816 }
9817
9818 if (aAddDataFlavor) {
9819 aTransferable->AddDataFlavor(item.flavor().get());
9820 }
9821
9822 nsCOMPtr<nsISupports> transferData;
9823 switch (item.data().type()) {
9824 case IPCTransferableDataType::TIPCTransferableDataString: {
9825 const auto& data = item.data().get_IPCTransferableDataString();
9826 nsCOMPtr<nsISupportsString> dataWrapper =
9827 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv);
9828 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"
, 9828); return rv; } } while (false)
;
9829 rv = dataWrapper->SetData(nsDependentSubstring(
9830 reinterpret_cast<const char16_t*>(data.data().Data()),
9831 data.data().Size() / sizeof(char16_t)));
9832 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"
, 9832); return rv; } } while (false)
;
9833 transferData = dataWrapper;
9834 break;
9835 }
9836 case IPCTransferableDataType::TIPCTransferableDataCString: {
9837 const auto& data = item.data().get_IPCTransferableDataCString();
9838 nsCOMPtr<nsISupportsCString> dataWrapper =
9839 do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID"@mozilla.org/supports-cstring;1", &rv);
9840 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"
, 9840); return rv; } } while (false)
;
9841 rv = dataWrapper->SetData(nsDependentCSubstring(
9842 reinterpret_cast<const char*>(data.data().Data()),
9843 data.data().Size()));
9844 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"
, 9844); return rv; } } while (false)
;
9845 transferData = dataWrapper;
9846 break;
9847 }
9848 case IPCTransferableDataType::TIPCTransferableDataInputStream: {
9849 const auto& data = item.data().get_IPCTransferableDataInputStream();
9850 nsCOMPtr<nsIInputStream> stream;
9851 rv = NS_NewByteInputStream(getter_AddRefs(stream),
9852 AsChars(data.data().AsSpan()),
9853 NS_ASSIGNMENT_COPY);
9854 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"
, 9854); return rv; } } while (false)
;
9855 transferData = stream.forget();
9856 break;
9857 }
9858 case IPCTransferableDataType::TIPCTransferableDataImageContainer: {
9859 const auto& data = item.data().get_IPCTransferableDataImageContainer();
9860 nsCOMPtr<imgIContainer> container = IPCImageToImage(data.image());
9861 if (!container) {
9862 return NS_ERROR_FAILURE;
9863 }
9864 transferData = container;
9865 break;
9866 }
9867 case IPCTransferableDataType::TIPCTransferableDataBlob: {
9868 const auto& data = item.data().get_IPCTransferableDataBlob();
9869 transferData = IPCBlobUtils::Deserialize(data.blob());
9870 break;
9871 }
9872 case IPCTransferableDataType::T__None:
9873 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", 9873
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
")"); do { MOZ_CrashSequence(__null, 9873); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9874 return NS_ERROR_FAILURE;
9875 }
9876
9877 rv = aTransferable->SetTransferData(item.flavor().get(), transferData);
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 }
9880 return NS_OK;
9881}
9882
9883nsresult nsContentUtils::IPCTransferableToTransferable(
9884 const IPCTransferable& aIPCTransferable, bool aAddDataFlavor,
9885 nsITransferable* aTransferable, const bool aFilterUnknownFlavors) {
9886 // Note that we need to set privacy status of transferable before adding any
9887 // data into it.
9888 aTransferable->SetIsPrivateData(aIPCTransferable.isPrivateData());
9889
9890 nsresult rv =
9891 IPCTransferableDataToTransferable(aIPCTransferable.data(), aAddDataFlavor,
9892 aTransferable, aFilterUnknownFlavors);
9893 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"
, 9893); return rv; } } while (false)
;
9894
9895 if (aIPCTransferable.cookieJarSettings().isSome()) {
9896 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
9897 net::CookieJarSettings::Deserialize(
9898 aIPCTransferable.cookieJarSettings().ref(),
9899 getter_AddRefs(cookieJarSettings));
9900 aTransferable->SetCookieJarSettings(cookieJarSettings);
9901 }
9902 aTransferable->SetReferrerInfo(aIPCTransferable.referrerInfo());
9903 aTransferable->SetDataPrincipal(aIPCTransferable.dataPrincipal());
9904 aTransferable->SetContentPolicyType(aIPCTransferable.contentPolicyType());
9905
9906 return NS_OK;
9907}
9908
9909nsresult nsContentUtils::IPCTransferableDataItemToVariant(
9910 const IPCTransferableDataItem& aItem, nsIWritableVariant* aVariant) {
9911 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"
, 9911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aVariant" ")"
); do { MOZ_CrashSequence(__null, 9911); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9912
9913 switch (aItem.data().type()) {
9914 case IPCTransferableDataType::TIPCTransferableDataString: {
9915 const auto& data = aItem.data().get_IPCTransferableDataString();
9916 return aVariant->SetAsAString(nsDependentSubstring(
9917 reinterpret_cast<const char16_t*>(data.data().Data()),
9918 data.data().Size() / sizeof(char16_t)));
9919 }
9920 case IPCTransferableDataType::TIPCTransferableDataCString: {
9921 const auto& data = aItem.data().get_IPCTransferableDataCString();
9922 return aVariant->SetAsACString(nsDependentCSubstring(
9923 reinterpret_cast<const char*>(data.data().Data()),
9924 data.data().Size()));
9925 }
9926 case IPCTransferableDataType::TIPCTransferableDataInputStream: {
9927 const auto& data = aItem.data().get_IPCTransferableDataInputStream();
9928 nsCOMPtr<nsIInputStream> stream;
9929 nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
9930 AsChars(data.data().AsSpan()),
9931 NS_ASSIGNMENT_COPY);
9932 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"
, 9932); return rv; } } while (false)
;
9933 return aVariant->SetAsISupports(stream);
9934 }
9935 case IPCTransferableDataType::TIPCTransferableDataImageContainer: {
9936 const auto& data = aItem.data().get_IPCTransferableDataImageContainer();
9937 nsCOMPtr<imgIContainer> container = IPCImageToImage(data.image());
9938 if (!container) {
9939 return NS_ERROR_FAILURE;
9940 }
9941 return aVariant->SetAsISupports(container);
9942 }
9943 case IPCTransferableDataType::TIPCTransferableDataBlob: {
9944 const auto& data = aItem.data().get_IPCTransferableDataBlob();
9945 RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(data.blob());
9946 return aVariant->SetAsISupports(blobImpl);
9947 }
9948 case IPCTransferableDataType::T__None:
9949 break;
9950 }
9951
9952 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", 9952
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
")"); do { MOZ_CrashSequence(__null, 9952); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9953 return NS_ERROR_UNEXPECTED;
9954}
9955
9956void nsContentUtils::TransferablesToIPCTransferableDatas(
9957 nsIArray* aTransferables, nsTArray<IPCTransferableData>& aIPC,
9958 bool aInSyncMessage, mozilla::dom::ContentParent* aParent) {
9959 aIPC.Clear();
9960 if (aTransferables) {
9961 uint32_t transferableCount = 0;
9962 aTransferables->GetLength(&transferableCount);
9963 for (uint32_t i = 0; i < transferableCount; ++i) {
9964 IPCTransferableData* dt = aIPC.AppendElement();
9965 nsCOMPtr<nsITransferable> transferable =
9966 do_QueryElementAt(aTransferables, i);
9967 TransferableToIPCTransferableData(transferable, dt, aInSyncMessage,
9968 aParent);
9969 }
9970 }
9971}
9972
9973nsresult nsContentUtils::CalculateBufferSizeForImage(
9974 const uint32_t& aStride, const IntSize& aImageSize,
9975 const SurfaceFormat& aFormat, size_t* aMaxBufferSize,
9976 size_t* aUsedBufferSize) {
9977 if (aImageSize.width <= 0 || aImageSize.height <= 0) {
9978 return NS_ERROR_FAILURE;
9979 }
9980
9981 CheckedInt32 rowBytes =
9982 CheckedInt32(aImageSize.width) * BytesPerPixel(aFormat);
9983 CheckedInt32 stride(aStride);
9984 if (!rowBytes.isValid() || !stride.isValid() ||
9985 stride.value() < rowBytes.value()) {
9986 return NS_ERROR_FAILURE;
9987 }
9988
9989 CheckedInt32 requiredBytes = stride * CheckedInt32(aImageSize.height);
9990 CheckedInt32 usedBytes = requiredBytes - stride + rowBytes;
9991 if (!requiredBytes.isValid() || !usedBytes.isValid()) {
9992 return NS_ERROR_FAILURE;
9993 }
9994
9995 *aMaxBufferSize = requiredBytes.value();
9996 *aUsedBufferSize = usedBytes.value();
9997 return NS_OK;
9998}
9999
10000static already_AddRefed<DataSourceSurface> BigBufferToDataSurface(
10001 const BigBuffer& aData, uint32_t aStride, const IntSize& aImageSize,
10002 SurfaceFormat aFormat) {
10003 if (!aData.Size() || !aImageSize.width || !aImageSize.height) {
10004 return nullptr;
10005 }
10006
10007 // Validate shared memory buffer size
10008 size_t imageBufLen = 0;
10009 size_t maxBufLen = 0;
10010 if (NS_FAILED(nsContentUtils::CalculateBufferSizeForImage(((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::CalculateBufferSizeForImage
( aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen
))), 0)))
10011 aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::CalculateBufferSizeForImage
( aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen
))), 0)))
) {
10012 return nullptr;
10013 }
10014 if (imageBufLen > aData.Size()) {
10015 return nullptr;
10016 }
10017 return CreateDataSourceSurfaceFromData(aImageSize, aFormat, aData.Data(),
10018 aStride);
10019}
10020
10021bool nsContentUtils::IsFlavorImage(const nsACString& aFlavor) {
10022 return aFlavor.EqualsLiteral(kNativeImageMime"application/x-moz-nativeimage") ||
10023 aFlavor.EqualsLiteral(kJPEGImageMime"image/jpeg") ||
10024 aFlavor.EqualsLiteral(kJPGImageMime"image/jpg") ||
10025 aFlavor.EqualsLiteral(kPNGImageMime"image/png") ||
10026 aFlavor.EqualsLiteral(kGIFImageMime"image/gif");
10027}
10028
10029// FIXME: This can probably be removed once bug 1783240 lands, as `nsString`
10030// will be implicitly serialized in shmem when sent over IPDL directly.
10031static IPCTransferableDataString AsIPCTransferableDataString(
10032 Span<const char16_t> aInput) {
10033 return IPCTransferableDataString{BigBuffer(AsBytes(aInput))};
10034}
10035
10036// FIXME: This can probably be removed once bug 1783240 lands, as `nsCString`
10037// will be implicitly serialized in shmem when sent over IPDL directly.
10038static IPCTransferableDataCString AsIPCTransferableDataCString(
10039 Span<const char> aInput) {
10040 return IPCTransferableDataCString{BigBuffer(AsBytes(aInput))};
10041}
10042
10043void nsContentUtils::TransferableToIPCTransferableData(
10044 nsITransferable* aTransferable, IPCTransferableData* aTransferableData,
10045 bool aInSyncMessage, mozilla::dom::ContentParent* aParent) {
10046 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"
, 10046); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent" ")"
); do { MOZ_CrashSequence(__null, 10046); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
10047
10048 if (aTransferable) {
10049 nsTArray<nsCString> flavorList;
10050 aTransferable->FlavorsTransferableCanExport(flavorList);
10051
10052 for (uint32_t j = 0; j < flavorList.Length(); ++j) {
10053 nsCString& flavorStr = flavorList[j];
10054 if (!flavorStr.Length()) {
10055 continue;
10056 }
10057
10058 nsCOMPtr<nsISupports> data;
10059 nsresult rv =
10060 aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(data));
10061
10062 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !data) {
10063 if (aInSyncMessage) {
10064 // Can't do anything.
10065 // FIXME: This shouldn't be the case anymore!
10066 continue;
10067 }
10068
10069 // This is a hack to support kFilePromiseMime.
10070 // On Windows there just needs to be an entry for it,
10071 // and for OSX we need to create
10072 // nsContentAreaDragDropDataProvider as nsIFlavorDataProvider.
10073 if (flavorStr.EqualsLiteral(kFilePromiseMime"application/x-moz-file-promise")) {
10074 IPCTransferableDataItem* item =
10075 aTransferableData->items().AppendElement();
10076 item->flavor() = flavorStr;
10077 item->data() =
10078 AsIPCTransferableDataString(NS_ConvertUTF8toUTF16(flavorStr));
10079 continue;
10080 }
10081
10082 // Empty element, transfer only the flavor
10083 IPCTransferableDataItem* item =
10084 aTransferableData->items().AppendElement();
10085 item->flavor() = flavorStr;
10086 item->data() = AsIPCTransferableDataString(EmptyString());
10087 continue;
10088 }
10089
10090 // We need to handle nsIInputStream before nsISupportsCString, otherwise
10091 // nsStringInputStream would be converted into a wrong type.
10092 if (nsCOMPtr<nsIInputStream> stream = do_QueryInterface(data)) {
10093 IPCTransferableDataItem* item =
10094 aTransferableData->items().AppendElement();
10095 item->flavor() = flavorStr;
10096 nsCString imageData;
10097 DebugOnly<nsresult> rv =
10098 NS_ConsumeStream(stream, UINT32_MAX(4294967295U), imageData);
10099 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", 10101
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK"
") (" "cannot use async input streams in nsITransferable right now"
")"); do { MOZ_CrashSequence(__null, 10101); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10100 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", 10101
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK"
") (" "cannot use async input streams in nsITransferable right now"
")"); do { MOZ_CrashSequence(__null, 10101); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10101 "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", 10101
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK"
") (" "cannot use async input streams in nsITransferable right now"
")"); do { MOZ_CrashSequence(__null, 10101); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10102 // FIXME: This can probably be simplified once bug 1783240 lands, as
10103 // `nsCString` will be implicitly serialized in shmem when sent over
10104 // IPDL directly.
10105 item->data() =
10106 IPCTransferableDataInputStream(BigBuffer(AsBytes(Span(imageData))));
10107 continue;
10108 }
10109
10110 if (nsCOMPtr<nsISupportsString> text = do_QueryInterface(data)) {
10111 nsAutoString dataAsString;
10112 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", 10112); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(text->GetData(dataAsString))" ")"
); do { MOZ_CrashSequence(__null, 10112); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
10113
10114 IPCTransferableDataItem* item =
10115 aTransferableData->items().AppendElement();
10116 item->flavor() = flavorStr;
10117 item->data() = AsIPCTransferableDataString(dataAsString);
10118 continue;
10119 }
10120
10121 if (nsCOMPtr<nsISupportsCString> ctext = do_QueryInterface(data)) {
10122 nsAutoCString dataAsString;
10123 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", 10123); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(ctext->GetData(dataAsString))"
")"); do { MOZ_CrashSequence(__null, 10123); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
10124
10125 IPCTransferableDataItem* item =
10126 aTransferableData->items().AppendElement();
10127 item->flavor() = flavorStr;
10128 item->data() = AsIPCTransferableDataCString(dataAsString);
10129 continue;
10130 }
10131
10132 if (nsCOMPtr<imgIContainer> image = do_QueryInterface(data)) {
10133 // Images to be placed on the clipboard are imgIContainers.
10134 RefPtr<mozilla::gfx::SourceSurface> surface = image->GetFrame(
10135 imgIContainer::FRAME_CURRENT,
10136 imgIContainer::FLAG_SYNC_DECODE | imgIContainer::FLAG_ASYNC_NOTIFY);
10137 if (!surface) {
10138 continue;
10139 }
10140 RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
10141 surface->GetDataSurface();
10142 if (!dataSurface) {
10143 continue;
10144 }
10145
10146 auto imageData = nsContentUtils::SurfaceToIPCImage(*dataSurface);
10147 if (!imageData) {
10148 continue;
10149 }
10150
10151 IPCTransferableDataItem* item =
10152 aTransferableData->items().AppendElement();
10153 item->flavor() = flavorStr;
10154 item->data() = IPCTransferableDataImageContainer(std::move(*imageData));
10155 continue;
10156 }
10157
10158 // Otherwise, handle this as a file.
10159 nsCOMPtr<BlobImpl> blobImpl;
10160 if (nsCOMPtr<nsIFile> file = do_QueryInterface(data)) {
10161 if (aParent) {
10162 bool isDir = false;
10163 if (NS_SUCCEEDED(file->IsDirectory(&isDir))((bool)(__builtin_expect(!!(!NS_FAILED_impl(file->IsDirectory
(&isDir))), 1)))
&& isDir) {
10164 nsAutoString path;
10165 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", 10165)
) {
10166 continue;
10167 }
10168
10169 RefPtr<FileSystemSecurity> fss = FileSystemSecurity::GetOrCreate();
10170 fss->GrantAccessToContentProcess(aParent->ChildID(), path);
10171 }
10172 }
10173
10174 blobImpl = new FileBlobImpl(file);
10175
10176 IgnoredErrorResult rv;
10177
10178 // Ensure that file data is cached no that the content process
10179 // has this data available to it when passed over:
10180 blobImpl->GetSize(rv);
10181 if (NS_WARN_IF(rv.Failed())NS_warn_if_impl(rv.Failed(), "rv.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10181)
) {
10182 continue;
10183 }
10184
10185 blobImpl->GetLastModified(rv);
10186 if (NS_WARN_IF(rv.Failed())NS_warn_if_impl(rv.Failed(), "rv.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10186)
) {
10187 continue;
10188 }
10189 } else {
10190 if (aInSyncMessage) {
10191 // Can't do anything.
10192 // FIXME: This shouldn't be the case anymore!
10193 continue;
10194 }
10195
10196 blobImpl = do_QueryInterface(data);
10197 }
10198
10199 if (blobImpl) {
10200 // If we failed to create the blob actor, then this blob probably
10201 // can't get the file size for the underlying file, ignore it for
10202 // now. TODO pass this through anyway.
10203 IPCBlob ipcBlob;
10204 nsresult rv = IPCBlobUtils::Serialize(blobImpl, ipcBlob);
10205 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"
, 10205)
) {
10206 continue;
10207 }
10208
10209 IPCTransferableDataItem* item =
10210 aTransferableData->items().AppendElement();
10211 item->flavor() = flavorStr;
10212 item->data() = IPCTransferableDataBlob(ipcBlob);
10213 }
10214 }
10215 }
10216}
10217
10218void nsContentUtils::TransferableToIPCTransferable(
10219 nsITransferable* aTransferable, IPCTransferable* aIPCTransferable,
10220 bool aInSyncMessage, mozilla::dom::ContentParent* aParent) {
10221 IPCTransferableData ipcTransferableData;
10222 TransferableToIPCTransferableData(aTransferable, &ipcTransferableData,
10223 aInSyncMessage, aParent);
10224
10225 Maybe<net::CookieJarSettingsArgs> cookieJarSettingsArgs;
10226 if (nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
10227 aTransferable->GetCookieJarSettings()) {
10228 net::CookieJarSettingsArgs args;
10229 net::CookieJarSettings::Cast(cookieJarSettings)->Serialize(args);
10230 cookieJarSettingsArgs = Some(std::move(args));
10231 }
10232
10233 aIPCTransferable->data() = std::move(ipcTransferableData);
10234 aIPCTransferable->isPrivateData() = aTransferable->GetIsPrivateData();
10235 aIPCTransferable->dataPrincipal() = aTransferable->GetDataPrincipal();
10236 aIPCTransferable->cookieJarSettings() = std::move(cookieJarSettingsArgs);
10237 aIPCTransferable->contentPolicyType() = aTransferable->GetContentPolicyType();
10238 aIPCTransferable->referrerInfo() = aTransferable->GetReferrerInfo();
10239}
10240
10241Maybe<BigBuffer> nsContentUtils::GetSurfaceData(DataSourceSurface& aSurface,
10242 size_t* aLength,
10243 int32_t* aStride) {
10244 mozilla::gfx::DataSourceSurface::MappedSurface map;
10245 if (!aSurface.Map(mozilla::gfx::DataSourceSurface::MapType::READ, &map)) {
10246 return Nothing();
10247 }
10248
10249 size_t bufLen = 0;
10250 size_t maxBufLen = 0;
10251 nsresult rv = nsContentUtils::CalculateBufferSizeForImage(
10252 map.mStride, aSurface.GetSize(), aSurface.GetFormat(), &maxBufLen,
10253 &bufLen);
10254 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10255 aSurface.Unmap();
10256 return Nothing();
10257 }
10258
10259 BigBuffer surfaceData = BigBuffer::TryAlloc(maxBufLen);
10260 if (surfaceData.Size() != maxBufLen) {
10261 aSurface.Unmap();
10262 return Nothing();
10263 }
10264 memcpy(surfaceData.Data(), map.mData, bufLen);
10265 memset(surfaceData.Data() + bufLen, 0, maxBufLen - bufLen);
10266
10267 *aLength = maxBufLen;
10268 *aStride = map.mStride;
10269
10270 aSurface.Unmap();
10271 return Some(std::move(surfaceData));
10272}
10273
10274Maybe<IPCImage> nsContentUtils::SurfaceToIPCImage(DataSourceSurface& aSurface) {
10275 size_t len = 0;
10276 int32_t stride = 0;
10277 auto mem = GetSurfaceData(aSurface, &len, &stride);
10278 if (!mem) {
10279 return Nothing();
10280 }
10281 return Some(IPCImage{std::move(*mem), uint32_t(stride), aSurface.GetFormat(),
10282 ImageIntSize::FromUnknownSize(aSurface.GetSize())});
10283}
10284
10285already_AddRefed<DataSourceSurface> nsContentUtils::IPCImageToSurface(
10286 const IPCImage& aImage) {
10287 return BigBufferToDataSurface(aImage.data(), aImage.stride(),
10288 aImage.size().ToUnknownSize(), aImage.format());
10289}
10290
10291already_AddRefed<imgIContainer> nsContentUtils::IPCImageToImage(
10292 const IPCImage& aImage) {
10293 RefPtr<DataSourceSurface> surface = IPCImageToSurface(aImage);
10294 if (!surface) {
10295 return nullptr;
10296 }
10297
10298 auto drawable = MakeRefPtr<gfxSurfaceDrawable>(surface, surface->GetSize());
10299 nsCOMPtr<imgIContainer> imageContainer =
10300 image::ImageOps::CreateFromDrawable(drawable);
10301 return imageContainer.forget();
10302}
10303
10304Modifiers nsContentUtils::GetWidgetModifiers(int32_t aModifiers) {
10305 Modifiers result = 0;
10306 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SHIFT) {
10307 result |= mozilla::MODIFIER_SHIFT;
10308 }
10309 if (aModifiers & nsIDOMWindowUtils::MODIFIER_CONTROL) {
10310 result |= mozilla::MODIFIER_CONTROL;
10311 }
10312 if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALT) {
10313 result |= mozilla::MODIFIER_ALT;
10314 }
10315 if (aModifiers & nsIDOMWindowUtils::MODIFIER_META) {
10316 result |= mozilla::MODIFIER_META;
10317 }
10318 if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALTGRAPH) {
10319 result |= mozilla::MODIFIER_ALTGRAPH;
10320 }
10321 if (aModifiers & nsIDOMWindowUtils::MODIFIER_CAPSLOCK) {
10322 result |= mozilla::MODIFIER_CAPSLOCK;
10323 }
10324 if (aModifiers & nsIDOMWindowUtils::MODIFIER_FN) {
10325 result |= mozilla::MODIFIER_FN;
10326 }
10327 if (aModifiers & nsIDOMWindowUtils::MODIFIER_FNLOCK) {
10328 result |= mozilla::MODIFIER_FNLOCK;
10329 }
10330 if (aModifiers & nsIDOMWindowUtils::MODIFIER_NUMLOCK) {
10331 result |= mozilla::MODIFIER_NUMLOCK;
10332 }
10333 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SCROLLLOCK) {
10334 result |= mozilla::MODIFIER_SCROLLLOCK;
10335 }
10336 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOL) {
10337 result |= mozilla::MODIFIER_SYMBOL;
10338 }
10339 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOLLOCK) {
10340 result |= mozilla::MODIFIER_SYMBOLLOCK;
10341 }
10342 return result;
10343}
10344
10345nsIWidget* nsContentUtils::GetWidget(PresShell* aPresShell, nsPoint* aOffset) {
10346 if (!aPresShell) {
10347 return nullptr;
10348 }
10349 nsIFrame* frame = aPresShell->GetRootFrame();
10350 if (!frame) {
10351 return nullptr;
10352 }
10353 return aOffset ? frame->GetNearestWidget(*aOffset)
10354 : frame->GetNearestWidget();
10355}
10356
10357int16_t nsContentUtils::GetButtonsFlagForButton(int32_t aButton) {
10358 switch (aButton) {
10359 case -1:
10360 return MouseButtonsFlag::eNoButtons;
10361 case MouseButton::ePrimary:
10362 return MouseButtonsFlag::ePrimaryFlag;
10363 case MouseButton::eMiddle:
10364 return MouseButtonsFlag::eMiddleFlag;
10365 case MouseButton::eSecondary:
10366 return MouseButtonsFlag::eSecondaryFlag;
10367 case 3:
10368 return MouseButtonsFlag::e4thFlag;
10369 case 4:
10370 return MouseButtonsFlag::e5thFlag;
10371 case MouseButton::eEraser:
10372 return MouseButtonsFlag::eEraserFlag;
10373 default:
10374 NS_ERROR("Button not known.")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Button not known.", "Error"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10374); MOZ_PretendNoReturn
(); } while (0)
;
10375 return 0;
10376 }
10377}
10378
10379LayoutDeviceIntPoint nsContentUtils::ToWidgetPoint(
10380 const CSSPoint& aPoint, const nsPoint& aOffset,
10381 nsPresContext* aPresContext) {
10382 nsPoint layoutRelative = CSSPoint::ToAppUnits(aPoint) + aOffset;
10383 nsPoint visualRelative =
10384 ViewportUtils::LayoutToVisual(layoutRelative, aPresContext->PresShell());
10385 return LayoutDeviceIntPoint::FromAppUnitsRounded(
10386 visualRelative, aPresContext->AppUnitsPerDevPixel());
10387}
10388
10389namespace {
10390
10391class SynthesizedEventCallback final : public nsISynthesizedEventCallback {
10392 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:
10393
10394 public:
10395 explicit SynthesizedEventCallback(VoidFunction& aCallback)
10396 : mCallback(&aCallback) {}
10397
10398 MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODvirtual nsresult OnCompleteDispatch() override {
10399 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", 10399
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCallback" ") (" "How can we have a null mCallback here?"
")"); do { MOZ_CrashSequence(__null, 10399); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10400
10401 ErrorResult rv;
10402 MOZ_KnownLive(mCallback)(mCallback)->Call(rv);
10403 if (MOZ_UNLIKELY(rv.Failed())(__builtin_expect(!!(rv.Failed()), 0))) {
10404 return rv.StealNSResult();
10405 }
10406
10407 return NS_OK;
10408 }
10409
10410 private:
10411 virtual ~SynthesizedEventCallback() = default;
10412
10413 const RefPtr<VoidFunction> mCallback;
10414};
10415
10416NS_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"
, 10416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 10416
); __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"
, 10416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SynthesizedEventCallback\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 10416); __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"
, 10416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 10416
); __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"
, 10416); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SynthesizedEventCallback\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 10416); __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"
, 10416); 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; }
10417
10418} // namespace
10419
10420Result<bool, nsresult> nsContentUtils::SynthesizeMouseEvent(
10421 mozilla::PresShell* aPresShell, nsIWidget* aWidget, const nsAString& aType,
10422 LayoutDeviceIntPoint& aRefPoint,
10423 const SynthesizeMouseEventData& aMouseEventData,
10424 const SynthesizeMouseEventOptions& aOptions,
10425 const Optional<OwningNonNull<VoidFunction>>& aCallback) {
10426 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"
, 10426); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresShell"
")"); do { MOZ_CrashSequence(__null, 10426); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10427 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"
, 10427); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWidget" ")"
); do { MOZ_CrashSequence(__null, 10427); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10428 AUTO_PROFILER_LABEL("nsContentUtils::SynthesizeMouseEvent", OTHER)mozilla::AutoProfilerLabel raiiObject10428( "nsContentUtils::SynthesizeMouseEvent"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
10429
10430 if (aCallback.WasPassed()) {
10431 if (!XRE_IsParentProcess()) {
10432 // TODO(edgar): There is currently no real use case for synthesizing a
10433 // mouse event with a callback from the content process. For now, throw an
10434 // error in this case. We can add support later if a valid use case
10435 // arises.
10436 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"
, 10438)
10437 "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"
, 10438)
10438 "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"
, 10438)
;
10439 return Err(NS_ERROR_FAILURE);
10440 }
10441
10442 if (!aOptions.mIsDOMEventSynthesized) {
10443 // TODO(edgar): There is currently no real use case for synthesizing a
10444 // mouse event with a callback that could be coalesced. For now, throw an
10445 // error. We can add support later if a need arises.
10446 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", 10449)
10447 "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", 10449)
10448 "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", 10449)
10449 "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", 10449)
;
10450 return Err(NS_ERROR_FAILURE);
10451 }
10452 }
10453
10454 EventMessage msg;
10455 Maybe<WidgetMouseEvent::ExitFrom> exitFrom;
10456 bool contextMenuKey = false;
10457 if (aType.EqualsLiteral("mousedown")) {
10458 msg = eMouseDown;
10459 } else if (aType.EqualsLiteral("mouseup")) {
10460 msg = eMouseUp;
10461 } else if (aType.EqualsLiteral("mousemove")) {
10462 msg = eMouseMove;
10463 } else if (aType.EqualsLiteral("mouseover")) {
10464 msg = eMouseEnterIntoWidget;
10465 } else if (aType.EqualsLiteral("mouseout")) {
10466 msg = eMouseExitFromWidget;
10467 exitFrom = Some(WidgetMouseEvent::ePlatformChild);
10468 } else if (aType.EqualsLiteral("mousecancel")) {
10469 msg = eMouseExitFromWidget;
10470 exitFrom = Some(XRE_IsParentProcess() ? WidgetMouseEvent::ePlatformTopLevel
10471 : WidgetMouseEvent::ePuppet);
10472 } else if (aType.EqualsLiteral("mouselongtap")) {
10473 msg = eMouseLongTap;
10474 } else if (aType.EqualsLiteral("contextmenu")) {
10475 msg = eContextMenu;
10476 contextMenuKey =
10477 !aMouseEventData.mButton &&
10478 aMouseEventData.mInputSource != MouseEvent_Binding::MOZ_SOURCE_TOUCH;
10479 } else if (aType.EqualsLiteral("MozMouseHittest")) {
10480 msg = eMouseHitTest;
10481 } else {
10482 return Err(NS_ERROR_FAILURE);
10483 }
10484
10485 if (aMouseEventData.mMovementX.WasPassed() !=
10486 aMouseEventData.mMovementY.WasPassed()) {
10487 return Err(NS_ERROR_INVALID_ARG);
10488 }
10489
10490 Maybe<WidgetPointerEvent> pointerEvent;
10491 Maybe<WidgetMouseEvent> mouseEvent;
10492 if (IsPointerEventMessage(msg)) {
10493 if (MOZ_UNLIKELY(aOptions.mIsWidgetEventSynthesized)(__builtin_expect(!!(aOptions.mIsWidgetEventSynthesized), 0))) {
10494 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", 10495); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "The event shouldn't be dispatched as a synthesized event"
")"); do { MOZ_CrashSequence(__null, 10495); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10495 "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", 10495); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "The event shouldn't be dispatched as a synthesized event"
")"); do { MOZ_CrashSequence(__null, 10495); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10496 // `click`, `auxclick` nor `contextmenu` should not be dispatched as a
10497 // synthesized event.
10498 return Err(NS_ERROR_INVALID_ARG);
10499 }
10500 pointerEvent.emplace(true, msg, aWidget,
10501 contextMenuKey ? WidgetMouseEvent::eContextMenuKey
10502 : WidgetMouseEvent::eNormal);
10503 } else {
10504 mouseEvent.emplace(true, msg, aWidget,
10505 aOptions.mIsWidgetEventSynthesized
10506 ? WidgetMouseEvent::eSynthesized
10507 : WidgetMouseEvent::eReal,
10508 contextMenuKey ? WidgetMouseEvent::eContextMenuKey
10509 : WidgetMouseEvent::eNormal);
10510 }
10511
10512 nsCOMPtr<nsISynthesizedEventCallback> callback;
10513 if (aCallback.WasPassed()) {
10514 callback = MakeAndAddRef<SynthesizedEventCallback>(aCallback.Value());
10515 }
10516
10517 mozilla::widget::AutoSynthesizedEventCallbackNotifier notifier(callback);
10518
10519 WidgetMouseEvent& mouseOrPointerEvent =
10520 pointerEvent.isSome() ? pointerEvent.ref() : mouseEvent.ref();
10521 mouseOrPointerEvent.pointerId = aMouseEventData.mIdentifier;
10522 mouseOrPointerEvent.mModifiers =
10523 GetWidgetModifiers(aMouseEventData.mModifiers);
10524 mouseOrPointerEvent.mButton = aMouseEventData.mButton;
10525 mouseOrPointerEvent.mButtons =
10526 aMouseEventData.mButtons.WasPassed()
10527 ? aMouseEventData.mButtons.Value()
10528 : (msg != eMouseDown
10529 ? 0
10530 : GetButtonsFlagForButton(aMouseEventData.mButton));
10531 // https://w3c.github.io/pointerevents/#dom-pointerevent-pressure.
10532 mouseOrPointerEvent.mPressure =
10533 aMouseEventData.mPressure.WasPassed()
10534 ? aMouseEventData.mPressure.Value()
10535 : ((mouseOrPointerEvent.mButtons == 0) ? 0.0f : 0.5f);
10536 mouseOrPointerEvent.mInputSource = aMouseEventData.mInputSource;
10537 mouseOrPointerEvent.mClickCount =
10538 aMouseEventData.mClickCount.WasPassed()
10539 ? aMouseEventData.mClickCount.Value()
10540 : ((msg == eMouseDown || msg == eMouseUp) ? 1 : 0);
10541 mouseOrPointerEvent.mFlags.mIsSynthesizedForTests =
10542 aOptions.mIsDOMEventSynthesized;
10543 mouseOrPointerEvent.mExitFrom = std::move(exitFrom);
10544 mouseOrPointerEvent.mCallbackId = notifier.SaveCallback();
10545
10546 nsPresContext* presContext = aPresShell->GetPresContext();
10547 if (!presContext) {
10548 return Err(NS_ERROR_FAILURE);
10549 }
10550
10551 mouseOrPointerEvent.mRefPoint = aRefPoint;
10552 mouseOrPointerEvent.mIgnoreRootScrollFrame = aOptions.mIgnoreRootScrollFrame;
10553 if (aMouseEventData.mMovementX.WasPassed()) {
10554 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", 10554); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aMouseEventData.mMovementY.WasPassed()" ")"
); do { MOZ_CrashSequence(__null, 10554); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10555 mouseOrPointerEvent.mMovement.emplace(aMouseEventData.mMovementX.Value(),
10556 aMouseEventData.mMovementY.Value());
10557 }
10558
10559 nsEventStatus status = nsEventStatus_eIgnore;
10560 if (aOptions.mToWindow) {
10561 nsresult rv = aPresShell->HandleEvent(aPresShell->GetRootFrame(),
10562 &mouseOrPointerEvent, false, &status);
10563 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10564 return Err(rv);
10565 }
10566 } else if (aOptions.mIsAsyncEnabled ||
10567 StaticPrefs::test_events_async_enabled()) {
10568 // The event is dispatched asynchronously via WebDriver when it is not
10569 // targeted directly at a window and async dispatching is requested.
10570 mouseOrPointerEvent.mFlags.mIsAsyncSynthesizedForTests =
10571 aOptions.mIsDOMEventSynthesized;
10572 status = aWidget->DispatchInputEvent(&mouseOrPointerEvent).mContentStatus;
10573 } else {
10574 status = aWidget->DispatchEvent(&mouseOrPointerEvent);
10575 }
10576
10577 // The callback ID may be cleared when the event also needs to be dispatched
10578 // to a content process. In such cases, the callback will be notified after
10579 // the event has been dispatched in the target content process.
10580 if (mouseOrPointerEvent.mCallbackId.isSome()) {
10581 mozilla::widget::AutoSynthesizedEventCallbackNotifier::NotifySavedCallback(
10582 mouseOrPointerEvent.mCallbackId.ref());
10583 }
10584
10585 return status == nsEventStatus_eConsumeNoDefault;
10586}
10587
10588mozilla::Result<bool, nsresult> nsContentUtils::SynthesizeTouchEvent(
10589 nsPresContext* aPresContext, nsIWidget* aWidget,
10590 const nsPoint& aWidgetOffset, const nsAString& aType,
10591 const nsTArray<SynthesizeTouchEventData>& aTouches,
10592 const int32_t aModifiers, const SynthesizeTouchEventOptions& aOptions,
10593 const Optional<OwningNonNull<VoidFunction>>& aCallback) {
10594 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"
, 10594); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresContext"
")"); do { MOZ_CrashSequence(__null, 10594); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10595 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"
, 10595); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWidget" ")"
); do { MOZ_CrashSequence(__null, 10595); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10596 AUTO_PROFILER_LABEL("nsContentUtils::SynthesizeTouchEvent", OTHER)mozilla::AutoProfilerLabel raiiObject10596( "nsContentUtils::SynthesizeTouchEvent"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
10597
10598 if (aCallback.WasPassed()) {
10599 if (!XRE_IsParentProcess()) {
10600 // TODO(edgar): There is currently no real use case for synthesizing a
10601 // touch event with a callback from the content process. For now, throw an
10602 // error in this case. We can add support later if a valid use case
10603 // arises.
10604 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"
, 10606)
10605 "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"
, 10606)
10606 "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"
, 10606)
;
10607 return Err(NS_ERROR_FAILURE);
10608 }
10609
10610 if (!aOptions.mIsDOMEventSynthesized) {
10611 // TODO(edgar): There is currently no real use case for synthesizing a
10612 // touch event with a callback that could be coalesced. For now, throw an
10613 // error. We can add support later if a need arises.
10614 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", 10617)
10615 "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", 10617)
10616 "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", 10617)
10617 "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", 10617)
;
10618 return Err(NS_ERROR_FAILURE);
10619 }
10620 }
10621
10622 if (XRE_IsParentProcess() && !aOptions.mIsAsyncEnabled &&
10623 !StaticPrefs::test_events_async_enabled()) {
10624 // TODO(edgar): Currently, dispatching touch event from parent process
10625 // without going through APZ would cause content process crash on debug
10626 // build.
10627 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", 10629)
10628 "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", 10629)
10629 "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", 10629)
;
10630 return Err(NS_ERROR_FAILURE);
10631 }
10632
10633 EventMessage msg;
10634 if (aType.EqualsLiteral("touchstart")) {
10635 msg = eTouchStart;
10636 } else if (aType.EqualsLiteral("touchmove")) {
10637 msg = eTouchMove;
10638 } else if (aType.EqualsLiteral("touchend")) {
10639 msg = eTouchEnd;
10640 } else if (aType.EqualsLiteral("touchcancel")) {
10641 msg = eTouchCancel;
10642 } else {
10643 return Err(NS_ERROR_UNEXPECTED);
10644 }
10645
10646 nsCOMPtr<nsISynthesizedEventCallback> callback;
10647 if (aCallback.WasPassed()) {
10648 callback = MakeAndAddRef<SynthesizedEventCallback>(aCallback.Value());
10649 }
10650
10651 mozilla::widget::AutoSynthesizedEventCallbackNotifier notifier(callback);
10652
10653 WidgetTouchEvent event(true, msg, aWidget);
10654 event.mFlags.mIsSynthesizedForTests = aOptions.mIsDOMEventSynthesized;
10655 event.mModifiers = nsContentUtils::GetWidgetModifiers(aModifiers);
10656 if (aOptions.mIsPen) {
10657 event.mInputSource = MouseEvent_Binding::MOZ_SOURCE_PEN;
10658 }
10659 event.mCallbackId = notifier.SaveCallback();
10660
10661 uint32_t count = aTouches.Length();
10662 event.mTouches.SetCapacity(count);
10663 for (uint32_t i = 0; i < count; ++i) {
10664 if (aTouches[i].mAltitudeAngle.WasPassed() !=
10665 aTouches[i].mAzimuthAngle.WasPassed()) {
10666 return Err(NS_ERROR_INVALID_ARG);
10667 }
10668
10669 LayoutDeviceIntPoint pt = nsContentUtils::ToWidgetPoint(
10670 CSSPoint(aTouches[i].mOffsetX, aTouches[i].mOffsetY), aWidgetOffset,
10671 aPresContext);
10672 LayoutDeviceIntPoint radius = LayoutDeviceIntPoint::FromAppUnitsRounded(
10673 CSSPoint::ToAppUnits(
10674 CSSPoint(aTouches[i].mRadiiX, aTouches[i].mRadiiY)),
10675 aPresContext->AppUnitsPerDevPixel());
10676 // https://w3c.github.io/pointerevents/#dom-pointerevent-pressure.
10677 float pressure = aTouches[i].mPressure.WasPassed()
10678 ? aTouches[i].mPressure.Value()
10679 : (msg == eTouchEnd ? 0.0f : 0.5f);
10680
10681 RefPtr<Touch> t =
10682 new Touch(CheckedInt<int32_t>(aTouches[i].mIdentifier).value(), pt,
10683 radius, aTouches[i].mRotationAngle, pressure);
10684 if (aTouches[i].mAltitudeAngle.WasPassed()) {
10685 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", 10685); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aTouches[i].mAzimuthAngle.WasPassed()" ")"
); do { MOZ_CrashSequence(__null, 10685); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10686 t->mAngle.emplace(aTouches[i].mAltitudeAngle.Value(),
10687 aTouches[i].mAzimuthAngle.Value());
10688 } else {
10689 t->mTilt.emplace(aTouches[i].mTiltX, aTouches[i].mTiltY);
10690 }
10691 t->twist = aTouches[i].mTwist;
10692 event.mTouches.AppendElement(t);
10693 }
10694
10695 nsEventStatus status = nsEventStatus_eIgnore;
10696 if (aOptions.mToWindow) {
10697 RefPtr<PresShell> presShell = aPresContext->PresShell();
10698 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(); })
10699 &status))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(presShell->HandleEvent(presShell->GetRootFrame(), &
event, false, &status)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
;
10700 } else if (aOptions.mIsAsyncEnabled ||
10701 StaticPrefs::test_events_async_enabled()) {
10702 status = aWidget->DispatchInputEvent(&event).mContentStatus;
10703 } else {
10704 status = aWidget->DispatchEvent(&event);
10705 }
10706
10707 // The callback ID may be cleared when the event also needs to be dispatched
10708 // to a content process. In such cases, the callback will be notified after
10709 // the event has been dispatched in the target content process.
10710 if (event.mCallbackId.isSome()) {
10711 mozilla::widget::AutoSynthesizedEventCallbackNotifier::NotifySavedCallback(
10712 event.mCallbackId.ref());
10713 }
10714
10715 return status == nsEventStatus_eConsumeNoDefault;
10716}
10717
10718/* static */
10719void nsContentUtils::FirePageHideEventForFrameLoaderSwap(
10720 nsIDocShellTreeItem* aItem, EventTarget* aChromeEventHandler,
10721 bool aOnlySystemGroup) {
10722 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"
, 10722); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aItem"
")"); do { MOZ_CrashSequence(__null, 10722); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10723 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", 10723); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "aChromeEventHandler" ")"); do {
MOZ_CrashSequence(__null, 10723); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
10724
10725 if (RefPtr<Document> doc = aItem->GetDocument()) {
10726 doc->OnPageHide(true, aChromeEventHandler, aOnlySystemGroup);
10727 }
10728
10729 int32_t childCount = 0;
10730 aItem->GetInProcessChildCount(&childCount);
10731 AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids;
10732 kids.AppendElements(childCount);
10733 for (int32_t i = 0; i < childCount; ++i) {
10734 aItem->GetInProcessChildAt(i, getter_AddRefs(kids[i]));
10735 }
10736
10737 for (uint32_t i = 0; i < kids.Length(); ++i) {
10738 if (kids[i]) {
10739 FirePageHideEventForFrameLoaderSwap(
10740 MOZ_KnownLive(kids[i])(kids[i]), aChromeEventHandler, aOnlySystemGroup);
10741 }
10742 }
10743}
10744
10745// The pageshow event is fired for a given document only if IsShowing()
10746// returns the same thing as aFireIfShowing. This gives us a way to fire
10747// pageshow only on documents that are still loading or only on documents that
10748// are already loaded.
10749/* static */
10750void nsContentUtils::FirePageShowEventForFrameLoaderSwap(
10751 nsIDocShellTreeItem* aItem, EventTarget* aChromeEventHandler,
10752 bool aFireIfShowing, bool aOnlySystemGroup) {
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 FirePageShowEventForFrameLoaderSwap(MOZ_KnownLive(kids[i])(kids[i]),
10764 aChromeEventHandler, aFireIfShowing,
10765 aOnlySystemGroup);
10766 }
10767 }
10768
10769 RefPtr<Document> doc = aItem->GetDocument();
10770 if (doc && doc->IsShowing() == aFireIfShowing) {
10771 doc->OnPageShow(true, aChromeEventHandler, aOnlySystemGroup);
10772 }
10773}
10774
10775/* static */
10776already_AddRefed<nsPIWindowRoot> nsContentUtils::GetWindowRoot(Document* aDoc) {
10777 if (aDoc) {
10778 if (nsPIDOMWindowOuter* win = aDoc->GetWindow()) {
10779 return win->GetTopWindowRoot();
10780 }
10781 }
10782 return nullptr;
10783}
10784
10785/* static */
10786bool nsContentUtils::LinkContextIsURI(const nsAString& aAnchor,
10787 nsIURI* aDocURI) {
10788 if (aAnchor.IsEmpty()) {
10789 // anchor parameter not present or empty -> same document reference
10790 return true;
10791 }
10792
10793 // the document URI might contain a fragment identifier ("#...')
10794 // we want to ignore that because it's invisible to the server
10795 // and just affects the local interpretation in the recipient
10796 nsCOMPtr<nsIURI> contextUri;
10797 nsresult rv = NS_GetURIWithoutRef(aDocURI, getter_AddRefs(contextUri));
10798
10799 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10800 // copying failed
10801 return false;
10802 }
10803
10804 // resolve anchor against context
10805 nsCOMPtr<nsIURI> resolvedUri;
10806 rv = NS_NewURI(getter_AddRefs(resolvedUri), aAnchor, nullptr, contextUri);
10807
10808 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10809 // resolving failed
10810 return false;
10811 }
10812
10813 bool same;
10814 rv = contextUri->Equals(resolvedUri, &same);
10815 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10816 // comparison failed
10817 return false;
10818 }
10819
10820 return same;
10821}
10822
10823/* static */
10824bool nsContentUtils::IsPreloadType(nsContentPolicyType aType) {
10825 return (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD ||
10826 aType == nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD ||
10827 aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD ||
10828 aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD ||
10829 aType == nsIContentPolicy::TYPE_INTERNAL_FONT_PRELOAD ||
10830 aType == nsIContentPolicy::TYPE_INTERNAL_JSON_PRELOAD ||
10831 aType == nsIContentPolicy::TYPE_INTERNAL_TEXT_PRELOAD ||
10832 aType == nsIContentPolicy::TYPE_INTERNAL_FETCH_PRELOAD);
10833}
10834
10835// static
10836bool nsContentUtils::IsImageType(ExtContentPolicy aType) {
10837 return aType == ExtContentPolicy::TYPE_IMAGE ||
10838 aType == ExtContentPolicy::TYPE_IMAGESET;
10839}
10840
10841// static
10842ReferrerPolicy nsContentUtils::GetReferrerPolicyFromChannel(
10843 nsIChannel* aChannel) {
10844 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
10845 if (!httpChannel) {
10846 return ReferrerPolicy::_empty;
10847 }
10848
10849 nsresult rv;
10850 nsAutoCString headerValue;
10851 rv = httpChannel->GetResponseHeader("referrer-policy"_ns, headerValue);
10852 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || headerValue.IsEmpty()) {
10853 return ReferrerPolicy::_empty;
10854 }
10855
10856 return ReferrerInfo::ReferrerPolicyFromHeaderString(
10857 NS_ConvertUTF8toUTF16(headerValue));
10858}
10859
10860// static
10861bool nsContentUtils::HasRelNoReferrer(const Element& aElement) {
10862 // rel=noreferrer is only supported in <a>, <area>, and <form>
10863 if (!aElement.IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area,
10864 nsGkAtoms::form) &&
10865 !aElement.IsSVGElement(nsGkAtoms::a) &&
10866 !(aElement.IsMathMLElement(nsGkAtoms::a) &&
10867 StaticPrefs::mathml_a_element_enabled())) {
10868 return false;
10869 }
10870
10871 nsAutoString rel;
10872 aElement.GetAttr(nsGkAtoms::rel, rel);
10873 nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(rel);
10874
10875 while (tok.hasMoreTokens()) {
10876 const nsAString& token = tok.nextToken();
10877 if (token.LowerCaseEqualsLiteral("noreferrer")) {
10878 return true;
10879 }
10880 }
10881
10882 return false;
10883}
10884
10885// static
10886bool nsContentUtils::IsNonSubresourceRequest(nsIChannel* aChannel) {
10887 nsLoadFlags loadFlags = 0;
10888 aChannel->GetLoadFlags(&loadFlags);
10889 if (loadFlags & nsIChannel::LOAD_DOCUMENT_URI) {
10890 return true;
10891 }
10892
10893 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
10894 nsContentPolicyType type = loadInfo->InternalContentPolicyType();
10895 return IsNonSubresourceInternalPolicyType(type);
10896}
10897
10898// static
10899bool nsContentUtils::IsNonSubresourceInternalPolicyType(
10900 nsContentPolicyType aType) {
10901 return aType == nsIContentPolicy::TYPE_DOCUMENT ||
10902 aType == nsIContentPolicy::TYPE_INTERNAL_IFRAME ||
10903 aType == nsIContentPolicy::TYPE_INTERNAL_FRAME ||
10904 aType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
10905 aType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
10906}
10907
10908// static public
10909bool nsContentUtils::IsThirdPartyTrackingResourceWindow(
10910 nsPIDOMWindowInner* aWindow) {
10911 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"
, 10911); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")"
); do { MOZ_CrashSequence(__null, 10911); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10912
10913 Document* document = aWindow->GetExtantDoc();
10914 if (!document) {
10915 return false;
10916 }
10917
10918 nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
10919 do_QueryInterface(document->GetChannel());
10920 if (!classifiedChannel) {
10921 return false;
10922 }
10923
10924 return classifiedChannel->IsThirdPartyTrackingResource();
10925}
10926
10927// static public
10928bool nsContentUtils::IsFirstPartyTrackingResourceWindow(
10929 nsPIDOMWindowInner* aWindow) {
10930 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"
, 10930); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")"
); do { MOZ_CrashSequence(__null, 10930); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10931
10932 Document* document = aWindow->GetExtantDoc();
10933 if (!document) {
10934 return false;
10935 }
10936
10937 nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
10938 do_QueryInterface(document->GetChannel());
10939 if (!classifiedChannel) {
10940 return false;
10941 }
10942
10943 uint32_t classificationFlags =
10944 classifiedChannel->GetFirstPartyClassificationFlags();
10945
10946 return mozilla::net::ChannelClassifierUtils::IsTrackingClassificationFlag(
10947 classificationFlags, NS_UsePrivateBrowsing(document->GetChannel()));
10948}
10949
10950namespace {
10951
10952// We put StringBuilder in the anonymous namespace to prevent anything outside
10953// this file from accidentally being linked against it.
10954class BulkAppender {
10955 using size_type = typename nsAString::size_type;
10956
10957 public:
10958 explicit BulkAppender(BulkWriteHandle<char16_t>&& aHandle)
10959 : mHandle(std::move(aHandle)), mPosition(0) {}
10960 ~BulkAppender() = default;
10961
10962 template <int N>
10963 void AppendLiteral(const char16_t (&aStr)[N]) {
10964 size_t len = N - 1;
10965 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", 10965); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()" ")"
); do { MOZ_CrashSequence(__null, 10965); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10966 memcpy(mHandle.Elements() + mPosition, aStr, len * sizeof(char16_t));
10967 mPosition += len;
10968 }
10969
10970 void Append(Span<const char16_t> aStr) {
10971 size_t len = aStr.Length();
10972 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", 10972); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()" ")"
); do { MOZ_CrashSequence(__null, 10972); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10973 // Both mHandle.Elements() and aStr.Elements() are guaranteed
10974 // to be non-null (by the string implementation and by Span,
10975 // respectively), so not checking the pointers for null before
10976 // memcpy does not lead to UB even if len was zero.
10977 memcpy(mHandle.Elements() + mPosition, aStr.Elements(),
10978 len * sizeof(char16_t));
10979 mPosition += len;
10980 }
10981
10982 void Append(Span<const char> aStr) {
10983 size_t len = aStr.Length();
10984 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", 10984); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()" ")"
); do { MOZ_CrashSequence(__null, 10984); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10985 ConvertLatin1toUtf16(aStr, mHandle.AsSpan().From(mPosition));
10986 mPosition += len;
10987 }
10988
10989 void Finish() { mHandle.Finish(mPosition, false); }
10990
10991 private:
10992 BulkWriteHandle<char16_t> mHandle;
10993 size_type mPosition;
10994};
10995
10996class StringBuilderSIMD {
10997 public:
10998 static const bool SIMD = true;
10999};
11000
11001class StringBuilderALU {
11002 public:
11003 static const bool SIMD = false;
11004};
11005
11006class StringBuilder {
11007 private:
11008 class Unit {
11009 public:
11010 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)
; }
11011 ~Unit() {
11012 if (mType == Type::String || mType == Type::StringWithEncode) {
11013 mString.~nsString();
11014 }
11015 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)
;
11016 }
11017
11018 enum class Type : uint8_t {
11019 Unknown,
11020 Atom,
11021 String,
11022 StringWithEncode,
11023 Literal,
11024 TextFragment,
11025 TextFragmentWithEncode,
11026 };
11027
11028 struct LiteralSpan {
11029 const char16_t* mData;
11030 uint32_t mLength;
11031
11032 Span<const char16_t> AsSpan() { return Span(mData, mLength); }
11033 };
11034
11035 union {
11036 nsAtom* mAtom;
11037 LiteralSpan mLiteral;
11038 nsString mString;
11039 const CharacterDataBuffer* mCharacterDataBuffer;
11040 };
11041 Type mType = Type::Unknown;
11042 };
11043
11044 static_assert(sizeof(void*) != 8 || sizeof(Unit) <= 3 * sizeof(void*),
11045 "Unit should remain small");
11046
11047 public:
11048 // Try to keep the size of StringBuilder close to a jemalloc bucket size
11049 // (the 16kb one in this case).
11050 static constexpr uint32_t TARGET_SIZE = 16 * 1024;
11051
11052 // The number of units we need to remove from the inline buffer so that the
11053 // rest of the builder members fit. A more precise approach would be to
11054 // calculate that extra size and use (TARGET_SIZE - OTHER_SIZE) /
11055 // sizeof(Unit) or so, but this is simpler.
11056 static constexpr uint32_t PADDING_UNITS = sizeof(void*) == 8 ? 1 : 2;
11057
11058 static constexpr uint32_t STRING_BUFFER_UNITS =
11059 TARGET_SIZE / sizeof(Unit) - PADDING_UNITS;
11060
11061 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)
; }
11062
11063 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); }
11064
11065 void Append(nsAtom* aAtom) {
11066 Unit* u = AddUnit();
11067 u->mAtom = aAtom;
11068 u->mType = Unit::Type::Atom;
11069 uint32_t len = aAtom->GetLength();
11070 mLength += len;
11071 }
11072
11073 template <int N>
11074 void Append(const char16_t (&aLiteral)[N]) {
11075 constexpr uint32_t len = N - 1;
11076 Unit* u = AddUnit();
11077 u->mLiteral = {aLiteral, len};
11078 u->mType = Unit::Type::Literal;
11079 mLength += len;
11080 }
11081
11082 void Append(nsString&& aString) {
11083 Unit* u = AddUnit();
11084 uint32_t len = aString.Length();
11085 new (&u->mString) nsString(std::move(aString));
11086 u->mType = Unit::Type::String;
11087 mLength += len;
11088 }
11089
11090 // aLen can be !isValid(), which will get propagated into mLength.
11091 void AppendWithAttrEncode(nsString&& aString, CheckedInt<uint32_t> aLen) {
11092 Unit* u = AddUnit();
11093 new (&u->mString) nsString(std::move(aString));
11094 u->mType = Unit::Type::StringWithEncode;
11095 mLength += aLen;
11096 }
11097
11098 void Append(const CharacterDataBuffer* aCharacterDataBuffer) {
11099 Unit* u = AddUnit();
11100 u->mCharacterDataBuffer = aCharacterDataBuffer;
11101 u->mType = Unit::Type::TextFragment;
11102 uint32_t len = aCharacterDataBuffer->GetLength();
11103 mLength += len;
11104 }
11105
11106 // aLen can be !isValid(), which will get propagated into mLength.
11107 void AppendWithEncode(const CharacterDataBuffer* aCharacterDataBuffer,
11108 CheckedInt<uint32_t> aLen) {
11109 Unit* u = AddUnit();
11110 u->mCharacterDataBuffer = aCharacterDataBuffer;
11111 u->mType = Unit::Type::TextFragmentWithEncode;
11112 mLength += aLen;
11113 }
11114
11115 bool ToString(nsAString& aOut) {
11116 if (!mLength.isValid()) {
11117 return false;
11118 }
11119 auto appenderOrErr = aOut.BulkWrite(mLength.value(), 0, true);
11120 if (appenderOrErr.isErr()) {
11121 return false;
11122 }
11123
11124 BulkAppender appender{appenderOrErr.unwrap()};
11125
11126 // Experiment with moving this higher up the call stack
11127 // after we have experience from
11128 // https://bugzilla.mozilla.org/show_bug.cgi?id=1997255
11129 // on the parser side.
11130 bool simd = mozilla::htmlaccel::htmlaccelEnabled();
11131
11132 for (StringBuilder* current = this; current;
11133 current = current->mNext.get()) {
11134 uint32_t len = current->mUnits.Length();
11135 for (uint32_t i = 0; i < len; ++i) {
11136 Unit& u = current->mUnits[i];
11137 switch (u.mType) {
11138 case Unit::Type::Atom:
11139 appender.Append(*(u.mAtom));
11140 break;
11141 case Unit::Type::String:
11142 appender.Append(u.mString);
11143 break;
11144 case Unit::Type::StringWithEncode:
11145 if (simd) {
11146 EncodeAttrString<StringBuilderSIMD>(u.mString, appender);
11147 } else {
11148 EncodeAttrString<StringBuilderALU>(u.mString, appender);
11149 }
11150 break;
11151 case Unit::Type::Literal:
11152 appender.Append(u.mLiteral.AsSpan());
11153 break;
11154 case Unit::Type::TextFragment:
11155 if (u.mCharacterDataBuffer->Is2b()) {
11156 appender.Append(Span(u.mCharacterDataBuffer->Get2b(),
11157 u.mCharacterDataBuffer->GetLength()));
11158 } else {
11159 appender.Append(Span(u.mCharacterDataBuffer->Get1b(),
11160 u.mCharacterDataBuffer->GetLength()));
11161 }
11162 break;
11163 case Unit::Type::TextFragmentWithEncode:
11164 if (u.mCharacterDataBuffer->Is2b()) {
11165 if (simd) {
11166 EncodeTextFragment<StringBuilderSIMD>(
11167 Span(u.mCharacterDataBuffer->Get2b(),
11168 u.mCharacterDataBuffer->GetLength()),
11169 appender);
11170
11171 } else {
11172 EncodeTextFragment<StringBuilderALU>(
11173 Span(u.mCharacterDataBuffer->Get2b(),
11174 u.mCharacterDataBuffer->GetLength()),
11175 appender);
11176 }
11177 } else {
11178 if (simd) {
11179 EncodeTextFragment<StringBuilderSIMD>(
11180 Span(u.mCharacterDataBuffer->Get1b(),
11181 u.mCharacterDataBuffer->GetLength()),
11182 appender);
11183
11184 } else {
11185 EncodeTextFragment<StringBuilderALU>(
11186 Span(u.mCharacterDataBuffer->Get1b(),
11187 u.mCharacterDataBuffer->GetLength()),
11188 appender);
11189 }
11190 }
11191 break;
11192 default:
11193 MOZ_CRASH("Unknown unit type?")do { do { } while (false); MOZ_ReportCrash("" "Unknown unit type?"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 11193); AnnotateMozCrashReason
("MOZ_CRASH(" "Unknown unit type?" ")"); do { MOZ_CrashSequence
(__null, 11193); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
11194 }
11195 }
11196 }
11197 appender.Finish();
11198 return true;
11199 }
11200
11201 private:
11202 Unit* AddUnit() {
11203 if (mLast->mUnits.Length() == STRING_BUFFER_UNITS) {
11204 new StringBuilder(this);
11205 }
11206 return mLast->mUnits.AppendElement();
11207 }
11208
11209 explicit StringBuilder(StringBuilder* aFirst) : mLast(nullptr), mLength(0) {
11210 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)
;
11211 aFirst->mLast->mNext = WrapUnique(this);
11212 aFirst->mLast = this;
11213 }
11214
11215 template <class S>
11216 void EncodeAttrString(Span<const char16_t> aStr, BulkAppender& aAppender) {
11217 size_t flushedUntil = 0;
11218 size_t currentPosition = 0;
11219 const char16_t* ptr = aStr.Elements();
11220 const char16_t* end = ptr + aStr.Length();
11221
11222 // continue by label (committee proposal P3568) isn't in C++, yet, so
11223 // goto is used for what's logically continuing an outer loop.
11224 //
11225 // The purpose of two loop levels is to efficiently stay in the inner
11226 // loop when there isn't a full SIMD stride left.
11227 //
11228 // Strange indent thanks to clang-format.
11229 outer:
11230 // Check for having at least a SIMD stride of data to avoid useless
11231 // non-inline function calls when there isn't a full stride left.
11232 // This should become unnecessary if it turns out to be feasible
11233 // to inline the call without triggering
11234 // https://github.com/llvm/llvm-project/issues/160886 .
11235 if (S::SIMD && (end - ptr >= 16)) {
11236 // Need to check ifdef inside here in order to make even non-opt
11237 // build consider `S::SIMD` used.
11238#ifdef MOZ_MAY_HAVE_HTMLACCEL1
11239 size_t skipped =
11240 mozilla::htmlaccel::SkipNonEscapedInAttributeValue(ptr, end);
11241 ptr += skipped;
11242 currentPosition += skipped;
11243#endif
11244 }
11245 while (ptr != end) {
11246 char16_t c = *ptr;
11247 ptr++;
11248 switch (c) {
11249 case '"':
11250 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11251 aAppender.AppendLiteral(u"&quot;");
11252 currentPosition++;
11253 flushedUntil = currentPosition;
11254 goto outer;
11255 case '&':
11256 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11257 aAppender.AppendLiteral(u"&amp;");
11258 currentPosition++;
11259 flushedUntil = currentPosition;
11260 goto outer;
11261 case 0x00A0:
11262 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11263 aAppender.AppendLiteral(u"&nbsp;");
11264 currentPosition++;
11265 flushedUntil = currentPosition;
11266 goto outer;
11267 case '<':
11268 if (StaticPrefs::dom_security_html_serialization_escape_lt_gt()) {
11269 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11270 aAppender.AppendLiteral(u"&lt;");
11271 currentPosition++;
11272 flushedUntil = currentPosition;
11273 } else {
11274 currentPosition++;
11275 }
11276 goto outer;
11277 case '>':
11278 if (StaticPrefs::dom_security_html_serialization_escape_lt_gt()) {
11279 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11280 aAppender.AppendLiteral(u"&gt;");
11281 currentPosition++;
11282 flushedUntil = currentPosition;
11283 } else {
11284 currentPosition++;
11285 }
11286 goto outer;
11287 default:
11288 currentPosition++;
11289 continue;
11290 }
11291 }
11292 // Logically the outer loop ends here.
11293 if (currentPosition > flushedUntil) {
11294 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11295 }
11296 }
11297
11298 template <class S, class T>
11299 void EncodeTextFragment(Span<const T> aStr, BulkAppender& aAppender) {
11300 size_t flushedUntil = 0;
11301 size_t currentPosition = 0;
11302 const T* ptr = aStr.Elements();
11303 const T* end = ptr + aStr.Length();
11304
11305 // continue by label (committee proposal P3568) isn't in C++, yet, so
11306 // goto is used for what's logically continuing an outer loop.
11307 //
11308 // The purpose of two loop levels is to efficiently stay in the inner
11309 // loop when there isn't a full SIMD stride left.
11310 //
11311 // Strange indent thanks to clang-format.
11312 outer:
11313 // Check for having at least a SIMD stride of data to avoid useless
11314 // non-inline function calls when there isn't a full stride left.
11315 // This should become unnecessary if it turns out to be feasible
11316 // to inline the call without triggering
11317 // https://github.com/llvm/llvm-project/issues/160886 .
11318 if (S::SIMD && (end - ptr >= 16)) {
11319 // Need to check ifdef inside here in order to make even non-opt
11320 // build consider `S::SIMD` used.
11321#ifdef MOZ_MAY_HAVE_HTMLACCEL1
11322 size_t skipped = mozilla::htmlaccel::SkipNonEscapedInTextNode(ptr, end);
11323 ptr += skipped;
11324 currentPosition += skipped;
11325#endif
11326 }
11327 while (ptr != end) {
11328 T c = *ptr;
11329 ++ptr;
11330 switch (c) {
11331 case '<':
11332 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11333 aAppender.AppendLiteral(u"&lt;");
11334 currentPosition++;
11335 flushedUntil = currentPosition;
11336 goto outer;
11337 case '>':
11338 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11339 aAppender.AppendLiteral(u"&gt;");
11340 currentPosition++;
11341 flushedUntil = currentPosition;
11342 goto outer;
11343 case '&':
11344 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11345 aAppender.AppendLiteral(u"&amp;");
11346 currentPosition++;
11347 flushedUntil = currentPosition;
11348 goto outer;
11349 case T(0xA0):
11350 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11351 aAppender.AppendLiteral(u"&nbsp;");
11352 currentPosition++;
11353 flushedUntil = currentPosition;
11354 goto outer;
11355 default:
11356 currentPosition++;
11357 continue;
11358 }
11359 }
11360 // Logically the outer loop ends here.
11361 if (currentPosition > flushedUntil) {
11362 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11363 }
11364 }
11365
11366 AutoTArray<Unit, STRING_BUFFER_UNITS> mUnits;
11367 UniquePtr<StringBuilder> mNext;
11368 StringBuilder* mLast;
11369 // mLength is used only in the first StringBuilder object in the linked
11370 // list.
11371 CheckedInt<uint32_t> mLength;
11372};
11373
11374static_assert(sizeof(StringBuilder) <= StringBuilder::TARGET_SIZE,
11375 "StringBuilder should fit in the target bucket");
11376
11377} // namespace
11378
11379static void AppendEncodedCharacters(const CharacterDataBuffer* aText,
11380 StringBuilder& aBuilder) {
11381 uint32_t numEncodedChars = 0;
11382 uint32_t len = aText->GetLength();
11383 if (aText->Is2b()) {
11384 const char16_t* data = aText->Get2b();
11385#ifdef MOZ_MAY_HAVE_HTMLACCEL1
11386 if (mozilla::htmlaccel::htmlaccelEnabled()) {
11387 numEncodedChars =
11388 mozilla::htmlaccel::CountEscapedInTextNode(data, data + len);
11389 } else
11390#endif
11391 {
11392 for (uint32_t i = 0; i < len; ++i) {
11393 const char16_t c = data[i];
11394 switch (c) {
11395 case '<':
11396 case '>':
11397 case '&':
11398 case 0x00A0:
11399 ++numEncodedChars;
11400 break;
11401 default:
11402 break;
11403 }
11404 }
11405 }
11406 } else {
11407 const char* data = aText->Get1b();
11408#ifdef MOZ_MAY_HAVE_HTMLACCEL1
11409 if (mozilla::htmlaccel::htmlaccelEnabled()) {
11410 numEncodedChars =
11411 mozilla::htmlaccel::CountEscapedInTextNode(data, data + len);
11412 } else
11413#endif
11414 {
11415 for (uint32_t i = 0; i < len; ++i) {
11416 const unsigned char c = data[i];
11417 switch (c) {
11418 case '<':
11419 case '>':
11420 case '&':
11421 case 0x00A0:
11422 ++numEncodedChars;
11423 break;
11424 default:
11425 break;
11426 }
11427 }
11428 }
11429 }
11430
11431 if (numEncodedChars) {
11432 // For simplicity, conservatively estimate the size of the string after
11433 // encoding. This will result in reserving more memory than we actually
11434 // need, but that should be fine unless the string has an enormous number
11435 // of eg < in it. We subtract 1 for the null terminator, then 1 more for
11436 // the existing character that will be replaced.
11437 constexpr uint32_t maxCharExtraSpace =
11438 std::max({std::size("&lt;"), std::size("&gt;"), std::size("&amp;"),
11439 std::size("&nbsp;")}) -
11440 2;
11441 static_assert(maxCharExtraSpace < 100, "Possible underflow");
11442 CheckedInt<uint32_t> maxExtraSpace =
11443 CheckedInt<uint32_t>(numEncodedChars) * maxCharExtraSpace;
11444 aBuilder.AppendWithEncode(aText, maxExtraSpace + len);
11445 } else {
11446 aBuilder.Append(aText);
11447 }
11448}
11449
11450static CheckedInt<uint32_t> ExtraSpaceNeededForAttrEncoding(
11451 const nsAString& aValue) {
11452 const char16_t* c = aValue.BeginReading();
11453 const char16_t* end = aValue.EndReading();
11454
11455 uint32_t numEncodedChars = 0;
11456#ifdef MOZ_MAY_HAVE_HTMLACCEL1
11457 if (mozilla::htmlaccel::htmlaccelEnabled()) {
11458 numEncodedChars = mozilla::htmlaccel::CountEscapedInAttributeValue(c, end);
11459 } else
11460#endif
11461 {
11462 while (c < end) {
11463 switch (*c) {
11464 case '"':
11465 case '&':
11466 case 0x00A0: // NO-BREAK SPACE
11467 case '<':
11468 case '>':
11469 ++numEncodedChars;
11470 break;
11471 default:
11472 break;
11473 }
11474 ++c;
11475 }
11476 }
11477
11478 if (!numEncodedChars) {
11479 return 0;
11480 }
11481
11482 // For simplicity, conservatively estimate the size of the string after
11483 // encoding. This will result in reserving more memory than we actually
11484 // need, but that should be fine unless the string has an enormous number of
11485 // & in it. We subtract 1 for the null terminator, then 1 more for the
11486 // existing character that will be replaced.
11487 constexpr uint32_t maxCharExtraSpace =
11488 std::max({std::size("&quot;"), std::size("&amp;"), std::size("&nbsp;"),
11489 std::size("&lt;"), std::size("&gt;")}) -
11490 2;
11491 static_assert(maxCharExtraSpace < 100, "Possible underflow");
11492 return CheckedInt<uint32_t>(numEncodedChars) * maxCharExtraSpace;
11493}
11494
11495static void AppendEncodedAtomAttributeValue(nsAtom* aAtom,
11496 StringBuilder& aBuilder) {
11497 nsDependentAtomString atomStr(aAtom);
11498 auto space = ExtraSpaceNeededForAttrEncoding(atomStr);
11499 if (space.isValid() && !space.value()) {
11500 aBuilder.Append(aAtom);
11501 } else {
11502 aBuilder.AppendWithAttrEncode(nsString(atomStr), space + atomStr.Length());
11503 }
11504}
11505
11506static void AppendEncodedAttributeValue(const nsAttrValue& aValue,
11507 StringBuilder& aBuilder) {
11508 if (nsAtom* atom = aValue.GetStoredAtom()) {
11509 AppendEncodedAtomAttributeValue(atom, aBuilder);
11510 return;
11511 }
11512
11513 // NOTE(emilio): In most cases this will just be a reference to the stored
11514 // nsStringBuffer.
11515 nsString str;
11516 aValue.ToString(str);
11517 auto space = ExtraSpaceNeededForAttrEncoding(str);
11518 if (!space.isValid() || space.value()) {
11519 aBuilder.AppendWithAttrEncode(std::move(str), space + str.Length());
11520 } else {
11521 aBuilder.Append(std::move(str));
11522 }
11523}
11524
11525static void StartElement(Element* aElement, StringBuilder& aBuilder) {
11526 nsAtom* localName = aElement->NodeInfo()->NameAtom();
11527 const int32_t tagNS = aElement->GetNameSpaceID();
11528
11529 aBuilder.Append(u"<");
11530 if (tagNS == kNameSpaceID_XHTML3 || tagNS == kNameSpaceID_SVG9 ||
11531 tagNS == kNameSpaceID_MathML6) {
11532 aBuilder.Append(localName);
11533 } else {
11534 aBuilder.Append(nsString(aElement->NodeName()));
11535 }
11536
11537 if (CustomElementData* ceData = aElement->GetCustomElementData()) {
11538 nsAtom* isAttr = ceData->GetIs(aElement);
11539 if (isAttr && !aElement->HasAttr(nsGkAtoms::is)) {
11540 aBuilder.Append(uR"( is=")");
11541 AppendEncodedAtomAttributeValue(isAttr, aBuilder);
11542 aBuilder.Append(uR"(")");
11543 }
11544 }
11545
11546 uint32_t i = 0;
11547 while (BorrowedAttrInfo info = aElement->GetAttrInfoAt(i++)) {
11548 const nsAttrName* name = info.mName;
11549
11550 int32_t attNs = name->NamespaceID();
11551 nsAtom* attName = name->LocalName();
11552
11553 // Filter out any attribute starting with [-|_]moz
11554 // FIXME(emilio): Do we still need this?
11555 nsDependentAtomString attrNameStr(attName);
11556 if (StringBeginsWith(attrNameStr, u"_moz"_ns) ||
11557 StringBeginsWith(attrNameStr, u"-moz"_ns)) {
11558 continue;
11559 }
11560
11561 aBuilder.Append(u" ");
11562
11563 if (MOZ_LIKELY(attNs == kNameSpaceID_None)(__builtin_expect(!!(attNs == kNameSpaceID_None), 1)) ||
11564 (attNs == kNameSpaceID_XMLNS1 && attName == nsGkAtoms::xmlns)) {
11565 // Nothing else required
11566 } else if (attNs == kNameSpaceID_XML2) {
11567 aBuilder.Append(u"xml:");
11568 } else if (attNs == kNameSpaceID_XMLNS1) {
11569 aBuilder.Append(u"xmlns:");
11570 } else if (attNs == kNameSpaceID_XLink4) {
11571 aBuilder.Append(u"xlink:");
11572 } else if (nsAtom* prefix = name->GetPrefix()) {
11573 aBuilder.Append(prefix);
11574 aBuilder.Append(u":");
11575 }
11576
11577 aBuilder.Append(attName);
11578 aBuilder.Append(uR"(=")");
11579 AppendEncodedAttributeValue(*info.mValue, aBuilder);
11580 aBuilder.Append(uR"(")");
11581 }
11582
11583 aBuilder.Append(u">");
11584
11585 /*
11586 // Per HTML spec we should append one \n if the first child of
11587 // pre/textarea/listing is a textnode and starts with a \n.
11588 // But because browsers haven't traditionally had that behavior,
11589 // we're not changing our behavior either - yet.
11590 if (aContent->IsHTMLElement()) {
11591 if (localName == nsGkAtoms::pre || localName == nsGkAtoms::textarea ||
11592 localName == nsGkAtoms::listing) {
11593 nsIContent* fc = aContent->GetFirstChild();
11594 if (fc &&
11595 (fc->NodeType() == nsINode::TEXT_NODE ||
11596 fc->NodeType() == nsINode::CDATA_SECTION_NODE)) {
11597 const CharacterDataBuffer* text = fc->GetText();
11598 if (text && text->GetLength() && text->CharAt(0) == char16_t('\n')) {
11599 aBuilder.Append("\n");
11600 }
11601 }
11602 }
11603 }*/
11604}
11605
11606static inline bool ShouldEscape(nsIContent* aParent) {
11607 if (!aParent || !aParent->IsHTMLElement()) {
11608 return true;
11609 }
11610
11611 static const nsAtom* nonEscapingElements[] = {
11612 nsGkAtoms::style, nsGkAtoms::script, nsGkAtoms::xmp,
11613 nsGkAtoms::iframe, nsGkAtoms::noembed, nsGkAtoms::noframes,
11614 nsGkAtoms::plaintext, nsGkAtoms::noscript};
11615 static mozilla::BitBloomFilter<12, nsAtom> sFilter;
11616 static bool sInitialized = false;
11617 if (!sInitialized) {
11618 sInitialized = true;
11619 for (auto& nonEscapingElement : nonEscapingElements) {
11620 sFilter.add(nonEscapingElement);
11621 }
11622 }
11623
11624 nsAtom* tag = aParent->NodeInfo()->NameAtom();
11625 if (sFilter.mightContain(tag)) {
11626 for (auto& nonEscapingElement : nonEscapingElements) {
11627 if (tag == nonEscapingElement) {
11628 if (MOZ_UNLIKELY(tag == nsGkAtoms::noscript)(__builtin_expect(!!(tag == nsGkAtoms::noscript), 0)) &&
11629 MOZ_UNLIKELY(!aParent->OwnerDoc()->IsScriptEnabled())(__builtin_expect(!!(!aParent->OwnerDoc()->IsScriptEnabled
()), 0))
) {
11630 return true;
11631 }
11632 return false;
11633 }
11634 }
11635 }
11636 return true;
11637}
11638
11639static inline bool IsVoidTag(Element* aElement) {
11640 if (!aElement->IsHTMLElement()) {
11641 return false;
11642 }
11643 return FragmentOrElement::IsHTMLVoid(aElement->NodeInfo()->NameAtom());
11644}
11645
11646static bool StartSerializingShadowDOM(
11647 nsINode* aNode, StringBuilder& aBuilder, bool aSerializableShadowRoots,
11648 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
11649 ShadowRoot* shadow = aNode->GetShadowRoot();
11650 if (!shadow || ((!aSerializableShadowRoots || !shadow->Serializable()) &&
11651 !aShadowRoots.Contains(shadow))) {
11652 return false;
11653 }
11654
11655 // https://html.spec.whatwg.org/#html-fragment-serialisation-algorithm
11656 // steps 4-12
11657
11658 // 4.2.1. Append "<template shadowrootmode="".
11659 aBuilder.Append(u"<template shadowrootmode=\"");
11660
11661 // 4.2.2. If shadow's mode is "open", then append "open". Otherwise, append
11662 // "closed".
11663 // 3. Append U+0022 (").
11664 if (shadow->IsClosed()) {
11665 aBuilder.Append(u"closed\"");
11666 } else {
11667 aBuilder.Append(u"open\"");
11668 }
11669
11670 // 4. If shadow's delegates focus is set, then append "
11671 // shadowrootdelegatesfocus=""".
11672 if (shadow->DelegatesFocus()) {
11673 aBuilder.Append(u" shadowrootdelegatesfocus=\"\"");
11674 }
11675
11676 // 5. If shadow's serializable is set, then append "
11677 // shadowrootserializable=""".
11678 if (shadow->Serializable()) {
11679 aBuilder.Append(u" shadowrootserializable=\"\"");
11680 }
11681
11682 // 6. If shadow's slot assignment is "manual", then append "
11683 // shadowrootslotassignment="manual"".
11684 if (StaticPrefs::dom_shadowdom_shadowRootSlotAssignment_enabled() &&
11685 shadow->SlotAssignment() == SlotAssignmentMode::Manual) {
11686 aBuilder.Append(u" shadowrootslotassignment=\"manual\"");
11687 }
11688
11689 // 7. If shadow's slot assignment is "manual", then append "
11690 // shadowrootslotassignment="manual"".
11691 if (shadow->Clonable()) {
11692 aBuilder.Append(u" shadowrootclonable=\"\"");
11693 }
11694
11695 auto isGlobalCustomElementRegistry = [](CustomElementRegistry* registry) {
11696 return registry && !registry->IsScoped();
11697 };
11698
11699 // 8. Let shouldAppendRegistryAttribute be the result of running these steps:
11700 const bool shouldAppendRegistryAttribute = [&]() {
11701 if (!StaticPrefs::dom_scoped_custom_element_registries_enabled()) {
11702 return false;
11703 }
11704
11705 // 8.1. Let documentRegistry be shadow's node document's custom element
11706 // registry.
11707 CustomElementRegistry* documentRegistry =
11708 shadow->OwnerDoc()->GetCustomElementRegistry();
11709 // 8.2. Let shadowRegistry be shadow's custom element registry.
11710 CustomElementRegistry* shadowRegistry = shadow->GetCustomElementRegistry();
11711
11712 // 8.3. If documentRegistry is null and shadowRegistry is null, then return
11713 // false.
11714 if (!documentRegistry && !shadowRegistry) {
11715 return false;
11716 }
11717 // 8.4. If documentRegistry is a global custom element registry and
11718 // shadowRegistry is a global custom element registry, then return
11719 // false.
11720 else if (isGlobalCustomElementRegistry(documentRegistry) &&
11721 isGlobalCustomElementRegistry(shadowRegistry)) {
11722 return false;
11723 }
11724
11725 // 8.5. Return true.
11726 return true;
11727 }();
11728
11729 // 9. If shouldAppendRegistryAttribute is true, then append "
11730 // shadowrootcustomelementregistry=""".
11731 if (shouldAppendRegistryAttribute) {
11732 aBuilder.Append(u" shadowrootcustomelementregistry=\"\"");
11733 }
11734
11735 // 10. Append U+003E (>).
11736 aBuilder.Append(u">");
11737
11738 // 11. Append the value of running the HTML fragment serialization algorithm
11739 // with shadow, serializableShadowRoots, and shadowRoots (thus recursing
11740 // into this algorithm for that element).
11741 // (Returning `true` tells the caller to continue).
11742 if (!shadow->HasChildren()) {
11743 // 12. Append "</template>".
11744 aBuilder.Append(u"</template>");
11745 return false;
11746 }
11747 return true;
11748}
11749
11750template <SerializeShadowRoots ShouldSerializeShadowRoots>
11751static void SerializeNodeToMarkupInternal(
11752 nsINode* aRoot, bool aDescendantsOnly, StringBuilder& aBuilder,
11753 bool aSerializableShadowRoots,
11754 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
11755 nsINode* current =
11756 aDescendantsOnly ? aRoot->GetFirstChildOfTemplateOrNode() : aRoot;
11757 if (!current) {
11758 return;
11759 }
11760
11761 nsIContent* next;
11762 while (true) {
11763 bool isVoid = false;
11764 switch (current->NodeType()) {
11765 case nsINode::ELEMENT_NODE: {
11766 Element* elem = current->AsElement();
11767 StartElement(elem, aBuilder);
11768
11769 if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
11770 if (StartSerializingShadowDOM(
11771 current, aBuilder, aSerializableShadowRoots, aShadowRoots)) {
11772 current = current->GetShadowRoot()->GetFirstChild();
11773 continue;
11774 }
11775 }
11776
11777 isVoid = IsVoidTag(elem);
11778 if (!isVoid && (next = current->GetFirstChildOfTemplateOrNode())) {
11779 current = next;
11780 continue;
11781 }
11782 break;
11783 }
11784
11785 case nsINode::TEXT_NODE:
11786 case nsINode::CDATA_SECTION_NODE: {
11787 const CharacterDataBuffer* characterDataBuffer =
11788 &current->AsText()->DataBuffer();
11789 nsIContent* parent = current->GetParent();
11790 if (ShouldEscape(parent)) {
11791 AppendEncodedCharacters(characterDataBuffer, aBuilder);
11792 } else {
11793 aBuilder.Append(characterDataBuffer);
11794 }
11795 break;
11796 }
11797
11798 case nsINode::COMMENT_NODE: {
11799 aBuilder.Append(u"<!--");
11800 aBuilder.Append(
11801 static_cast<nsIContent*>(current)->GetCharacterDataBuffer());
11802 aBuilder.Append(u"-->");
11803 break;
11804 }
11805
11806 case nsINode::DOCUMENT_TYPE_NODE: {
11807 aBuilder.Append(u"<!DOCTYPE ");
11808 aBuilder.Append(nsString(current->NodeName()));
11809 aBuilder.Append(u">");
11810 break;
11811 }
11812
11813 case nsINode::PROCESSING_INSTRUCTION_NODE: {
11814 aBuilder.Append(u"<?");
11815 aBuilder.Append(nsString(current->NodeName()));
11816 aBuilder.Append(u" ");
11817 aBuilder.Append(
11818 static_cast<nsIContent*>(current)->GetCharacterDataBuffer());
11819 aBuilder.Append(u">");
11820 break;
11821 }
11822 }
11823
11824 while (true) {
11825 if (!isVoid && current->NodeType() == nsINode::ELEMENT_NODE) {
11826 aBuilder.Append(u"</");
11827 nsIContent* elem = static_cast<nsIContent*>(current);
11828 if (elem->IsHTMLElement() || elem->IsSVGElement() ||
11829 elem->IsMathMLElement()) {
11830 aBuilder.Append(elem->NodeInfo()->NameAtom());
11831 } else {
11832 aBuilder.Append(nsString(current->NodeName()));
11833 }
11834 aBuilder.Append(u">");
11835 }
11836 isVoid = false;
11837
11838 if (current == aRoot) {
11839 return;
11840 }
11841
11842 if ((next = current->GetNextSibling())) {
11843 current = next;
11844 break;
11845 }
11846
11847 if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
11848 // If the current node is a shadow root, then we must go to its host.
11849 // Since shadow DOMs are serialized declaratively as template
11850 // elements, we serialize the end tag of the template before going
11851 // back to serializing the shadow host.
11852 if (current->IsShadowRoot()) {
11853 current = current->GetContainingShadowHost();
11854 aBuilder.Append(u"</template>");
11855
11856 if (current->HasChildren()) {
11857 current = current->GetFirstChildOfTemplateOrNode();
11858 break;
11859 }
11860 continue;
11861 }
11862 }
11863
11864 current = current->GetParentNode();
11865
11866 // Handle template element. If the parent is a template's content,
11867 // then adjust the parent to be the template element.
11868 if (current != aRoot &&
11869 current->NodeType() == nsINode::DOCUMENT_FRAGMENT_NODE) {
11870 DocumentFragment* frag = static_cast<DocumentFragment*>(current);
11871 nsIContent* fragHost = frag->GetHost();
11872 if (fragHost && fragHost->IsTemplateElement()) {
11873 current = fragHost;
11874 }
11875 }
11876
11877 if (aDescendantsOnly && current == aRoot) {
11878 return;
11879 }
11880 }
11881 }
11882}
11883
11884template <SerializeShadowRoots ShouldSerializeShadowRoots>
11885bool nsContentUtils::SerializeNodeToMarkup(
11886 nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
11887 bool aSerializableShadowRoots,
11888 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
11889 // If you pass in a DOCUMENT_NODE, you must pass aDescendentsOnly as true
11890 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", 11890); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aDescendantsOnly || aRoot->NodeType() != nsINode::DOCUMENT_NODE"
")"); do { MOZ_CrashSequence(__null, 11890); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11891
11892 StringBuilder builder;
11893 if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
11894 if (aDescendantsOnly &&
11895 StartSerializingShadowDOM(aRoot, builder, aSerializableShadowRoots,
11896 aShadowRoots)) {
11897 SerializeNodeToMarkupInternal<SerializeShadowRoots::Yes>(
11898 aRoot->GetShadowRoot(), true, builder, aSerializableShadowRoots,
11899 aShadowRoots);
11900 // The template tag is opened in StartSerializingShadowDOM, so we need
11901 // to close it here before serializing any children of aRoot.
11902 builder.Append(u"</template>");
11903 }
11904 }
11905
11906 SerializeNodeToMarkupInternal<ShouldSerializeShadowRoots>(
11907 aRoot, aDescendantsOnly, builder, aSerializableShadowRoots, aShadowRoots);
11908 return builder.ToString(aOut);
11909}
11910
11911template bool nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::No>(
11912 nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
11913 bool aSerializableShadowRoots,
11914 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots);
11915template bool nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::Yes>(
11916 nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
11917 bool aSerializableShadowRoots,
11918 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots);
11919
11920bool nsContentUtils::IsSpecificAboutPage(JSObject* aGlobal, const char* aUri) {
11921 // aUri must start with about: or this isn't the right function to be using.
11922 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"
, 11922); AnnotateMozCrashReason("MOZ_ASSERT" "(" "strncmp(aUri, \"about:\", 6) == 0"
")"); do { MOZ_CrashSequence(__null, 11922); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11923
11924 // Make sure the global is a window
11925 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", 11925); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "JS_IsGlobalObject(aGlobal)" ")"
); do { MOZ_CrashSequence(__null, 11925); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11926 nsGlobalWindowInner* win = xpc::WindowOrNull(aGlobal);
11927 if (!win) {
11928 return false;
11929 }
11930
11931 nsCOMPtr<nsIPrincipal> principal = win->GetPrincipal();
11932 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", 11932); return
false; } } while (false)
;
11933
11934 // First check the scheme to avoid getting long specs in the common case.
11935 if (!principal->SchemeIs("about")) {
11936 return false;
11937 }
11938
11939 nsAutoCString spec;
11940 principal->GetAsciiSpec(spec);
11941
11942 return spec.EqualsASCII(aUri);
11943}
11944
11945/* static */
11946nsIDocShell* nsContentUtils::GetDocShellForEventTarget(EventTarget* aTarget) {
11947 if (!aTarget) {
11948 return nullptr;
11949 }
11950
11951 nsCOMPtr<nsPIDOMWindowInner> innerWindow;
11952 if (nsCOMPtr<nsINode> node = nsINode::FromEventTarget(aTarget)) {
11953 bool ignore;
11954 innerWindow =
11955 do_QueryInterface(node->OwnerDoc()->GetScriptHandlingObject(ignore));
11956 } else if ((innerWindow = nsPIDOMWindowInner::FromEventTarget(aTarget))) {
11957 // Nothing else to do
11958 } else if (nsCOMPtr<DOMEventTargetHelper> helper =
11959 do_QueryInterface(aTarget)) {
11960 innerWindow = helper->GetOwnerWindow();
11961 }
11962
11963 if (innerWindow) {
11964 return innerWindow->GetDocShell();
11965 }
11966
11967 return nullptr;
11968}
11969
11970/*
11971 * Note: this function only relates to figuring out HTTPS state, which is an
11972 * input to the Secure Context algorithm. We are not actually implementing
11973 * any part of the Secure Context algorithm itself here.
11974 *
11975 * This is a bit of a hack. Ideally we'd propagate HTTPS state through
11976 * nsIChannel as described in the Fetch and HTML specs, but making channels
11977 * know about whether they should inherit HTTPS state, propagating information
11978 * about who the channel's "client" is, exposing GetHttpsState API on channels
11979 * and modifying the various cache implementations to store and retrieve HTTPS
11980 * state involves a huge amount of code (see bug 1220687). We avoid that for
11981 * now using this function.
11982 *
11983 * This function takes advantage of the observation that we can return true if
11984 * nsIContentSecurityManager::IsOriginPotentiallyTrustworthy returns true for
11985 * the document's origin (e.g. the origin has a scheme of 'https' or host
11986 * 'localhost' etc.). Since we generally propagate a creator document's
11987 * origin onto data:, blob:, etc. documents, this works for them too.
11988 *
11989 * The scenario where this observation breaks down is sandboxing without the
11990 * 'allow-same-origin' flag, since in this case a document is given a unique
11991 * origin (IsOriginPotentiallyTrustworthy would return false). We handle that
11992 * by using the origin that the document would have had had it not been
11993 * sandboxed.
11994 *
11995 * DEFICIENCIES: Note that this function uses nsIScriptSecurityManager's
11996 * getChannelResultPrincipalIfNotSandboxed, and that method's ignoring of
11997 * sandboxing is limited to the immediate sandbox. In the case that aDocument
11998 * should inherit its origin (e.g. data: URI) but its parent has ended up
11999 * with a unique origin due to sandboxing further up the parent chain we may
12000 * end up returning false when we would ideally return true (since we will
12001 * examine the parent's origin for 'https' and not finding it.) This means
12002 * that we may restrict the privileges of some pages unnecessarily in this
12003 * edge case.
12004 */
12005/* static */
12006bool nsContentUtils::HttpsStateIsModern(Document* aDocument) {
12007 if (!aDocument) {
12008 return false;
12009 }
12010
12011 nsCOMPtr<nsIPrincipal> principal = aDocument->NodePrincipal();
12012
12013 if (principal->IsSystemPrincipal()) {
12014 return true;
12015 }
12016
12017 // If aDocument is sandboxed, try and get the principal that it would have
12018 // been given had it not been sandboxed:
12019 if (principal->GetIsNullPrincipal() &&
12020 (aDocument->GetSandboxFlags() & SANDBOXED_ORIGIN)) {
12021 nsIChannel* channel = aDocument->GetChannel();
12022 if (channel) {
12023 nsCOMPtr<nsIScriptSecurityManager> ssm =
12024 nsContentUtils::GetSecurityManager();
12025 nsresult rv = ssm->GetChannelResultPrincipalIfNotSandboxed(
12026 channel, getter_AddRefs(principal));
12027 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12028 return false;
12029 }
12030 if (principal->IsSystemPrincipal()) {
12031 // If a document with the system principal is sandboxing a subdocument
12032 // that would normally inherit the embedding element's principal (e.g.
12033 // a srcdoc document) then the embedding document does not trust the
12034 // content that is written to the embedded document. Unlike when the
12035 // embedding document is https, in this case we have no indication as
12036 // to whether the embedded document's contents are delivered securely
12037 // or not, and the sandboxing would possibly indicate that they were
12038 // not. To play it safe we return false here. (See bug 1162772
12039 // comment 73-80.)
12040 return false;
12041 }
12042 }
12043 }
12044
12045 if (principal->GetIsNullPrincipal()) {
12046 return false;
12047 }
12048
12049 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", 12049); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "principal->GetIsContentPrincipal()" ")"
); do { MOZ_CrashSequence(__null, 12049); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12050
12051 return principal->GetIsOriginPotentiallyTrustworthy();
12052}
12053
12054/* static */
12055bool nsContentUtils::ComputeIsSecureContext(nsIChannel* aChannel) {
12056 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"
, 12056); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChannel" ")"
); do { MOZ_CrashSequence(__null, 12056); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12057
12058 nsCOMPtr<nsIScriptSecurityManager> ssm = nsContentUtils::GetSecurityManager();
12059 nsCOMPtr<nsIPrincipal> principal;
12060 nsresult rv = ssm->GetChannelResultPrincipalIfNotSandboxed(
12061 aChannel, getter_AddRefs(principal));
12062 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12063 return false;
12064 }
12065
12066 const RefPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
12067
12068 if (principal->IsSystemPrincipal()) {
12069 // If the load would've been sandboxed, treat this load as an untrusted
12070 // load, as system code considers sandboxed resources insecure.
12071 return !loadInfo->GetLoadingSandboxed();
12072 }
12073
12074 if (principal->GetIsNullPrincipal()) {
12075 return false;
12076 }
12077
12078 if (const RefPtr<WindowContext> windowContext =
12079 WindowContext::GetById(loadInfo->GetInnerWindowID())) {
12080 if (!windowContext->GetIsSecureContext()) {
12081 return false;
12082 }
12083 }
12084
12085 return principal->GetIsOriginPotentiallyTrustworthy();
12086}
12087
12088/* https://html.spec.whatwg.org/#concept-try-upgrade */
12089void nsContentUtils::TryToUpgradeElement(Element* aElement) {
12090 // 1. "Let definition be the result of looking up a custom element definition
12091 // given element's custom element registry, element's namespace, element's
12092 // local name, and element's is value."
12093 NodeInfo* nodeInfo = aElement->NodeInfo();
12094 RefPtr<nsAtom> typeAtom =
12095 aElement->GetCustomElementData()->GetCustomElementType();
12096
12097 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", 12097); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())"
")"); do { MOZ_CrashSequence(__null, 12097); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12098
12099 // When scoped custom element registries are enabled, look up the element's
12100 // own custom element registry (which may be a scoped registry, null, or the
12101 // document's global registry as fallback).
12102 CustomElementRegistry* registry = nullptr;
12103 if (StaticPrefs::dom_scoped_custom_element_registries_enabled()) {
12104 registry = aElement->GetCustomElementRegistry();
12105 if (!registry) {
12106 return;
12107 }
12108 }
12109
12110 CustomElementDefinition* definition = nullptr;
12111 if (registry) {
12112 definition = registry->LookupCustomElementDefinition(
12113 nodeInfo->NameAtom(), nodeInfo->NamespaceID(), typeAtom);
12114 } else {
12115 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", 12115); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!StaticPrefs::dom_scoped_custom_element_registries_enabled()"
")"); do { MOZ_CrashSequence(__null, 12115); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12116 definition = nsContentUtils::LookupCustomElementDefinition(
12117 nodeInfo->GetDocument(), nodeInfo->NameAtom(), nodeInfo->NamespaceID(),
12118 typeAtom);
12119 }
12120
12121 // 2. "If definition is not null, then enqueue a custom element upgrade
12122 // reaction given element and definition."
12123 if (definition) {
12124 nsContentUtils::EnqueueUpgradeReaction(aElement, definition);
12125 } else if (registry) {
12126 registry->RegisterUnresolvedElement(aElement, typeAtom);
12127 } else {
12128 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", 12128); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!StaticPrefs::dom_scoped_custom_element_registries_enabled()"
")"); do { MOZ_CrashSequence(__null, 12128); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12129 // XXX: Not in spec. Add an unresolved custom element that is a candidate
12130 // for upgrade when a custom element is connected to the document.
12131 nsContentUtils::RegisterUnresolvedElement(aElement, typeAtom);
12132 }
12133}
12134
12135MOZ_CAN_RUN_SCRIPT
12136static void DoCustomElementCreate(Element** aElement, JSContext* aCx,
12137 Document* aDoc, NodeInfo* aNodeInfo,
12138 CustomElementConstructor* aConstructor,
12139 ErrorResult& aRv, FromParser aFromParser) {
12140 JS::Rooted<JS::Value> constructResult(aCx);
12141 aConstructor->Construct(&constructResult, aRv, "Custom Element Create",
12142 CallbackFunction::eRethrowExceptions);
12143 if (aRv.Failed()) {
12144 return;
12145 }
12146
12147 RefPtr<Element> element;
12148 // constructResult is an ObjectValue because construction with a callback
12149 // always forms the return value from a JSObject.
12150 UNWRAP_OBJECT(Element, &constructResult, element)mozilla::dom::binding_detail::UnwrapObjectWithCrossOriginAsserts
< mozilla::dom::prototypes::id::Element, mozilla::dom::Element_Binding
::NativeType>(&constructResult, element)
;
12151 if (aNodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
12152 if (!element || !element->IsHTMLElement()) {
12153 aRv.ThrowTypeError<MSG_DOES_NOT_IMPLEMENT_INTERFACE>("\"this\"",
12154 "HTMLElement");
12155 return;
12156 }
12157 } else {
12158 if (!element || !element->IsXULElement()) {
12159 aRv.ThrowTypeError<MSG_DOES_NOT_IMPLEMENT_INTERFACE>("\"this\"",
12160 "XULElement");
12161 return;
12162 }
12163 }
12164
12165 nsAtom* localName = aNodeInfo->NameAtom();
12166
12167 if (aDoc != element->OwnerDoc() || element->GetParentNode() ||
12168 element->HasChildren() || element->GetAttrCount() ||
12169 element->NodeInfo()->NameAtom() != localName) {
12170 aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
12171 return;
12172 }
12173
12174 if (element->IsHTMLElement()) {
12175 static_cast<HTMLElement*>(&*element)->InhibitRestoration(
12176 !(aFromParser & FROM_PARSER_NETWORK));
12177 }
12178
12179 element.forget(aElement);
12180}
12181
12182/* https://dom.spec.whatwg.org/#concept-create-element */
12183nsresult nsContentUtils::NewXULOrHTMLElement(
12184 Element** aResult, mozilla::dom::NodeInfo* aNodeInfo,
12185 FromParser aFromParser, nsAtom* aIsAtom,
12186 mozilla::dom::CustomElementDefinition* aDefinition,
12187 Maybe<RefPtr<CustomElementRegistry>> aCustomElementRegistry) {
12188 RefPtr<mozilla::dom::NodeInfo> nodeInfo = aNodeInfo;
12189 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"
, 12191); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
") (" "Can only create XUL or XHTML elements." ")"); do { MOZ_CrashSequence
(__null, 12191); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1
Taking false branch
2
Loop condition is false. Exiting loop
12190 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"
, 12191); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
") (" "Can only create XUL or XHTML elements." ")"); do { MOZ_CrashSequence
(__null, 12191); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
12191 "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"
, 12191); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
") (" "Can only create XUL or XHTML elements." ")"); do { MOZ_CrashSequence
(__null, 12191); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12192
12193 nsAtom* name = nodeInfo->NameAtom();
12194 bool isCustomElementName = false;
12195 const Maybe<const nsHTMLTag>& tag = nodeInfo->HTMLTag();
12196 if (tag.isSome()) {
3
Assuming the condition is false
4
Taking false branch
12197 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"
, 12197); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3)"
")"); do { MOZ_CrashSequence(__null, 12197); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12198 isCustomElementName =
12199 (*tag == eHTMLTag_userdefined &&
12200 nsContentUtils::IsCustomElementName(name, kNameSpaceID_XHTML3));
12201 } else {
12202 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"
, 12202); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(8)"
")"); do { MOZ_CrashSequence(__null, 12202); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
5
Taking false branch
6
Loop condition is false. Exiting loop
12203 if (aIsAtom) {
7
Assuming 'aIsAtom' is null
8
Taking false branch
12204 // Make sure the customized built-in element to be constructed confirms
12205 // to our naming requirement, i.e. [is] must be a dashed name and
12206 // the tag name must not.
12207 // if so, set isCustomElementName to false to kick off all the logics
12208 // that pick up aIsAtom.
12209 if (nsContentUtils::IsNameWithDash(aIsAtom) &&
12210 !nsContentUtils::IsNameWithDash(name)) {
12211 isCustomElementName = false;
12212 } else {
12213 isCustomElementName =
12214 nsContentUtils::IsCustomElementName(name, kNameSpaceID_XUL8);
12215 }
12216 } else {
12217 isCustomElementName =
12218 nsContentUtils::IsCustomElementName(name, kNameSpaceID_XUL8);
12219 }
12220 }
12221
12222 nsAtom* tagAtom = nodeInfo->NameAtom();
12223 nsAtom* typeAtom = nullptr;
12224 bool isCustomElement = isCustomElementName
8.1
'isCustomElementName' is true
|| aIsAtom;
12225 if (isCustomElement
8.2
'isCustomElement' is true
) {
12226 typeAtom = isCustomElementName
9.1
'isCustomElementName' is true
? tagAtom : aIsAtom;
9
Taking true branch
10
'?' condition is true
12227 }
12228
12229 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"
, 12229); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isCustomElement"
")"); do { MOZ_CrashSequence(__null, 12229); __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
12230
12231 // 3. "Let definition be the result of looking up a custom element definition
12232 // given registry, namespace, localName, and is."
12233 RefPtr<CustomElementDefinition> definition = aDefinition;
12234 if (isCustomElement
15.1
'isCustomElement' is true
&& !definition) {
12235 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", 12235); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())"
")"); do { MOZ_CrashSequence(__null, 12235); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12236 // When a custom element registry is provided (e.g. from fragment parsing
12237 // with a scoped registry), use it for definition lookup.
12238 if (aCustomElementRegistry.isSome()) {
12239 if (RefPtr<CustomElementRegistry> registry =
12240 aCustomElementRegistry.value()) {
12241 definition = registry->LookupCustomElementDefinition(
12242 nodeInfo->NameAtom(), nodeInfo->NamespaceID(), typeAtom);
12243 }
12244 // If registry is explicitly null, definition stays null (no upgrade).
12245 } else {
12246 definition = nsContentUtils::LookupCustomElementDefinition(
12247 nodeInfo->GetDocument(), nodeInfo->NameAtom(),
12248 nodeInfo->NamespaceID(), typeAtom);
12249 }
12250 }
12251
12252 /*
12253 * Synchronous custom elements flag is determined by 3 places in spec,
12254 * 1) create an element for a token, the flag is determined by
12255 * "will execute script" which is not originally created
12256 * for the HTML fragment parsing algorithm.
12257 * 2) createElement and createElementNS, the flag is the same as
12258 * NOT_FROM_PARSER.
12259 * 3) clone a node, our implementation will not go into this function.
12260 * For the unset case which is non-synchronous only applied for
12261 * inner/outerHTML.
12262 */
12263 bool synchronousCustomElements =
12264 definition && aFromParser != dom::FROM_PARSER_FRAGMENT;
16
Assuming 'aFromParser' is not equal to FROM_PARSER_FRAGMENT
12265 auto setRegistryOnExit = MakeScopeExit([&]() {
12266 if (!*aResult ||
12267 !StaticPrefs::dom_scoped_custom_element_registries_enabled() ||
12268 synchronousCustomElements) {
12269 return;
12270 }
12271 if (aCustomElementRegistry.isSome()) {
12272 RefPtr<CustomElementRegistry> registry = aCustomElementRegistry.value();
12273 if (registry) {
12274 (*aResult)->SetCustomElementRegistry(registry);
12275 } else {
12276 (*aResult)->SetNullCustomElementRegistry();
12277 }
12278 } else {
12279 Document* doc = (*aResult)->OwnerDoc();
12280 if (CustomElementRegistry* globalRegistry =
12281 doc->GetEffectiveGlobalCustomElementRegistry()) {
12282 (*aResult)->SetCustomElementRegistry(globalRegistry);
12283 }
12284 }
12285 });
12286
12287 // It might be a problem that parser synchronously calls constructor, so
12288 // filed bug 1378079 to figure out what we should do for parser case.
12289 if (definition) {
17
Taking true branch
12290 // Per discussion in https://github.com/w3c/webcomponents/issues/635,
12291 // use entry global in those places that are called from JS APIs and use
12292 // the node document's global object if it is called from parser.
12293 nsIGlobalObject* global;
12294 if (aFromParser == dom::NOT_FROM_PARSER) {
18
Assuming 'aFromParser' is equal to NOT_FROM_PARSER
19
Taking true branch
12295 global = GetEntryGlobal();
12296
12297 // Documents created from the PrototypeDocumentSink always use
12298 // NOT_FROM_PARSER for non-XUL elements. We can get the global from the
12299 // document in that case.
12300 if (!global) {
20
Assuming 'global' is non-null
21
Taking false branch
12301 Document* doc = nodeInfo->GetDocument();
12302 if (doc && doc->LoadedFromPrototype()) {
12303 global = doc->GetScopeObject();
12304 }
12305 }
12306 } else {
12307 global = nodeInfo->GetDocument()->GetScopeObject();
12308 }
12309 if (!global
21.1
'global' is non-null
) {
22
Taking false branch
12310 // In browser chrome code, one may have access to a document which
12311 // doesn't have scope object anymore.
12312 return NS_ERROR_FAILURE;
12313 }
12314
12315 AutoAllowLegacyScriptExecution exemption;
12316 AutoEntryScript aes(global, "create custom elements");
12317 JSContext* cx = aes.cx();
12318 ErrorResult rv;
12319
12320 // 4. "If definition is non-null, and definition's name is not equal to its
12321 // local name (i.e., definition represents a customized built-in
12322 // element):"
12323 if (definition->IsCustomBuiltIn()) {
23
Taking true branch
12324 // 4.2. "Set result to the result of creating an element internal..."
12325 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
24
Taking false branch
12326 *aResult =
12327 CreateHTMLElement(*tag, nodeInfo.forget(), aFromParser).take();
12328 } else {
12329 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
25
Assigning value
12330 }
12331 (*aResult)->SetCustomElementData(MakeUnique<CustomElementData>(typeAtom));
26
Called C++ object pointer is null
12332 if (synchronousCustomElements) {
12333 // 4.3. "If synchronousCustomElements is true, then run this step while
12334 // catching any exceptions: Upgrade result using definition."
12335 CustomElementRegistry::Upgrade(*aResult, definition, rv);
12336 if (rv.MaybeSetPendingException(cx)) {
12337 aes.ReportException();
12338 }
12339 } else {
12340 // 4.4. "Otherwise, enqueue a custom element upgrade reaction given
12341 // result and definition."
12342 nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
12343 }
12344
12345 return NS_OK;
12346 }
12347
12348 // 5. "Otherwise, if definition is non-null:"
12349 // 5.1. "If synchronousCustomElements is true:"
12350 if (synchronousCustomElements) {
12351 {
12352 // 5.1.1. "Let C be definition's constructor."
12353 CustomElementConstructor* constructor = definition->mConstructor;
12354
12355 RefPtr<Document> doc = nodeInfo->GetDocument();
12356 DocGroup* docGroup = doc->GetDocGroup();
12357
12358 // XXX: https://github.com/whatwg/dom/pull/1494
12359 // 5.1.2. Let previousRegistry be the surrounding agent's active
12360 // custom element constructor map[C] with default null.
12361 // 5.1.3. Set the surrounding agent's active custom element constructor
12362 // map[C] to registry.
12363 Maybe<DocGroup::AutoActiveConstructorRegistry>
12364 activeConstructorRegistry;
12365 if (StaticPrefs::dom_scoped_custom_element_registries_enabled() &&
12366 constructor->CallableOrNull() && docGroup) {
12367 if (aCustomElementRegistry.isSome()) {
12368 activeConstructorRegistry.emplace(docGroup, constructor,
12369 aCustomElementRegistry.ref());
12370 } else {
12371 activeConstructorRegistry.emplace(
12372 docGroup, constructor,
12373 doc->GetEffectiveGlobalCustomElementRegistry());
12374 }
12375 }
12376
12377 // 5.1.4. "Run these steps while catching any exceptions:
12378 DoCustomElementCreate(aResult, cx, doc, nodeInfo,
12379 MOZ_KnownLive(definition->mConstructor)(definition->mConstructor), rv,
12380 aFromParser);
12381
12382 // 5.1.5. If previousRegistry is null, then remove the surrounding
12383 // agent's active custom element constructor map[C]. Otherwise,
12384 // set it back to previousRegistry.
12385 // 5.1.6. Otherwise, set the surrounding agent ’s active custom element
12386 // constructor map[C] to previousRegistry.
12387 // (Handled by `activeRegistry`'s destructor during scope exit).
12388 }
12389
12390 if (rv.MaybeSetPendingException(cx)) {
12391 // "If any of these steps threw an exception: ... Set result to the
12392 // result of creating an element internal given document,
12393 // HTMLUnknownElement..."
12394 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
12395 NS_IF_ADDREF(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget(),ns_if_addref(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget
(), aFromParser))
12396 aFromParser))ns_if_addref(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget
(), aFromParser))
;
12397 } else {
12398 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
12399 }
12400 (*aResult)->SetDefined(false);
12401 // Set the fallback element's registry even on failure.
12402 if (StaticPrefs::dom_scoped_custom_element_registries_enabled()) {
12403 if (aCustomElementRegistry.isSome()) {
12404 if (CustomElementRegistry* registry =
12405 aCustomElementRegistry.ref()) {
12406 (*aResult)->SetCustomElementRegistry(registry);
12407 } else {
12408 (*aResult)->SetNullCustomElementRegistry();
12409 }
12410 }
12411 }
12412 } else if (*aResult && nodeInfo->GetPrefixAtom()) {
12413 // 5.1.3.9. Set result's namespace prefix to prefix.
12414 (*aResult)->SetNamespacePrefix(nodeInfo->GetPrefixAtom());
12415 }
12416 return NS_OK;
12417 }
12418
12419 // 5.2. "Otherwise:"
12420 // 5.2.1. "Set result to the result of creating an element internal given
12421 // document, HTMLElement, localName..."
12422 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
12423 NS_IF_ADDREF(*aResult =ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
12424 NS_NewHTMLElement(nodeInfo.forget(), aFromParser))ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
;
12425 } else {
12426 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
12427 }
12428 (*aResult)->SetCustomElementData(
12429 MakeUnique<CustomElementData>(definition->mType));
12430 // 5.2.2. "Enqueue a custom element upgrade reaction given result and
12431 // definition."
12432 nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
12433 return NS_OK;
12434 }
12435
12436 // 6. "Otherwise:"
12437 // 6.1. "Let interface be the element interface for localName and namespace."
12438 // 6.2. "Set result to the result of creating an element internal..."
12439 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
12440 // Per the Custom Element specification, unknown tags that are valid
12441 // custom element names should be HTMLElement instead of
12442 // HTMLUnknownElement.
12443 if (isCustomElementName) {
12444 NS_IF_ADDREF(*aResult =ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
12445 NS_NewHTMLElement(nodeInfo.forget(), aFromParser))ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
;
12446 } else {
12447 *aResult = CreateHTMLElement(*tag, nodeInfo.forget(), aFromParser).take();
12448 }
12449 } else {
12450 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
12451 }
12452
12453 if (!*aResult) {
12454 return NS_ERROR_OUT_OF_MEMORY;
12455 }
12456
12457 // 6.3. "If namespace is the HTML namespace, and either localName is a valid
12458 // custom element name or is is non-null, then set result's custom
12459 // element state to "undefined"."
12460 if (isCustomElement) {
12461 (*aResult)->SetCustomElementData(MakeUnique<CustomElementData>(typeAtom));
12462 if (aCustomElementRegistry.isSome()) {
12463 // When an explicit custom element registry is provided, register for
12464 // upgrade on that registry (if non-null), not the document's.
12465 if (CustomElementRegistry* registry = aCustomElementRegistry.ref()) {
12466 registry->RegisterCallbackUpgradeElement(*aResult, typeAtom);
12467 }
12468 } else {
12469 nsContentUtils::RegisterCallbackUpgradeElement(*aResult, typeAtom);
12470 }
12471 }
12472
12473 // 7. "Return result."
12474 return NS_OK;
12475}
12476
12477// https://html.spec.whatwg.org/#look-up-a-custom-element-registry
12478Maybe<RefPtr<CustomElementRegistry>> nsContentUtils::GetCustomElementRegistry(
12479 nsINode* aNode) {
12480 if (!aNode || !StaticPrefs::dom_scoped_custom_element_registries_enabled()) {
12481 return Nothing();
12482 }
12483 // 1. If node is an Element object, then return node's custom element
12484 // registry.
12485 // 2. If node is a ShadowRoot object, then return node's custom element
12486 // registry.
12487 // 3. If node is a Document object, then return node's custom element
12488 // registry.
12489 // A node specifies its own registry only when its state is not Global (i.e.
12490 // scoped, or explicitly null). A Global-state node inherits the global
12491 // registry, which we report as Nothing() so callers can fall back to a
12492 // context registry when parsing into the node.
12493 CustomElementRegistryState state = CustomElementRegistryState::Global;
12494 if (aNode->IsElement()) {
12495 state = aNode->AsElement()->GetCustomElementRegistryState();
12496 } else if (ShadowRoot* shadowRoot = ShadowRoot::FromNode(aNode)) {
12497 state = shadowRoot->GetCustomElementRegistryState();
12498 } else if (aNode->IsDocument()) {
12499 if (!aNode->AsDocument()->HasScopedCustomElementRegistry()) {
12500 // 4. Return null (reported as Nothing(): inherit the global registry).
12501 return Nothing();
12502 }
12503 state = CustomElementRegistryState::Scoped;
12504 } else {
12505 // 4. Return null.
12506 return Nothing();
12507 }
12508 if (state == CustomElementRegistryState::Global) {
12509 return Nothing();
12510 }
12511 RefPtr<CustomElementRegistry> registry;
12512 if (aNode->IsElement()) {
12513 registry = aNode->AsElement()->GetCustomElementRegistry();
12514 } else if (ShadowRoot* shadowRoot = ShadowRoot::FromNode(aNode)) {
12515 registry = shadowRoot->GetCustomElementRegistry();
12516 } else {
12517 registry = aNode->AsDocument()->GetCustomElementRegistry();
12518 }
12519 return Some(std::move(registry));
12520}
12521
12522/* https://html.spec.whatwg.org/#look-up-a-custom-element-definition */
12523CustomElementDefinition* nsContentUtils::LookupCustomElementDefinition(
12524 DocumentOrShadowRoot* aDoc, nsAtom* aNameAtom, uint32_t aNameSpaceID,
12525 nsAtom* aTypeAtom) {
12526 // 2. If namespace is not the HTML namespace, then return null.
12527 if (aNameSpaceID != kNameSpaceID_XUL8 && aNameSpaceID != kNameSpaceID_XHTML3) {
12528 return nullptr;
12529 }
12530
12531 // 1. If registry is null, then return null.
12532 // TODO(keithamus): re-order for Scoped Registries
12533 RefPtr<CustomElementRegistry> registry = aDoc->GetCustomElementRegistry();
12534 if (!registry) {
12535 return nullptr;
12536 }
12537
12538 // XXX: Steps 3-5 performed by
12539 // CustomElementRegistry::LookupCustomElementDefinition:
12540 // 3. If registry's custom element definition set contains an item with name
12541 // and local name both equal to localName, then return that item.
12542 // 4. If registry's custom element definition set contains an item with name
12543 // equal to is and local name equal to localName, then return that item.
12544 // 5. Return null.
12545 return registry->LookupCustomElementDefinition(aNameAtom, aNameSpaceID,
12546 aTypeAtom);
12547}
12548
12549/* static */
12550void nsContentUtils::RegisterCallbackUpgradeElement(Element* aElement,
12551 nsAtom* aTypeName) {
12552 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"
, 12552); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 12552); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12553
12554 CustomElementRegistry* registry = aElement->GetCustomElementRegistry();
12555 if (registry) {
12556 registry->RegisterCallbackUpgradeElement(aElement, aTypeName);
12557 }
12558}
12559
12560/* static */
12561void nsContentUtils::RegisterUnresolvedElement(Element* aElement,
12562 nsAtom* aTypeName) {
12563 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"
, 12563); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 12563); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12564
12565 CustomElementRegistry* registry = aElement->GetCustomElementRegistry();
12566 if (registry) {
12567 registry->RegisterUnresolvedElement(aElement, aTypeName);
12568 }
12569}
12570
12571/* static */
12572void nsContentUtils::UnregisterUnresolvedElement(Element* aElement) {
12573 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"
, 12573); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 12573); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12574
12575 nsAtom* typeAtom = aElement->GetCustomElementData()->GetCustomElementType();
12576 CustomElementRegistry* registry = aElement->GetCustomElementRegistry();
12577 if (registry) {
12578 registry->UnregisterUnresolvedElement(aElement, typeAtom);
12579 }
12580}
12581
12582/* static */
12583void nsContentUtils::EnqueueUpgradeReaction(
12584 Element* aElement, CustomElementDefinition* aDefinition) {
12585 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"
, 12585); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 12585); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12586
12587 Document* doc = aElement->OwnerDoc();
12588
12589 // No DocGroup means no custom element reactions stack.
12590 if (!doc->GetDocGroup()) {
12591 return;
12592 }
12593
12594 CustomElementReactionsStack* stack =
12595 doc->GetDocGroup()->CustomElementReactionsStack();
12596 stack->EnqueueUpgradeReaction(aElement, aDefinition);
12597}
12598
12599/* static */
12600void nsContentUtils::EnqueueLifecycleCallback(
12601 ElementCallbackType aType, Element* aCustomElement,
12602 const LifecycleCallbackArgs& aArgs, CustomElementDefinition* aDefinition) {
12603 // No DocGroup means no custom element reactions stack.
12604 if (!aCustomElement->OwnerDoc()->GetDocGroup()) {
12605 return;
12606 }
12607
12608 CustomElementRegistry::EnqueueLifecycleCallback(aType, aCustomElement, aArgs,
12609 aDefinition);
12610}
12611
12612/* static */
12613CustomElementFormValue nsContentUtils::ConvertToCustomElementFormValue(
12614 const Nullable<OwningFileOrUSVStringOrFormData>& aState) {
12615 if (aState.IsNull()) {
12616 return void_t{};
12617 }
12618 const auto& state = aState.Value();
12619 if (state.IsFile()) {
12620 RefPtr<BlobImpl> impl = state.GetAsFile()->Impl();
12621 return {std::move(impl)};
12622 }
12623 if (state.IsUSVString()) {
12624 return state.GetAsUSVString();
12625 }
12626 return state.GetAsFormData()->ConvertToCustomElementFormValue();
12627}
12628
12629/* static */
12630Nullable<OwningFileOrUSVStringOrFormData>
12631nsContentUtils::ExtractFormAssociatedCustomElementValue(
12632 nsIGlobalObject* aGlobal,
12633 const mozilla::dom::CustomElementFormValue& aCEValue) {
12634 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"
, 12634); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aGlobal" ")"
); do { MOZ_CrashSequence(__null, 12634); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12635
12636 OwningFileOrUSVStringOrFormData value;
12637 switch (aCEValue.type()) {
12638 case CustomElementFormValue::TBlobImpl: {
12639 RefPtr<File> file = File::Create(aGlobal, aCEValue.get_BlobImpl());
12640 if (NS_WARN_IF(!file)NS_warn_if_impl(!file, "!file", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12640)
) {
12641 return {};
12642 }
12643 value.SetAsFile() = file;
12644 } break;
12645
12646 case CustomElementFormValue::TnsString:
12647 value.SetAsUSVString() = aCEValue.get_nsString();
12648 break;
12649
12650 case CustomElementFormValue::TArrayOfFormDataTuple: {
12651 const auto& array = aCEValue.get_ArrayOfFormDataTuple();
12652 auto formData = MakeRefPtr<FormData>();
12653
12654 for (auto i = 0ul; i < array.Length(); ++i) {
12655 const auto& item = array.ElementAt(i);
12656 switch (item.value().type()) {
12657 case IPCFormDataValue::TnsString:
12658 formData->AddNameValuePair(item.name(),
12659 item.value().get_nsString());
12660 break;
12661
12662 case IPCFormDataValue::TBlobImpl: {
12663 auto blobImpl = item.value().get_BlobImpl();
12664 RefPtr<Blob> blob = Blob::Create(aGlobal, blobImpl);
12665 formData->AddNameBlobPair(item.name(), blob);
12666 } break;
12667
12668 default:
12669 continue;
12670 }
12671 }
12672
12673 value.SetAsFormData() = formData;
12674 } break;
12675 case CustomElementFormValue::Tvoid_t:
12676 return {};
12677 default:
12678 NS_WARNING("Invalid CustomElementContentData type!")NS_DebugBreak(NS_DEBUG_WARNING, "Invalid CustomElementContentData type!"
, nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp",
12678)
;
12679 return {};
12680 }
12681 return value;
12682}
12683
12684/* static */
12685void nsContentUtils::AppendDocumentLevelNativeAnonymousContentTo(
12686 Document* aDocument, nsTArray<nsIContent*>& aElements) {
12687 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"
, 12687); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument"
")"); do { MOZ_CrashSequence(__null, 12687); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12688#ifdef DEBUG1
12689 size_t oldLength = aElements.Length();
12690#endif
12691
12692 if (PresShell* presShell = aDocument->GetPresShell()) {
12693 if (ScrollContainerFrame* rootScrollContainerFrame =
12694 presShell->GetRootScrollContainerFrame()) {
12695 rootScrollContainerFrame->AppendAnonymousContentTo(aElements, 0);
12696 }
12697 if (nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame()) {
12698 canvasFrame->AppendAnonymousContentTo(aElements, 0);
12699 }
12700 }
12701
12702 if (auto* el = aDocument->GetCustomContentContainer()) {
12703 aElements.AppendElement(el);
12704 }
12705
12706#ifdef DEBUG1
12707 for (size_t i = oldLength; i < aElements.Length(); i++) {
12708 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", 12710); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
") (" "Someone here has lied, or missed to flag the node" ")"
); do { MOZ_CrashSequence(__null, 12710); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
12709 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", 12710); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
") (" "Someone here has lied, or missed to flag the node" ")"
); do { MOZ_CrashSequence(__null, 12710); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
12710 "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", 12710); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
") (" "Someone here has lied, or missed to flag the node" ")"
); do { MOZ_CrashSequence(__null, 12710); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12711 }
12712#endif
12713}
12714
12715static void AppendNativeAnonymousChildrenFromFrame(nsIFrame* aFrame,
12716 nsTArray<nsIContent*>& aKids,
12717 uint32_t aFlags) {
12718 if (nsIAnonymousContentCreator* ac = do_QueryFrame(aFrame)) {
12719 ac->AppendAnonymousContentTo(aKids, aFlags);
12720 }
12721}
12722
12723/* static */
12724void nsContentUtils::AppendNativeAnonymousChildren(const nsIContent* aContent,
12725 nsTArray<nsIContent*>& aKids,
12726 uint32_t aFlags) {
12727 if (aContent->MayHaveAnonymousChildren()) {
12728 if (nsIFrame* primaryFrame = aContent->GetPrimaryFrame()) {
12729 // NAC created by the element's primary frame.
12730 AppendNativeAnonymousChildrenFromFrame(primaryFrame, aKids, aFlags);
12731
12732 // NAC created by any other non-primary frames for the element.
12733 AutoTArray<nsIFrame::OwnedAnonBox, 8> ownedAnonBoxes;
12734 primaryFrame->AppendOwnedAnonBoxes(ownedAnonBoxes);
12735 for (nsIFrame::OwnedAnonBox& box : ownedAnonBoxes) {
12736 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", 12736); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "box.mAnonBoxFrame->GetContent() == aContent"
")"); do { MOZ_CrashSequence(__null, 12736); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12737 AppendNativeAnonymousChildrenFromFrame(box.mAnonBoxFrame, aKids,
12738 aFlags);
12739 }
12740 }
12741
12742 // View transition pseudos.
12743 if (aContent->IsRootElement()) {
12744 if (auto* vt = aContent->OwnerDoc()->GetActiveViewTransition()) {
12745 if (auto* root = vt->GetSnapshotContainingBlock()) {
12746 aKids.AppendElement(root);
12747 }
12748 }
12749 }
12750
12751 // Get manually created NAC (editor resize handles, etc.).
12752 if (auto nac = static_cast<ManualNACArray*>(
12753 aContent->GetProperty(nsGkAtoms::manualNACProperty))) {
12754 aKids.AppendElements(*nac);
12755 }
12756 }
12757
12758 // The root scroll frame is not the primary frame of the root element.
12759 // Detect and handle this case.
12760 if (!(aFlags & nsIContent::eSkipDocumentLevelNativeAnonymousContent) &&
12761 aContent->IsRootElement()) {
12762 AppendDocumentLevelNativeAnonymousContentTo(aContent->OwnerDoc(), aKids);
12763 }
12764}
12765
12766bool nsContentUtils::IsImageAvailable(nsIContent* aLoadingNode, nsIURI* aURI,
12767 nsIPrincipal* aDefaultTriggeringPrincipal,
12768 CORSMode aCORSMode) {
12769 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
12770 QueryTriggeringPrincipal(aLoadingNode, aDefaultTriggeringPrincipal,
12771 getter_AddRefs(triggeringPrincipal));
12772 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", 12772); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "triggeringPrincipal" ")"); do { MOZ_CrashSequence
(__null, 12772); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12773
12774 Document* doc = aLoadingNode->OwnerDoc();
12775 return IsImageAvailable(aURI, triggeringPrincipal, aCORSMode, doc);
12776}
12777
12778bool nsContentUtils::IsImageAvailable(nsIURI* aURI,
12779 nsIPrincipal* aTriggeringPrincipal,
12780 CORSMode aCORSMode, Document* aDoc) {
12781 imgLoader* imgLoader = GetImgLoaderForDocument(aDoc);
12782 return imgLoader->IsImageAvailable(aURI, aTriggeringPrincipal, aCORSMode,
12783 aDoc);
12784}
12785
12786/* static */
12787bool nsContentUtils::QueryTriggeringPrincipal(
12788 nsIContent* aLoadingNode, nsIPrincipal* aDefaultPrincipal,
12789 nsIPrincipal** aTriggeringPrincipal) {
12790 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"
, 12790); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingNode"
")"); do { MOZ_CrashSequence(__null, 12790); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12791 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", 12791); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aTriggeringPrincipal" ")"); do { MOZ_CrashSequence
(__null, 12791); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12792
12793 bool result = false;
12794 nsCOMPtr<nsIPrincipal> loadingPrincipal = aDefaultPrincipal;
12795 if (!loadingPrincipal) {
12796 loadingPrincipal = aLoadingNode->NodePrincipal();
12797 }
12798
12799 // If aLoadingNode is content, bail out early.
12800 if (!aLoadingNode->NodePrincipal()->IsSystemPrincipal()) {
12801 loadingPrincipal.forget(aTriggeringPrincipal);
12802 return result;
12803 }
12804
12805 nsAutoString loadingStr;
12806 if (aLoadingNode->IsElement()) {
12807 aLoadingNode->AsElement()->GetAttr(
12808 kNameSpaceID_None, nsGkAtoms::triggeringprincipal, loadingStr);
12809 }
12810
12811 // Fall back if 'triggeringprincipal' isn't specified,
12812 if (loadingStr.IsEmpty()) {
12813 loadingPrincipal.forget(aTriggeringPrincipal);
12814 return result;
12815 }
12816
12817 nsCString binary;
12818 nsCOMPtr<nsIPrincipal> serializedPrin =
12819 BasePrincipal::FromJSON(NS_ConvertUTF16toUTF8(loadingStr));
12820 if (serializedPrin) {
12821 result = true;
12822 serializedPrin.forget(aTriggeringPrincipal);
12823 }
12824
12825 if (!result) {
12826 // Fallback if the deserialization is failed.
12827 loadingPrincipal.forget(aTriggeringPrincipal);
12828 }
12829
12830 return result;
12831}
12832
12833/* static */
12834void nsContentUtils::GetContentPolicyTypeForUIImageLoading(
12835 nsIContent* aLoadingNode, nsIPrincipal** aTriggeringPrincipal,
12836 nsContentPolicyType& aContentPolicyType, uint64_t* aRequestContextID) {
12837 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", 12837); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequestContextID" ")"); do { MOZ_CrashSequence
(__null, 12837); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12838
12839 bool result = QueryTriggeringPrincipal(aLoadingNode, aTriggeringPrincipal);
12840 if (result) {
12841 // Set the content policy type to TYPE_INTERNAL_IMAGE_FAVICON for
12842 // indicating it's a favicon loading.
12843 aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON;
12844
12845 nsAutoString requestContextID;
12846 if (aLoadingNode->IsElement()) {
12847 aLoadingNode->AsElement()->GetAttr(
12848 kNameSpaceID_None, nsGkAtoms::requestcontextid, requestContextID);
12849 }
12850 nsresult rv;
12851 int64_t val = requestContextID.ToInteger64(&rv);
12852 *aRequestContextID = NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) ? val : 0;
12853 } else {
12854 aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE;
12855 }
12856}
12857
12858/* static */
12859nsresult nsContentUtils::CreateJSValueFromSequenceOfObject(
12860 JSContext* aCx, const Sequence<JSObject*>& aTransfer,
12861 JS::MutableHandle<JS::Value> aValue) {
12862 if (aTransfer.IsEmpty()) {
12863 return NS_OK;
12864 }
12865
12866 JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, aTransfer.Length()));
12867 if (!array) {
12868 return NS_ERROR_OUT_OF_MEMORY;
12869 }
12870
12871 for (uint32_t i = 0; i < aTransfer.Length(); ++i) {
12872 JS::Rooted<JSObject*> object(aCx, aTransfer[i]);
12873 if (!object) {
12874 continue;
12875 }
12876
12877 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", 12878)
12878 !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", 12878)
) {
12879 return NS_ERROR_OUT_OF_MEMORY;
12880 }
12881 }
12882
12883 aValue.setObject(*array);
12884 return NS_OK;
12885}
12886
12887/* static */
12888void nsContentUtils::StructuredClone(JSContext* aCx, nsIGlobalObject* aGlobal,
12889 JS::Handle<JS::Value> aValue,
12890 const StructuredSerializeOptions& aOptions,
12891 JS::MutableHandle<JS::Value> aRetval,
12892 ErrorResult& aError) {
12893 JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
12894 aError = nsContentUtils::CreateJSValueFromSequenceOfObject(
12895 aCx, aOptions.mTransfer, &transferArray);
12896 if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12896)
) {
12897 return;
12898 }
12899
12900 JS::CloneDataPolicy clonePolicy;
12901 // We are definitely staying in the same agent cluster.
12902 clonePolicy.allowIntraClusterClonableSharedObjects();
12903 if (aGlobal->IsSharedMemoryAllowed()) {
12904 clonePolicy.allowSharedMemoryObjects();
12905 }
12906
12907 // 2.7.10 Structured cloning API
12908 // Step 1: Let serialized be
12909 // ? StructuredSerializeWithTransfer(value, options["transfer"])
12910 StructuredCloneHolder holder(StructuredCloneHolder::CloningSupported,
12911 StructuredCloneHolder::TransferringSupported,
12912 JS::StructuredCloneScope::SameProcess);
12913 holder.Write(aCx, aValue, transferArray, clonePolicy, aError);
12914 if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12914)
) {
12915 return;
12916 }
12917
12918 // Step 2: Let deserializeRecord be
12919 // ? StructuredDeserializeWithTransfer(serialized, this's relevant realm).
12920 JSAutoRealm ar(aCx, aGlobal->GetGlobalJSObject());
12921 holder.Read(aCx, aRetval, clonePolicy, aError);
12922 if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12922)
) {
12923 return;
12924 }
12925
12926 // Step 3: Return deserializeRecord.[[Deserialized]].
12927 // (discarding deserializeRecord.[[TransferredValues]])
12928 nsTArray<RefPtr<MessagePort>> ports = holder.TakeTransferredPorts();
12929 (void)ports;
12930}
12931
12932/* static */
12933bool nsContentUtils::ShouldBlockReservedKeys(WidgetKeyboardEvent* aKeyEvent) {
12934 nsCOMPtr<nsIPrincipal> principal;
12935 RefPtr<Element> targetElement =
12936 Element::FromEventTargetOrNull(aKeyEvent->mOriginalTarget);
12937 nsCOMPtr<nsIBrowser> targetBrowser;
12938 if (targetElement) {
12939 targetBrowser = targetElement->AsBrowser();
12940 }
12941 bool isRemoteBrowser = false;
12942 if (targetBrowser) {
12943 targetBrowser->GetIsRemoteBrowser(&isRemoteBrowser);
12944 }
12945
12946 if (isRemoteBrowser) {
12947 targetBrowser->GetContentPrincipal(getter_AddRefs(principal));
12948 return principal ? nsContentUtils::IsSitePermDeny(principal, "shortcuts"_ns)
12949 : false;
12950 }
12951
12952 if (targetElement) {
12953 Document* doc = targetElement->GetUncomposedDoc();
12954 if (doc) {
12955 RefPtr<WindowContext> wc = doc->GetWindowContext();
12956 if (wc) {
12957 return wc->TopWindowContext()->GetShortcutsPermission() ==
12958 nsIPermissionManager::DENY_ACTION;
12959 }
12960 }
12961 }
12962
12963 return false;
12964}
12965
12966/**
12967 * Checks whether the given type is a supported document type for
12968 * loading within the nsObjectLoadingContent specified by aContent.
12969 *
12970 * NOTE Helper method for nsContentUtils::HtmlObjectContentTypeForMIMEType.
12971 * NOTE Does not take content policy or capabilities into account
12972 */
12973static bool HtmlObjectContentSupportsDocument(const nsCString& aMimeType) {
12974 nsCOMPtr<nsIWebNavigationInfo> info(
12975 do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID"@mozilla.org/webnavigation-info;1"));
12976 if (!info) {
12977 return false;
12978 }
12979
12980 uint32_t supported;
12981 nsresult rv = info->IsTypeSupported(aMimeType, &supported);
12982
12983 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12984 return false;
12985 }
12986
12987 if (supported != nsIWebNavigationInfo::UNSUPPORTED) {
12988 return true;
12989 }
12990
12991 // Try a stream converter
12992 // NOTE: We treat any type we can convert from as a supported type. If a
12993 // type is not actually supported, the URI loader will detect that and
12994 // return an error, and we'll fallback.
12995 nsCOMPtr<nsIStreamConverterService> convServ =
12996 do_GetService("@mozilla.org/streamConverters;1");
12997 bool canConvert = false;
12998 if (convServ) {
12999 rv = convServ->CanConvert(aMimeType.get(), "*/*", &canConvert);
13000 }
13001 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && canConvert;
13002}
13003
13004/* static */
13005uint32_t nsContentUtils::HtmlObjectContentTypeForMIMEType(
13006 const nsCString& aMIMEType, bool aIsSandboxed) {
13007 if (aMIMEType.IsEmpty()) {
13008 return nsIObjectLoadingContent::TYPE_FALLBACK;
13009 }
13010
13011 if (imgLoader::SupportImageWithMimeType(aMIMEType)) {
13012 return nsIObjectLoadingContent::TYPE_DOCUMENT;
13013 }
13014
13015 // Faking support of the PDF content as a document for EMBED tags when the
13016 // internal PDF viewer or the embedded PDF fallback is enabled.
13017 if (aMIMEType.LowerCaseEqualsLiteral(APPLICATION_PDF"application/pdf") &&
13018 (IsPDFJSEnabled() || StaticPrefs::pdfjs_embedFallback())) {
13019 // Sandboxed iframes are just never allowed to display plugins. In the
13020 // modern world, this just means "application/pdf".
13021 return aIsSandboxed ? nsIObjectLoadingContent::TYPE_FALLBACK
13022 : nsIObjectLoadingContent::TYPE_DOCUMENT;
13023 }
13024
13025 if (HtmlObjectContentSupportsDocument(aMIMEType)) {
13026 return nsIObjectLoadingContent::TYPE_DOCUMENT;
13027 }
13028
13029 return nsIObjectLoadingContent::TYPE_FALLBACK;
13030}
13031
13032/* static */
13033bool nsContentUtils::IsLocalRefURL(const nsAString& aString) {
13034 return !aString.IsEmpty() && aString[0] == '#';
13035}
13036
13037// We use only 53 bits for the ID so that it can be converted to and from a JS
13038// value without loss of precision. The upper bits of the ID hold the process
13039// ID. The lower bits identify the object itself.
13040static constexpr uint64_t kIdTotalBits = 53;
13041static constexpr uint64_t kIdProcessBits = 22;
13042static constexpr uint64_t kIdBits = kIdTotalBits - kIdProcessBits;
13043
13044/* static */
13045uint64_t nsContentUtils::GenerateProcessSpecificId(uint64_t aId) {
13046 uint64_t processId = XRE_GetChildID();
13047
13048 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"
, 13048); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "processId < (uint64_t(1) << kIdProcessBits)"
")"); do { MOZ_CrashSequence(__null, 13048); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13049 uint64_t processBits = processId & ((uint64_t(1) << kIdProcessBits) - 1);
13050
13051 uint64_t id = aId;
13052 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", 13052); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "id < (uint64_t(1) << kIdBits)"
")"); do { MOZ_CrashSequence(__null, 13052); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13053 uint64_t bits = id & ((uint64_t(1) << kIdBits) - 1);
13054
13055 return (processBits << kIdBits) | bits;
13056}
13057
13058/* static */
13059std::tuple<GeckoChildID, uint64_t> nsContentUtils::SplitProcessSpecificId(
13060 uint64_t aId) {
13061 return {GeckoChildID(aId >> kIdBits), aId & ((uint64_t(1) << kIdBits) - 1)};
13062}
13063
13064/* static */
13065bool nsContentUtils::IsProcessSpecificIdFrom(uint64_t aId,
13066 GeckoChildID aChildID) {
13067 return (aId >> kIdBits) == static_cast<uint64_t>(aChildID);
13068}
13069
13070// Next process-local Tab ID.
13071static uint64_t gNextTabId = 0;
13072
13073/* static */
13074uint64_t nsContentUtils::GenerateTabId() {
13075 return GenerateProcessSpecificId(++gNextTabId);
13076}
13077
13078// Next process-local Browser ID.
13079static uint64_t gNextBrowserId = 0;
13080
13081/* static */
13082uint64_t nsContentUtils::GenerateBrowserId() {
13083 return GenerateProcessSpecificId(++gNextBrowserId);
13084}
13085
13086// Next process-local Browsing Context ID.
13087static uint64_t gNextBrowsingContextId = 0;
13088
13089/* static */
13090uint64_t nsContentUtils::GenerateBrowsingContextId() {
13091 return GenerateProcessSpecificId(++gNextBrowsingContextId);
13092}
13093
13094// Next process-local Window ID.
13095static uint64_t gNextWindowId = 0;
13096
13097/* static */
13098uint64_t nsContentUtils::GenerateWindowId() {
13099 return GenerateProcessSpecificId(++gNextWindowId);
13100}
13101
13102// Next process-local load.
13103static Atomic<uint64_t> gNextLoadIdentifier(0);
13104
13105/* static */
13106uint64_t nsContentUtils::GenerateLoadIdentifier() {
13107 return GenerateProcessSpecificId(++gNextLoadIdentifier);
13108}
13109
13110/* static */
13111bool nsContentUtils::GetUserIsInteracting() {
13112 return UserInteractionObserver::sUserActive;
13113}
13114
13115/* static */
13116bool nsContentUtils::GetSourceMapURL(nsIHttpChannel* aChannel,
13117 nsACString& aResult) {
13118 nsresult rv = aChannel->GetResponseHeader("SourceMap"_ns, aResult);
13119 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
13120 rv = aChannel->GetResponseHeader("X-SourceMap"_ns, aResult);
13121 }
13122 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)));
13123}
13124
13125/* static */
13126bool nsContentUtils::IsMessageInputEvent(const IPC::Message& aMsg) {
13127 if ((aMsg.type() & mozilla::dom::PBrowser::PBrowserStart) ==
13128 mozilla::dom::PBrowser::PBrowserStart) {
13129 switch (aMsg.type()) {
13130 case mozilla::dom::PBrowser::Msg_RealMouseMoveEvent__ID:
13131 case mozilla::dom::PBrowser::Msg_RealMouseButtonEvent__ID:
13132 case mozilla::dom::PBrowser::Msg_RealMouseEnterExitWidgetEvent__ID:
13133 case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID:
13134 case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID:
13135 case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID:
13136 case mozilla::dom::PBrowser::Msg_RealTouchMoveEvent__ID:
13137 case mozilla::dom::PBrowser::Msg_RealDragEvent__ID:
13138 case mozilla::dom::PBrowser::Msg_UpdateDimensions__ID:
13139 return true;
13140 }
13141 }
13142 return false;
13143}
13144
13145/* static */
13146bool nsContentUtils::IsMessageCriticalInputEvent(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_RealMouseButtonEvent__ID:
13151 case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID:
13152 case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID:
13153 case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID:
13154 case mozilla::dom::PBrowser::Msg_RealDragEvent__ID:
13155 return true;
13156 }
13157 }
13158 return false;
13159}
13160
13161static const char* kUserInteractionInactive = "user-interaction-inactive";
13162static const char* kUserInteractionActive = "user-interaction-active";
13163
13164void nsContentUtils::UserInteractionObserver::Init() {
13165 // Listen for the observer messages from EventStateManager which are telling
13166 // us whether or not the user is interacting.
13167 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
13168 obs->AddObserver(this, kUserInteractionInactive, false);
13169 obs->AddObserver(this, kUserInteractionActive, false);
13170
13171 // We can't register ourselves as an annotator yet, as the
13172 // BackgroundHangMonitor hasn't started yet. It will have started by the
13173 // time we have the chance to spin the event loop.
13174 RefPtr<UserInteractionObserver> self = this;
13175 NS_DispatchToMainThread(NS_NewRunnableFunction(
13176 "nsContentUtils::UserInteractionObserver::Init",
13177 [=]() { BackgroundHangMonitor::RegisterAnnotator(*self); }));
13178}
13179
13180void nsContentUtils::UserInteractionObserver::Shutdown() {
13181 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
13182 if (obs) {
13183 obs->RemoveObserver(this, kUserInteractionInactive);
13184 obs->RemoveObserver(this, kUserInteractionActive);
13185 }
13186
13187 BackgroundHangMonitor::UnregisterAnnotator(*this);
13188}
13189
13190/**
13191 * NB: This function is always called by the BackgroundHangMonitor thread.
13192 * Plan accordingly
13193 */
13194void nsContentUtils::UserInteractionObserver::AnnotateHang(
13195 BackgroundHangAnnotations& aAnnotations) {
13196 // NOTE: Only annotate the hang report if the user is known to be interacting.
13197 if (sUserActive) {
13198 aAnnotations.AddAnnotation(u"UserInteracting"_ns, true);
13199 }
13200}
13201
13202NS_IMETHODIMPnsresult
13203nsContentUtils::UserInteractionObserver::Observe(nsISupports* aSubject,
13204 const char* aTopic,
13205 const char16_t* aData) {
13206 if (!strcmp(aTopic, kUserInteractionInactive)) {
13207 if (sUserActive && XRE_IsParentProcess()) {
13208 glean::RecordPowerMetrics();
13209 }
13210 sUserActive = false;
13211 } else if (!strcmp(aTopic, kUserInteractionActive)) {
13212 if (!sUserActive && XRE_IsParentProcess()) {
13213 glean::RecordPowerMetrics();
13214
13215 nsCOMPtr<nsIUserIdleServiceInternal> idleService =
13216 do_GetService("@mozilla.org/widget/useridleservice;1");
13217 if (idleService) {
13218 idleService->ResetIdleTimeOut(0);
13219 }
13220 }
13221
13222 sUserActive = true;
13223 } else {
13224 NS_WARNING("Unexpected observer notification")NS_DebugBreak(NS_DEBUG_WARNING, "Unexpected observer notification"
, nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp",
13224)
;
13225 }
13226 return NS_OK;
13227}
13228
13229Atomic<bool> nsContentUtils::UserInteractionObserver::sUserActive(false);
13230NS_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"
, 13230); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 13230
); __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"
, 13230); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsContentUtils::UserInteractionObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 13230); __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"
, 13230); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 13230
); __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"
, 13230); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsContentUtils::UserInteractionObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 13230); __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", 13230); 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; }
13231
13232/* static */
13233bool nsContentUtils::IsSpecialName(const nsAString& aName) {
13234 return aName.LowerCaseEqualsLiteral("_blank") ||
13235 aName.LowerCaseEqualsLiteral("_top") ||
13236 aName.LowerCaseEqualsLiteral("_parent") ||
13237 aName.LowerCaseEqualsLiteral("_self");
13238}
13239
13240/* static */
13241bool nsContentUtils::IsOverridingWindowName(const nsAString& aName) {
13242 return !aName.IsEmpty() && !IsSpecialName(aName);
13243}
13244
13245// Unfortunately, we can't unwrap an IDL object using only a concrete type.
13246// We need to calculate type data based on the IDL typename. Which means
13247// wrapping our templated function in a macro.
13248#define EXTRACT_EXN_VALUES(T, ...) \
13249 ExtractExceptionValuesImpl<mozilla::dom::prototypes::id::T, \
13250 T##_Binding::NativeType, T>(__VA_ARGS__) \
13251 .isOk()
13252
13253template <prototypes::ID PrototypeID, class NativeType, typename T>
13254static Result<Ok, nsresult> ExtractExceptionValuesImpl(
13255 JSContext* aCx, JS::Handle<JSObject*> aObj, nsACString& aFilename,
13256 uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) {
13257 AssertStaticUnwrapOK<PrototypeID>();
13258 RefPtr<T> exn;
13259 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(); })
;
13260
13261 if (nsCOMPtr<nsIStackFrame> location = exn->GetLocation()) {
13262 location->GetFilename(aCx, aFilename);
13263 *aLineOut = location->GetLineNumber(aCx);
13264 *aColumnOut = location->GetColumnNumber(aCx);
13265 } else {
13266 aFilename.Truncate();
13267 *aLineOut = 0;
13268 *aColumnOut = 0;
13269 }
13270
13271 exn->GetName(aMessageOut);
13272 aMessageOut.AppendLiteral(": ");
13273
13274 nsAutoString message;
13275 exn->GetMessageMoz(message);
13276 aMessageOut.Append(message);
13277 return Ok();
13278}
13279
13280/* static */
13281bool nsContentUtils::ExtractExceptionValues(
13282 JSContext* aCx, JS::Handle<JSObject*> aObj, nsACString& aFilename,
13283 uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) {
13284 return EXTRACT_EXN_VALUES(DOMException, aCx, aObj, aFilename, aLineOut,
13285 aColumnOut, aMessageOut) ||
13286 EXTRACT_EXN_VALUES(Exception, aCx, aObj, aFilename, aLineOut,
13287 aColumnOut, aMessageOut);
13288}
13289
13290/* static */
13291void nsContentUtils::ExtractErrorValues(
13292 JSContext* aCx, JS::Handle<JS::Value> aValue, nsACString& aSourceSpecOut,
13293 uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) {
13294 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"
, 13294); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLineOut" ")"
); do { MOZ_CrashSequence(__null, 13294); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13295 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"
, 13295); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aColumnOut"
")"); do { MOZ_CrashSequence(__null, 13295); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13296
13297 if (aValue.isObject()) {
13298 JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
13299
13300 // Try to process as an Error object. Use the file/line/column values
13301 // from the Error as they will be more specific to the root cause of
13302 // the problem.
13303 JS::BorrowedErrorReport err(aCx);
13304 if (JS_ErrorFromException(aCx, obj, err)) {
13305 // Use xpc to extract the error message only. We don't actually send
13306 // this report anywhere.
13307 RefPtr<xpc::ErrorReport> report = new xpc::ErrorReport();
13308 report->Init(err.get(),
13309 nullptr, // toString result
13310 false, // chrome
13311 0); // window ID
13312
13313 if (!report->mFileName.IsEmpty()) {
13314 aSourceSpecOut = report->mFileName;
13315 *aLineOut = report->mLineNumber;
13316 *aColumnOut = report->mColumn;
13317 }
13318 aMessageOut.Assign(report->mErrorMsg);
13319 }
13320
13321 // Next, try to unwrap the rejection value as a (DOM)Exception.
13322 else if (ExtractExceptionValues(aCx, obj, aSourceSpecOut, aLineOut,
13323 aColumnOut, aMessageOut)) {
13324 return;
13325 }
13326 }
13327
13328 // If we could not unwrap a specific error type, then perform default safe
13329 // string conversions on primitives. Objects will result in "[Object]"
13330 // unfortunately.
13331 if (aMessageOut.IsEmpty()) {
13332 nsAutoJSString jsString;
13333 if (jsString.init(aCx, aValue)) {
13334 aMessageOut = jsString;
13335 } else {
13336 JS_ClearPendingException(aCx);
13337 }
13338 }
13339}
13340
13341#undef EXTRACT_EXN_VALUES
13342
13343/* static */
13344bool nsContentUtils::ContentIsLink(nsIContent* aContent) {
13345 if (!aContent || !aContent->IsElement()) {
13346 return false;
13347 }
13348
13349 if (aContent->IsHTMLElement(nsGkAtoms::a)) {
13350 return true;
13351 }
13352
13353 return aContent->AsElement()->AttrValueIs(kNameSpaceID_XLink4, nsGkAtoms::type,
13354 nsGkAtoms::simple, eCaseMatters);
13355}
13356
13357/* static */
13358already_AddRefed<ContentFrameMessageManager>
13359nsContentUtils::TryGetBrowserChildGlobal(nsISupports* aFrom) {
13360 RefPtr<nsFrameLoaderOwner> frameLoaderOwner = do_QueryObject(aFrom);
13361 if (!frameLoaderOwner) {
13362 return nullptr;
13363 }
13364
13365 RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
13366 if (!frameLoader) {
13367 return nullptr;
13368 }
13369
13370 RefPtr<ContentFrameMessageManager> manager =
13371 frameLoader->GetBrowserChildMessageManager();
13372 return manager.forget();
13373}
13374
13375/* static */
13376Document* nsContentUtils::TryGetDocumentFromWindowGlobal(nsISupports* aFrom) {
13377 nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aFrom);
13378 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", 13378
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "window"
") (" "Expected a window global" ")"); do { MOZ_CrashSequence
(__null, 13378); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13379 if (!window) {
13380 return nullptr;
13381 }
13382 return window->GetExtantDoc();
13383}
13384
13385/* static */
13386uint32_t nsContentUtils::InnerOrOuterWindowCreated() {
13387 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", 13387); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 13387); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13388 ++sInnerOrOuterWindowCount;
13389 return ++sInnerOrOuterWindowSerialCounter;
13390}
13391
13392/* static */
13393void nsContentUtils::InnerOrOuterWindowDestroyed() {
13394 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", 13394); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 13394); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13395 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"
, 13395); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sInnerOrOuterWindowCount > 0"
")"); do { MOZ_CrashSequence(__null, 13395); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13396 --sInnerOrOuterWindowCount;
13397}
13398
13399static bool JSONCreator(const char16_t* aBuf, uint32_t aLen, void* aData) {
13400 nsAString* result = static_cast<nsAString*>(aData);
13401 return result->Append(aBuf, aLen, fallible);
13402}
13403
13404/* static */
13405bool nsContentUtils::StringifyJSON(JSContext* aCx, JS::Handle<JS::Value> aValue,
13406 nsAString& aOutStr, JSONBehavior aBehavior) {
13407 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"
, 13407); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aCx" ")");
do { MOZ_CrashSequence(__null, 13407); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13408 switch (aBehavior) {
13409 case UndefinedIsNullStringLiteral: {
13410 aOutStr.Truncate();
13411 JS::Rooted<JS::Value> value(aCx, aValue);
13412 return JS_Stringify(aCx, &value, nullptr, JS::NullHandleValue,
13413 JSONCreator, &aOutStr);
13414 }
13415 case UndefinedIsVoidString: {
13416 aOutStr.SetIsVoid(true);
13417 return JS::ToJSON(aCx, aValue, nullptr, JS::NullHandleValue, JSONCreator,
13418 &aOutStr);
13419 }
13420 default:
13421 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"
, 13421); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Invalid value for aBehavior" ")"
); do { MOZ_CrashSequence(__null, 13421); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13422 return false;
13423 }
13424}
13425
13426/* static */
13427bool nsContentUtils::
13428 HighPriorityEventPendingForTopLevelDocumentBeforeContentfulPaint(
13429 Document* aDocument) {
13430 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", 13431); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "XRE_IsContentProcess()" ") (" "This function only makes sense in content processes"
")"); do { MOZ_CrashSequence(__null, 13431); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13431 "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", 13431); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "XRE_IsContentProcess()" ") (" "This function only makes sense in content processes"
")"); do { MOZ_CrashSequence(__null, 13431); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13432
13433 if (aDocument && !aDocument->IsLoadedAsData()) {
13434 if (nsPresContext* presContext = FindPresContextForDocument(aDocument)) {
13435 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", 13436
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!presContext->IsChrome()"
") (" "Should never have a chrome PresContext in a content process"
")"); do { MOZ_CrashSequence(__null, 13436); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13436 "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", 13436
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!presContext->IsChrome()"
") (" "Should never have a chrome PresContext in a content process"
")"); do { MOZ_CrashSequence(__null, 13436); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13437
13438 return !presContext->GetInProcessRootContentDocumentPresContext()
13439 ->HadFirstContentfulPaint() &&
13440 nsThreadManager::MainThreadHasPendingHighPriorityEvents();
13441 }
13442 }
13443 return false;
13444}
13445
13446static nsGlobalWindowInner* GetInnerWindowForGlobal(nsIGlobalObject* aGlobal) {
13447 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", 13447); return
nullptr; } } while (false)
;
13448
13449 if (auto* window = aGlobal->GetAsInnerWindow()) {
13450 return nsGlobalWindowInner::Cast(window);
13451 }
13452
13453 // When Extensions run content scripts inside a sandbox, it uses
13454 // sandboxPrototype to make them appear as though they're running in the
13455 // scope of the page. So when a content script invokes postMessage, it expects
13456 // the |source| of the received message to be the window set as the
13457 // sandboxPrototype. This used to work incidentally for unrelated reasons, but
13458 // now we need to do some special handling to support it.
13459 JS::Rooted<JSObject*> scope(RootingCx(), aGlobal->GetGlobalJSObject());
13460 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", 13460); return
nullptr; } } while (false)
;
13461
13462 if (xpc::IsSandbox(scope)) {
13463 AutoJSAPI jsapi;
13464 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", 13464); AnnotateMozCrashReason
("MOZ_CRASH(" "jsapi.Init(scope)" ")"); do { MOZ_CrashSequence
(__null, 13464); __attribute__((nomerge)) ::abort(); } while (
false); } while (false); } } while (false)
;
13465 JSContext* cx = jsapi.cx();
13466 // Our current Realm on aCx is the sandbox. Using that for unwrapping
13467 // makes sense: if the sandbox can unwrap the window, we can use it.
13468 return xpc::SandboxWindowOrNull(scope, cx);
13469 }
13470
13471 // The calling window must be holding a reference, so we can return a weak
13472 // pointer.
13473 return nsGlobalWindowInner::Cast(aGlobal->GetAsInnerWindow());
13474}
13475
13476/* static */
13477nsGlobalWindowInner* nsContentUtils::IncumbentInnerWindow() {
13478 return GetInnerWindowForGlobal(GetIncumbentGlobal());
13479}
13480
13481/* static */
13482nsGlobalWindowInner* nsContentUtils::EntryInnerWindow() {
13483 return GetInnerWindowForGlobal(GetEntryGlobal());
13484}
13485
13486/* static */
13487bool nsContentUtils::IsURIInPrefList(nsIURI* aURI, const char* aPrefName) {
13488 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"
, 13488); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrefName"
")"); do { MOZ_CrashSequence(__null, 13488); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13489
13490 nsAutoCString list;
13491 Preferences::GetCString(aPrefName, list);
13492 ToLowerCase(list);
13493 return IsURIInList(aURI, list);
13494}
13495
13496/* static */
13497bool nsContentUtils::IsURIInList(nsIURI* aURI, const nsCString& aList) {
13498#ifdef DEBUG1
13499 nsAutoCString listLowerCase(aList);
13500 ToLowerCase(listLowerCase);
13501 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"
, 13502); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listLowerCase.Equals(aList)"
") (" "The aList argument should be lower-case" ")"); do { MOZ_CrashSequence
(__null, 13502); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
13502 "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"
, 13502); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listLowerCase.Equals(aList)"
") (" "The aList argument should be lower-case" ")"); do { MOZ_CrashSequence
(__null, 13502); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13503#endif
13504
13505 if (!aURI) {
13506 return false;
13507 }
13508
13509 if (aList.IsEmpty()) {
13510 return false;
13511 }
13512
13513 nsAutoCString scheme;
13514 aURI->GetScheme(scheme);
13515 if (!scheme.EqualsLiteral("http") && !scheme.EqualsLiteral("https")) {
13516 return false;
13517 }
13518
13519 // The list is comma separated domain list. Each item may start with "*.".
13520 // If starts with "*.", it matches any sub-domains.
13521
13522 nsCCharSeparatedTokenizer tokenizer(aList, ',');
13523 while (tokenizer.hasMoreTokens()) {
13524 const nsCString token(tokenizer.nextToken());
13525
13526 nsAutoCString host;
13527 aURI->GetHost(host);
13528 if (host.IsEmpty()) {
13529 return false;
13530 }
13531 ToLowerCase(host);
13532
13533 for (;;) {
13534 int32_t index = token.Find(host);
13535 if (index >= 0 &&
13536 static_cast<uint32_t>(index) + host.Length() <= token.Length()) {
13537 // If we found a full match, return true.
13538 size_t indexAfterHost = index + host.Length();
13539 if (index == 0 && indexAfterHost == token.Length()) {
13540 return true;
13541 }
13542 // If next character is '/', we need to check the path too.
13543 // We assume the path in the list means "/foo" + "*".
13544 if (token[indexAfterHost] == '/') {
13545 nsDependentCSubstring pathInList(
13546 token, indexAfterHost,
13547 static_cast<nsDependentCSubstring::size_type>(-1));
13548 nsAutoCString filePath;
13549 aURI->GetFilePath(filePath);
13550 ToLowerCase(filePath);
13551 if (StringBeginsWith(filePath, pathInList) &&
13552 (filePath.Length() == pathInList.Length() ||
13553 pathInList.EqualsLiteral("/") ||
13554 filePath[pathInList.Length() - 1] == '/' ||
13555 filePath[pathInList.Length() - 1] == '?' ||
13556 filePath[pathInList.Length() - 1] == '#')) {
13557 return true;
13558 }
13559 }
13560 }
13561 int32_t startIndexOfCurrentLevel = host[0] == '*' ? 1 : 0;
13562 int32_t startIndexOfNextLevel =
13563 host.Find(".", startIndexOfCurrentLevel + 1);
13564 if (startIndexOfNextLevel <= 0) {
13565 break;
13566 }
13567 host.ReplaceLiteral(0, startIndexOfNextLevel, "*");
13568 }
13569 }
13570
13571 return false;
13572}
13573
13574/* static */
13575LayoutDeviceIntMargin nsContentUtils::GetWindowSafeAreaInsets(
13576 nsIScreen* aScreen, const LayoutDeviceIntMargin& aSafeAreaInsets,
13577 const LayoutDeviceIntRect& aWindowRect) {
13578 // This calculates safe area insets of window from screen rectangle, window
13579 // rectangle and safe area insets of screen.
13580 //
13581 // +----------------------------------------+ <-- screen
13582 // | +-------------------------------+ <------- window
13583 // | | window's safe area inset top) | |
13584 // +--+-------------------------------+--+ |
13585 // | | | |<------ safe area rectangle of
13586 // | | | | | screen
13587 // +--+-------------------------------+--+ |
13588 // | |window's safe area inset bottom| |
13589 // | +-------------------------------+ |
13590 // +----------------------------------------+
13591 //
13592 LayoutDeviceIntMargin windowSafeAreaInsets;
13593 if (windowSafeAreaInsets == aSafeAreaInsets) {
13594 // no safe area insets.
13595 return windowSafeAreaInsets;
13596 }
13597
13598 const LayoutDeviceIntRect screenRect = aScreen->GetRect();
13599 LayoutDeviceIntRect safeAreaRect = screenRect;
13600 safeAreaRect.Deflate(aSafeAreaInsets);
13601
13602 // FIXME(bug 1754323): This can trigger because the screen rect is not
13603 // orientation-aware.
13604 // MOZ_ASSERT(screenRect.Contains(windowRect),
13605 // "Screen doesn't contain window rect? Something seems off");
13606
13607 // window's rect of safe area
13608 safeAreaRect = safeAreaRect.Intersect(aWindowRect);
13609
13610 windowSafeAreaInsets.top = safeAreaRect.y - aWindowRect.y;
13611 windowSafeAreaInsets.left = safeAreaRect.x - aWindowRect.x;
13612 windowSafeAreaInsets.right =
13613 aWindowRect.x + aWindowRect.width - (safeAreaRect.x + safeAreaRect.width);
13614 windowSafeAreaInsets.bottom = aWindowRect.y + aWindowRect.height -
13615 (safeAreaRect.y + safeAreaRect.height);
13616
13617 windowSafeAreaInsets.EnsureAtLeast(LayoutDeviceIntMargin());
13618 // This shouldn't be needed, but it wallpapers orientation issues, see bug
13619 // 1754323.
13620 windowSafeAreaInsets.EnsureAtMost(aSafeAreaInsets);
13621
13622 return windowSafeAreaInsets;
13623}
13624
13625/* static */
13626nsContentUtils::SubresourceCacheValidationInfo
13627nsContentUtils::GetSubresourceCacheValidationInfo(nsIRequest* aRequest,
13628 nsIURI* aURI) {
13629 SubresourceCacheValidationInfo info;
13630 if (nsCOMPtr<nsICacheInfoChannel> cache = do_QueryInterface(aRequest)) {
13631 uint32_t value = 0;
13632 if (NS_SUCCEEDED(cache->GetCacheTokenExpirationTime(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cache->GetCacheTokenExpirationTime
(&value))), 1)))
) {
13633 // NOTE: If the cache doesn't expire, the value should be
13634 // nsICacheEntry::NO_EXPIRATION_TIME.
13635 info.mExpirationTime.emplace(CacheExpirationTime::ExpireAt(value));
13636 }
13637 }
13638
13639 // Determine whether the cache entry must be revalidated when we try to use
13640 // it. Currently, only HTTP specifies this information...
13641 if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest)) {
13642 (void)httpChannel->IsNoStoreResponse(&info.mMustRevalidate);
13643
13644 if (!info.mMustRevalidate) {
13645 (void)httpChannel->IsNoCacheResponse(&info.mMustRevalidate);
13646 }
13647
13648 if (!info.mMustRevalidate) {
13649 nsAutoCString vary;
13650 (void)httpChannel->GetResponseHeader("vary"_ns, vary);
13651 info.mMustRevalidate = [&] {
13652 for (const nsACString& token :
13653 nsCCharSeparatedTokenizer(vary, ',').ToRange()) {
13654 if (token.EqualsLiteral("*")) {
13655 return true;
13656 }
13657 if (token.EqualsIgnoreCase("cookie")) {
13658 return true;
13659 }
13660 }
13661 return false;
13662 }();
13663 }
13664 }
13665
13666 // data: URIs are safe to cache across documents under any circumstance, so we
13667 // special-case them here even though the channel itself doesn't have any
13668 // caching policy. Same for chrome:// uris.
13669 //
13670 // TODO(emilio): Figure out which other schemes that don't have caching
13671 // policies are safe to cache. Blobs should be...
13672 const bool knownCacheable = [&] {
13673 if (!aURI) {
13674 return false;
13675 }
13676 if (aURI->SchemeIs("data") || aURI->SchemeIs("moz-page-thumb") ||
13677 aURI->SchemeIs("moz-newtab-wallpaper") ||
13678 aURI->SchemeIs("moz-extension")) {
13679 return true;
13680 }
13681 if (aURI->SchemeIs("chrome") || aURI->SchemeIs("resource")) {
13682 return !StaticPrefs::nglayout_debug_disable_xul_cache();
13683 }
13684 return false;
13685 }();
13686
13687 if (knownCacheable) {
13688 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", 13688); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!info.mExpirationTime" ")"); do { MOZ_CrashSequence
(__null, 13688); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13689 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", 13689); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!info.mMustRevalidate" ")"); do { MOZ_CrashSequence
(__null, 13689); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13690 info.mExpirationTime = Some(CacheExpirationTime::Never());
13691 }
13692
13693 return info;
13694}
13695
13696CacheExpirationTime nsContentUtils::GetSubresourceCacheExpirationTime(
13697 nsIRequest* aRequest, nsIURI* aURI) {
13698 auto info = GetSubresourceCacheValidationInfo(aRequest, aURI);
13699
13700 // For now, we never cache entries that we have to revalidate, or whose
13701 // channel don't support caching.
13702 if (info.mMustRevalidate || !info.mExpirationTime) {
13703 return CacheExpirationTime::AlreadyExpired();
13704 }
13705 return *info.mExpirationTime;
13706}
13707
13708/* static */
13709bool nsContentUtils::ShouldBypassSubResourceCache(Document* aDoc) {
13710 RefPtr<nsILoadGroup> lg = aDoc->GetDocumentLoadGroup();
13711 if (!lg) {
13712 return false;
13713 }
13714 nsLoadFlags flags;
13715 if (NS_FAILED(lg->GetLoadFlags(&flags))((bool)(__builtin_expect(!!(NS_FAILED_impl(lg->GetLoadFlags
(&flags))), 0)))
) {
13716 return false;
13717 }
13718 return flags & (nsIRequest::LOAD_BYPASS_CACHE |
13719 nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE);
13720}
13721
13722nsCString nsContentUtils::TruncatedURLForDisplay(nsIURI* aURL, size_t aMaxLen) {
13723 nsCString spec;
13724 if (aURL) {
13725 aURL->GetSpec(spec);
13726 spec.Truncate(std::min(aMaxLen, spec.Length()));
13727 }
13728 return spec;
13729}
13730
13731/* static */
13732nsresult nsContentUtils::AnonymizeId(nsAString& aId,
13733 const nsACString& aOriginKey,
13734 OriginFormat aFormat) {
13735 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", 13735); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 13735); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13736
13737 nsresult rv;
13738 nsCString rawKey;
13739 if (aFormat == OriginFormat::Base64) {
13740 rv = Base64Decode(aOriginKey, rawKey);
13741 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"
, 13741); return rv; } } while (false)
;
13742 } else {
13743 rawKey = aOriginKey;
13744 }
13745
13746 HMAC hmac;
13747 rv = hmac.Begin(
13748 SEC_OID_SHA256,
13749 Span(reinterpret_cast<const uint8_t*>(rawKey.get()), rawKey.Length()));
13750 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"
, 13750); return rv; } } while (false)
;
13751
13752 NS_ConvertUTF16toUTF8 id(aId);
13753 rv = hmac.Update(reinterpret_cast<const uint8_t*>(id.get()), id.Length());
13754 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"
, 13754); return rv; } } while (false)
;
13755
13756 nsTArray<uint8_t> macBytes;
13757 rv = hmac.End(macBytes);
13758 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"
, 13758); return rv; } } while (false)
;
13759
13760 nsCString macBase64;
13761 rv = Base64Encode(
13762 nsDependentCSubstring(reinterpret_cast<const char*>(macBytes.Elements()),
13763 macBytes.Length()),
13764 macBase64);
13765 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"
, 13765); return rv; } } while (false)
;
13766
13767 CopyUTF8toUTF16(macBase64, aId);
13768 return NS_OK;
13769}
13770
13771void nsContentUtils::RequestGeckoTaskBurst() {
13772 nsCOMPtr<nsIAppShell> appShell = do_GetService(NS_APPSHELL_CID{0x2d96b3df, 0xc051, 0x11d1, {0xa8, 0x27, 0x00, 0x40, 0x95, 0x9a
, 0x28, 0xc9}}
);
13773 if (appShell) {
13774 appShell->GeckoTaskBurst();
13775 }
13776}
13777
13778nsIContent* nsContentUtils::GetClosestLinkInFlatTree(nsIContent* aContent) {
13779 for (nsIContent* content = aContent; content;
13780 content = content->GetFlattenedTreeParent()) {
13781 if (nsContentUtils::IsDraggableLink(content)) {
13782 return content;
13783 }
13784 }
13785 return nullptr;
13786}
13787
13788template <TreeKind aKind>
13789MOZ_ALWAYS_INLINEinline const nsINode* GetParent(const nsINode* aNode) {
13790 if constexpr (aKind == TreeKind::DOM) {
13791 return aNode->GetParentNode();
13792 } else if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
13793 return aNode->GetParentOrShadowHostNode();
13794 } else if constexpr (aKind == TreeKind::FlatForSelection) {
13795 return aNode->GetFlattenedTreeParentNodeForSelection();
13796 } else if constexpr (aKind == TreeKind::Flat) {
13797 return aNode->GetFlattenedTreeParentNode();
13798 } else {
13799 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"
, 13799); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Handle the new TreeKind value" ")"
); do { MOZ_CrashSequence(__null, 13799); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); __builtin_unreachable
(); } while (false)
;
13800 }
13801}
13802
13803template <TreeKind aKind>
13804Maybe<int32_t> nsContentUtils::GetIndexInParent(
13805 const nsINode* aParent, const nsIContent* aPossibleChild) {
13806 const Maybe<uint32_t> idx = [&]() {
13807 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
13808 return aParent->ComputeIndexOf(aPossibleChild);
13809 } else {
13810 return aParent->ComputeIndexOf<aKind>(aPossibleChild);
13811 }
13812 }();
13813 if (idx) {
13814 return idx.map([](auto i) { return AssertedCast<int32_t>(i); });
13815 }
13816
13817 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
13818 if (const auto* sr = ShadowRoot::FromNode(aPossibleChild)) {
13819 return sr->GetHost() == aParent ? Some(-1) : Nothing();
13820 }
13821 }
13822
13823 // Handle pseudo-element and anonymous node ordering:
13824 // ::backdrop -> ::marker -> ::checkmark -> ::before -> regular siblings ->
13825 // all other NAC -> ::after -> ::picker-icon
13826 // This matches the order of AllChildrenIterator.
13827 if (NS_WARN_IF(!aPossibleChild->IsRootOfNativeAnonymousSubtree())NS_warn_if_impl(!aPossibleChild->IsRootOfNativeAnonymousSubtree
(), "!aPossibleChild->IsRootOfNativeAnonymousSubtree()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13827)
) {
13828 // If aNode is mid unbind, we can reach this.
13829 return Nothing();
13830 }
13831
13832 if (NS_WARN_IF(aPossibleChild->GetParentNode() != aParent)NS_warn_if_impl(aPossibleChild->GetParentNode() != aParent
, "aPossibleChild->GetParentNode() != aParent", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13832)
) {
13833 // We can't be an anon child if not correctly parented.
13834 return Nothing();
13835 }
13836
13837 if (aPossibleChild->IsGeneratedContentContainerForBackdrop()) {
13838 return Some(-5);
13839 }
13840
13841 if (aPossibleChild->IsGeneratedContentContainerForMarker()) {
13842 return Some(-4);
13843 }
13844
13845 if (aPossibleChild->IsGeneratedContentContainerForCheckmark()) {
13846 return Some(-3);
13847 }
13848
13849 if (aPossibleChild->IsGeneratedContentContainerForBefore()) {
13850 return Some(-2);
13851 }
13852
13853 AutoTArray<nsIContent*, 8> anonKids;
13854
13855 // Regular children are indexed via ComputeIndexOf (range [0, GetChildCount))
13856 // for both DOM and ShadowIncludingDOM above; only the flat tree indexes them
13857 // via the flattened iterator. Trailing NAC must be based at the matching
13858 // count so it lands after the regular children in the same index space.
13859 const int32_t siblingCount = [&]() -> uint32_t {
13860 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
13861 return aParent->GetChildCount();
13862 } else {
13863 return aParent->GetChildCount<aKind>();
13864 }
13865 }();
13866
13867 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", 13867); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aParent->MayHaveAnonymousChildren()" ")"
); do { MOZ_CrashSequence(__null, 13867); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13868 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", 13868); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aParent->IsContent()" ")"); do { MOZ_CrashSequence
(__null, 13868); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13869 nsContentUtils::AppendNativeAnonymousChildren(aParent->AsContent(), anonKids,
13870 nsIContent::eAllChildren);
13871
13872 if (aPossibleChild->IsGeneratedContentContainerForAfter()) {
13873 return Some(int32_t(siblingCount + anonKids.Length()));
13874 }
13875
13876 if (aPossibleChild->IsGeneratedContentContainerForPickerIcon()) {
13877 return Some(int32_t(siblingCount + anonKids.Length()) + 1);
13878 }
13879
13880 auto index = anonKids.IndexOf(aPossibleChild);
13881 if (index == decltype(anonKids)::NoIndex) {
13882 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", 13884
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
"Missing parent -> child link somehow?" "Potentially unstable ordering"
")"); do { MOZ_CrashSequence(__null, 13884); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13883 "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", 13884
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
"Missing parent -> child link somehow?" "Potentially unstable ordering"
")"); do { MOZ_CrashSequence(__null, 13884); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13884 "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", 13884
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
"Missing parent -> child link somehow?" "Potentially unstable ordering"
")"); do { MOZ_CrashSequence(__null, 13884); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13885 return Nothing();
13886 }
13887 return Some(siblingCount + int32_t(index));
13888}
13889
13890template <TreeKind aTreeKind>
13891int32_t nsContentUtils::CompareTreePosition(const nsINode* aNode1,
13892 const nsINode* aNode2,
13893 const nsINode* aCommonAncestor,
13894 NodeIndexCache* aCache) {
13895 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", 13895
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ") (" "aNode1 must not be null"
")"); do { MOZ_CrashSequence(__null, 13895); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13896 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", 13896
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ") (" "aNode2 must not be null"
")"); do { MOZ_CrashSequence(__null, 13896); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13897
13898 if (NS_WARN_IF(aNode1 == aNode2)NS_warn_if_impl(aNode1 == aNode2, "aNode1 == aNode2", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13898)
) {
13899 return 0;
13900 }
13901
13902 // TODO: Maybe handle flat tree too or other common cases?
13903 if constexpr (aTreeKind == TreeKind::DOM ||
13904 aTreeKind == TreeKind::ShadowIncludingDOM) {
13905 if (aNode1->GetNextSibling() == aNode2) {
13906 return -1;
13907 }
13908 if (aNode1->GetPreviousSibling() == aNode2) {
13909 return 1;
13910 }
13911 }
13912
13913 AutoTArray<const nsINode*, 32> node1Ancestors;
13914 const nsINode* c1;
13915 for (c1 = aNode1; c1 && c1 != aCommonAncestor;
13916 c1 = GetParent<aTreeKind>(c1)) {
13917 node1Ancestors.AppendElement(c1);
13918 }
13919 if (!c1 && aCommonAncestor) {
13920 // So, it turns out aCommonAncestor was not an ancestor of c1. Oops.
13921 // Never mind. We can continue as if aCommonAncestor was null.
13922 aCommonAncestor = nullptr;
13923 }
13924
13925 AutoTArray<const nsINode*, 32> node2Ancestors;
13926 const nsINode* c2;
13927 for (c2 = aNode2; c2 && c2 != aCommonAncestor;
13928 c2 = GetParent<aTreeKind>(c2)) {
13929 node2Ancestors.AppendElement(c2);
13930 }
13931 if (!c2 && aCommonAncestor) {
13932 // So, it turns out aCommonAncestor was not an ancestor of c2.
13933 // We need to retry with no common ancestor hint.
13934 return CompareTreePosition<aTreeKind>(aNode1, aNode2, nullptr, aCache);
13935 }
13936
13937 // FIXME: Looks like that some of this can be rewritten with CommonAncestors.
13938 int last1 = node1Ancestors.Length() - 1;
13939 int last2 = node2Ancestors.Length() - 1;
13940 const nsINode* node1Ancestor = nullptr;
13941 const nsINode* node2Ancestor = nullptr;
13942 while (last1 >= 0 && last2 >= 0 &&
13943 ((node1Ancestor = node1Ancestors.ElementAt(last1)) ==
13944 (node2Ancestor = node2Ancestors.ElementAt(last2)))) {
13945 last1--;
13946 last2--;
13947 }
13948
13949 if (last1 < 0) {
13950 if (last2 < 0) {
13951 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"
, 13951); MOZ_PretendNoReturn(); } } while (0)
;
13952 return 0;
13953 }
13954 // aContent1 is an ancestor of aContent2
13955 return -1;
13956 }
13957
13958 if (last2 < 0) {
13959 // aContent2 is an ancestor of aContent1
13960 return 1;
13961 }
13962 // node1Ancestor != node2Ancestor, so they must be siblings with the
13963 // same parent
13964 const nsINode* parent = GetParent<aTreeKind>(node1Ancestor);
13965 if (NS_WARN_IF(!parent)NS_warn_if_impl(!parent, "!parent", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13965)
) { // different documents??
13966 return 0;
13967 }
13968 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", 13968); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "node1Ancestor" ")"); do { MOZ_CrashSequence
(__null, 13968); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13969 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", 13969); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "node2Ancestor" ")"); do { MOZ_CrashSequence
(__null, 13969); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13970 Maybe<int32_t> index1;
13971 Maybe<int32_t> index2;
13972 // node1Ancestor and node2Ancestor must be children of parent so that they
13973 // must be content nodes if we can get the indices.
13974 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"
, 13974); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "node1Ancestor->IsContent()"
")"); do { MOZ_CrashSequence(__null, 13974); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13975 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"
, 13975); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "node2Ancestor->IsContent()"
")"); do { MOZ_CrashSequence(__null, 13975); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13976 if (aCache) {
13977 aCache->ComputeIndicesOf<aTreeKind>(parent, node1Ancestor->AsContent(),
13978 node2Ancestor->AsContent(), index1,
13979 index2);
13980 } else {
13981 index1 = GetIndexInParent<aTreeKind>(parent, node1Ancestor->AsContent());
13982 index2 = GetIndexInParent<aTreeKind>(parent, node2Ancestor->AsContent());
13983 }
13984 if (NS_WARN_IF(index1.isNothing())NS_warn_if_impl(index1.isNothing(), "index1.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13984)
|| NS_WARN_IF(index2.isNothing())NS_warn_if_impl(index2.isNothing(), "index2.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13984)
) {
13985 // This should generally never happen, but can happen mid-unbind or in other
13986 // edge cases, deal with it somewhat reasonably.
13987 return 0;
13988 }
13989 return static_cast<int32_t>(static_cast<int64_t>(*index1) - *index2);
13990}
13991
13992nsIContent* nsContentUtils::AttachDeclarativeShadowRoot(
13993 nsIContent* aHost, ShadowRootMode aMode, bool aIsClonable,
13994 bool aIsSerializable, bool aDelegatesFocus, bool aCustomElementRegistry,
13995 SlotAssignmentMode aSlotAssignment, const nsAString& aReferenceTarget) {
13996 RefPtr<Element> host = mozilla::dom::Element::FromNodeOrNull(aHost);
13997 if (!host || host->GetShadowRoot()) {
13998 // https://html.spec.whatwg.org/#parsing-main-inhead:shadow-host
13999 return nullptr;
14000 }
14001
14002 ShadowRootInit init;
14003 init.mMode = aMode;
14004 init.mDelegatesFocus = aDelegatesFocus;
14005 init.mSlotAssignment = aSlotAssignment;
14006 init.mClonable = aIsClonable;
14007 init.mSerializable = aIsSerializable;
14008 // https://html.spec.whatwg.org/#current-template-insertion-mode
14009 // "Let registry be null if templateStartTag has a
14010 // shadowrootcustomelementregistry attribute; otherwise
14011 // declarativeShadowHostElement's node document's custom element registry."
14012 if (StaticPrefs::dom_scoped_custom_element_registries_enabled()) {
14013 if (aCustomElementRegistry) {
14014 init.mCustomElementRegistry.Construct(nullptr);
14015 } else {
14016 init.mCustomElementRegistry.Construct(
14017 host->OwnerDoc()->GetCustomElementRegistry());
14018 }
14019 }
14020
14021 RefPtr shadowRoot = host->AttachShadow(init, IgnoreErrors());
14022 if (shadowRoot) {
14023 shadowRoot->SetIsDeclarative(
14024 nsGenericHTMLFormControlElement::ShadowRootDeclarative::Yes);
14025 // https://html.spec.whatwg.org/#parsing-main-inhead
14026 // 7. If templateStartTag has a shadowrootcustomelementregistry attribute,
14027 // set shadow's keep custom element registry null to true.
14028 if (StaticPrefs::dom_scoped_custom_element_registries_enabled() &&
14029 aCustomElementRegistry) {
14030 shadowRoot->SetKeepCustomElementRegistryNull();
14031 }
14032 // https://html.spec.whatwg.org/#parsing-main-inhead:available-to-element-internals
14033 shadowRoot->SetAvailableToElementInternals();
14034 shadowRoot->SetReferenceTarget(aReferenceTarget);
14035 }
14036 return shadowRoot;
14037}
14038
14039// https://html.spec.whatwg.org/#the-navigation-must-be-a-replace
14040/* static */ bool nsContentUtils::NavigationMustBeAReplace(
14041 nsIURI& aURI, const Document& aDocument) {
14042 // The navigation must be a replace, given a URL url and a Document document,
14043 // if any of the following are true:
14044 // - url's scheme is "javascript"; or
14045 // - document's is initial about:blank is true.
14046 return aURI.SchemeIs("javascript") ||
14047 (NS_IsAboutBlank(aDocument.GetDocumentURI()) &&
14048 aDocument.IsInitialDocument());
14049}
14050
14051template int32_t nsContentUtils::CompareTreePosition<TreeKind::DOM>(
14052 const nsINode*, const nsINode*, const nsINode*, NodeIndexCache*);
14053template int32_t
14054nsContentUtils::CompareTreePosition<TreeKind::ShadowIncludingDOM>(
14055 const nsINode*, const nsINode*, const nsINode*, NodeIndexCache*);
14056template int32_t
14057nsContentUtils::CompareTreePosition<TreeKind::FlatForSelection>(
14058 const nsINode*, const nsINode*, const nsINode*, NodeIndexCache*);
14059template int32_t nsContentUtils::CompareTreePosition<TreeKind::Flat>(
14060 const nsINode*, const nsINode*, const nsINode*, NodeIndexCache*);