Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name nsContentUtils.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/base -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/base -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/dom/base -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/base -I /root/firefox-clang/dom/battery -I /root/firefox-clang/dom/events -I /root/firefox-clang/dom/media -I /root/firefox-clang/dom/network -I /root/firefox-clang/caps -I /root/firefox-clang/docshell/base -I /root/firefox-clang/dom/base -I /root/firefox-clang/dom/file -I /root/firefox-clang/dom/geolocation -I /root/firefox-clang/dom/html -I /root/firefox-clang/dom/ipc -I /root/firefox-clang/dom/storage -I /root/firefox-clang/dom/svg -I /root/firefox-clang/dom/xml -I /root/firefox-clang/dom/xslt/xpath -I /root/firefox-clang/dom/xul -I /root/firefox-clang/extensions/spellcheck/src -I /root/firefox-clang/gfx/2d -I /root/firefox-clang/image -I /root/firefox-clang/js/xpconnect/loader -I /root/firefox-clang/js/xpconnect/src -I /root/firefox-clang/js/xpconnect/wrappers -I /root/firefox-clang/layout/base -I /root/firefox-clang/layout/forms -I /root/firefox-clang/layout/generic -I /root/firefox-clang/layout/style -I /root/firefox-clang/layout/xul -I /root/firefox-clang/netwerk/base -I /root/firefox-clang/netwerk/protocol/http -I /root/firefox-clang/netwerk/url-classifier -I /root/firefox-clang/parser/htmlparser -I /root/firefox-clang/security/manager/ssl -I /root/firefox-clang/third_party/xsimd/include -I /root/firefox-clang/widget -I /root/firefox-clang/xpcom/build -I /root/firefox-clang/xpcom/ds -I /root/firefox-clang/netwerk/sctp/datachannel -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/toolkit/components/telemetry -I /root/firefox-clang/xpcom/base -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -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-09-01-224014-2642839-1 -x c++ /root/firefox-clang/dom/base/nsContentUtils.cpp

/root/firefox-clang/dom/base/nsContentUtils.cpp

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5/* A namespace class for static layout utilities. */
6
7#include "nsContentUtils.h"
8
9#include <fmt/format.h>
10
11#include <algorithm>
12#include <cstddef>
13#include <cstdint>
14#include <cstdlib>
15#include <cstring>
16#include <functional>
17#include <new>
18#include <utility>
19
20#include "BrowserChild.h"
21#include "CharacterDataBuffer.h"
22#include "DecoderTraits.h"
23#include "ErrorList.h"
24#include "HTMLSplitOnSpacesTokenizer.h"
25#include "ImageOps.h"
26#include "InProcessBrowserChildMessageManager.h"
27#include "MainThreadUtils.h"
28#include "PLDHashTable.h"
29#include "ReferrerInfo.h"
30#include "ScopedNSSTypes.h"
31#include "ThirdPartyUtil.h"
32#include "Units.h"
33#include "chrome/common/ipc_message.h"
34#include "gfxDrawable.h"
35#include "harfbuzz/hb.h"
36#include "imgICache.h"
37#include "imgIContainer.h"
38#include "imgILoader.h"
39#include "imgIRequest.h"
40#include "imgLoader.h"
41#include "js/Array.h"
42#include "js/ArrayBuffer.h"
43#include "js/BuildId.h"
44#include "js/GCAPI.h"
45#include "js/Id.h"
46#include "js/JSON.h"
47#include "js/PropertyAndElement.h" // JS_DefineElement, JS_GetProperty
48#include "js/PropertyDescriptor.h"
49#include "js/Realm.h"
50#include "js/RegExp.h"
51#include "js/RegExpFlags.h"
52#include "js/RootingAPI.h"
53#include "js/TypeDecls.h"
54#include "js/Value.h"
55#include "js/Wrapper.h"
56#include "jsapi.h"
57#include "jsfriendapi.h"
58#include "mozAutoDocUpdate.h"
59#include "mozIDOMWindow.h"
60#include "mozilla/AlreadyAddRefed.h"
61#include "mozilla/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_nglayout.h"
128#include "mozilla/StaticPrefs_privacy.h"
129#include "mozilla/StaticPrefs_test.h"
130#include "mozilla/StaticPrefs_ui.h"
131#include "mozilla/StaticPtr.h"
132#include "mozilla/TextControlState.h"
133#include "mozilla/TextEditor.h"
134#include "mozilla/TextEvents.h"
135#include "mozilla/TextUtils.h"
136#include "mozilla/Tokenizer.h"
137#include "mozilla/UniquePtr.h"
138#include "mozilla/ViewportUtils.h"
139#include "mozilla/dom/AncestorIterator.h"
140#include "mozilla/dom/AutoEntryScript.h"
141#include "mozilla/dom/AutoSuppressEventHandlingAndSuspend.h"
142#include "mozilla/dom/AutocompleteInfoBinding.h"
143#include "mozilla/dom/BindingDeclarations.h"
144#include "mozilla/dom/BindingUtils.h"
145#include "mozilla/dom/BlobImpl.h"
146#include "mozilla/dom/BlobURLProtocolHandler.h"
147#include "mozilla/dom/BorrowedAttrInfo.h"
148#include "mozilla/dom/BrowserBridgeParent.h"
149#include "mozilla/dom/BrowserParent.h"
150#include "mozilla/dom/BrowsingContext.h"
151#include "mozilla/dom/BrowsingContextGroup.h"
152#include "mozilla/dom/CacheExpirationTime.h"
153#include "mozilla/dom/CallbackFunction.h"
154#include "mozilla/dom/CallbackObject.h"
155#include "mozilla/dom/ChildIterator.h"
156#include "mozilla/dom/ChromeMessageBroadcaster.h"
157#include "mozilla/dom/ContentChild.h"
158#include "mozilla/dom/ContentFrameMessageManager.h"
159#include "mozilla/dom/ContentParent.h"
160#include "mozilla/dom/CustomElementRegistry.h"
161#include "mozilla/dom/CustomElementRegistryBinding.h"
162#include "mozilla/dom/CustomElementTypes.h"
163#include "mozilla/dom/DOMArena.h"
164#include "mozilla/dom/DOMException.h"
165#include "mozilla/dom/DOMExceptionBinding.h"
166#include "mozilla/dom/DOMSecurityMonitor.h"
167#include "mozilla/dom/DOMTypes.h"
168#include "mozilla/dom/DataTransfer.h"
169#include "mozilla/dom/DeprecationReportBody.h"
170#include "mozilla/dom/DocGroup.h"
171#include "mozilla/dom/Document.h"
172#include "mozilla/dom/DocumentFragment.h"
173#include "mozilla/dom/DocumentInlines.h"
174#include "mozilla/dom/DocumentOrShadowRoot.h"
175#include "mozilla/dom/Element.h"
176#include "mozilla/dom/ElementBinding.h"
177#include "mozilla/dom/ElementInlines.h"
178#include "mozilla/dom/Event.h"
179#include "mozilla/dom/EventTarget.h"
180#include "mozilla/dom/FileBlobImpl.h"
181#include "mozilla/dom/FileSystemSecurity.h"
182#include "mozilla/dom/FilteredNodeIterator.h"
183#include "mozilla/dom/FormData.h"
184#include "mozilla/dom/FragmentOrElement.h"
185#include "mozilla/dom/FromParser.h"
186#include "mozilla/dom/FunctionBinding.h"
187#include "mozilla/dom/HTMLElement.h"
188#include "mozilla/dom/HTMLFormElement.h"
189#include "mozilla/dom/HTMLImageElement.h"
190#include "mozilla/dom/HTMLInputElement.h"
191#include "mozilla/dom/HTMLTemplateElement.h"
192#include "mozilla/dom/HTMLTextAreaElement.h"
193#include "mozilla/dom/IPCBlob.h"
194#include "mozilla/dom/IPCBlobUtils.h"
195#include "mozilla/dom/MessageBroadcaster.h"
196#include "mozilla/dom/MessageListenerManager.h"
197#include "mozilla/dom/MessagePort.h"
198#include "mozilla/dom/MimeType.h"
199#include "mozilla/dom/MouseEventBinding.h"
200#include "mozilla/dom/MutationObservers.h"
201#include "mozilla/dom/NameSpaceConstants.h"
202#include "mozilla/dom/NodeBinding.h"
203#include "mozilla/dom/NodeInfo.h"
204#include "mozilla/dom/PBrowser.h"
205#include "mozilla/dom/PContentChild.h"
206#include "mozilla/dom/PrototypeList.h"
207#include "mozilla/dom/ReferrerPolicyBinding.h"
208#include "mozilla/dom/ReportingUtils.h"
209#include "mozilla/dom/Sanitizer.h"
210#include "mozilla/dom/ScriptLoader.h"
211#include "mozilla/dom/ScriptSettings.h"
212#include "mozilla/dom/Selection.h"
213#include "mozilla/dom/ShadowRoot.h"
214#include "mozilla/dom/Text.h"
215#include "mozilla/dom/TrustedHTML.h"
216#include "mozilla/dom/TrustedTypeUtils.h"
217#include "mozilla/dom/TrustedTypesConstants.h"
218#include "mozilla/dom/UserActivation.h"
219#include "mozilla/dom/ViewTransition.h"
220#include "mozilla/dom/WindowBinding.h"
221#include "mozilla/dom/WindowContext.h"
222#include "mozilla/dom/WindowGlobalChild.h"
223#include "mozilla/dom/WindowGlobalParent.h"
224#include "mozilla/dom/WorkerCommon.h"
225#include "mozilla/dom/WorkerPrivate.h"
226#include "mozilla/dom/WorkerRunnable.h"
227#include "mozilla/dom/XULCommandEvent.h"
228#include "mozilla/fallible.h"
229#include "mozilla/gfx/2D.h"
230#include "mozilla/gfx/BaseMargin.h"
231#include "mozilla/gfx/BasePoint.h"
232#include "mozilla/gfx/BaseSize.h"
233#include "mozilla/gfx/DataSurfaceHelpers.h"
234#include "mozilla/gfx/Point.h"
235#include "mozilla/gfx/Rect.h"
236#include "mozilla/gfx/Types.h"
237#include "mozilla/glean/GleanPings.h"
238#include "mozilla/htmlaccel/htmlaccelEnabled.h"
239#ifdef MOZ_MAY_HAVE_HTMLACCEL1
240# include "mozilla/htmlaccel/htmlaccelNotInline.h"
241#endif
242#include "mozilla/dom/ContentList.h"
243#include "mozilla/intl/LocaleService.h"
244#include "mozilla/ipc/ProtocolUtils.h"
245#include "mozilla/net/ChannelClassifierUtils.h"
246#include "mozilla/widget/IMEData.h"
247#include "nsAboutProtocolUtils.h"
248#include "nsArrayUtils.h"
249#include "nsAtomHashKeys.h"
250#include "nsAttrName.h"
251#include "nsAttrValue.h"
252#include "nsAttrValueInlines.h"
253#include "nsBaseHashtable.h"
254#include "nsCCUncollectableMarker.h"
255#include "nsCOMPtr.h"
256#include "nsCRT.h"
257#include "nsCRTGlue.h"
258#include "nsCanvasFrame.h"
259#include "nsCaseTreatment.h"
260#include "nsCharSeparatedTokenizer.h"
261#include "nsCharTraits.h"
262#include "nsCompatibility.h"
263#include "nsComponentManagerUtils.h"
264#include "nsContainerFrame.h"
265#include "nsContentCreatorFunctions.h"
266#include "nsContentDLF.h"
267#include "nsContentListDeclarations.h"
268#include "nsContentPolicyUtils.h"
269#include "nsCoord.h"
270#include "nsCycleCollectionNoteChild.h"
271#include "nsDOMMutationObserver.h"
272#include "nsDOMString.h"
273#include "nsDebug.h"
274#include "nsDocShell.h"
275#include "nsDocShellCID.h"
276#include "nsError.h"
277#include "nsFocusManager.h"
278#include "nsFrameList.h"
279#include "nsFrameLoader.h"
280#include "nsFrameLoaderOwner.h"
281#include "nsGenericHTMLElement.h"
282#include "nsGkAtoms.h"
283#include "nsGlobalWindowInner.h"
284#include "nsGlobalWindowOuter.h"
285#include "nsHTMLDocument.h"
286#include "nsHTMLTags.h"
287#include "nsHashKeys.h"
288#include "nsHtml5StringParser.h"
289#include "nsIAboutModule.h"
290#include "nsIAnonymousContentCreator.h"
291#include "nsIAppShell.h"
292#include "nsIArray.h"
293#include "nsIAsyncVerifyRedirectCallback.h"
294#include "nsIBidiKeyboard.h"
295#include "nsIBrowser.h"
296#include "nsICacheInfoChannel.h"
297#include "nsICachingChannel.h"
298#include "nsICategoryManager.h"
299#include "nsIChannel.h"
300#include "nsIChannelEventSink.h"
301#include "nsIClassifiedChannel.h"
302#include "nsIConsoleService.h"
303#include "nsIContent.h"
304#include "nsIContentInlines.h"
305#include "nsIContentPolicy.h"
306#include "nsIContentSecurityPolicy.h"
307#include "nsIContentSink.h"
308#include "nsIDOMWindowUtils.h"
309#include "nsIDocShell.h"
310#include "nsIDocShellTreeItem.h"
311#include "nsIDocumentEncoder.h"
312#include "nsIDocumentLoaderFactory.h"
313#include "nsIDocumentViewer.h"
314#include "nsIDragService.h"
315#include "nsIDragSession.h"
316#include "nsIFile.h"
317#include "nsIFocusManager.h"
318#include "nsIFormControl.h"
319#include "nsIFragmentContentSink.h"
320#include "nsIFrame.h"
321#include "nsIGlobalObject.h"
322#include "nsIHttpChannel.h"
323#include "nsIHttpChannelInternal.h"
324#include "nsIIOService.h"
325#include "nsIImageLoadingContent.h"
326#include "nsIInputStream.h"
327#include "nsIInterfaceRequestor.h"
328#include "nsIInterfaceRequestorUtils.h"
329#include "nsILoadContext.h"
330#include "nsILoadGroup.h"
331#include "nsILoadInfo.h"
332#include "nsIMIMEService.h"
333#include "nsINetUtil.h"
334#include "nsINode.h"
335#include "nsIObjectLoadingContent.h"
336#include "nsIObserver.h"
337#include "nsIObserverService.h"
338#include "nsIParserUtils.h"
339#include "nsIPermissionManager.h"
340#include "nsIPrincipal.h"
341#include "nsIProperties.h"
342#include "nsIProtocolHandler.h"
343#include "nsIRequest.h"
344#include "nsIRunnable.h"
345#include "nsIScreen.h"
346#include "nsIScriptError.h"
347#include "nsIScriptGlobalObject.h"
348#include "nsIScriptObjectPrincipal.h"
349#include "nsIScriptSecurityManager.h"
350#include "nsISerialEventTarget.h"
351#include "nsIStreamConverter.h"
352#include "nsIStreamConverterService.h"
353#include "nsIStringBundle.h"
354#include "nsISupports.h"
355#include "nsISupportsPrimitives.h"
356#include "nsISupportsUtils.h"
357#include "nsITransferable.h"
358#include "nsIURI.h"
359#include "nsIURIMutator.h"
360#include "nsTHashMap.h"
361#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
362# include "nsIURIWithSpecialOrigin.h"
363#endif
364#include "nsIUserIdleServiceInternal.h"
365#include "nsIWeakReferenceUtils.h"
366#include "nsIWebNavigation.h"
367#include "nsIWebNavigationInfo.h"
368#include "nsIWidget.h"
369#include "nsIWindowMediator.h"
370#include "nsIXPConnect.h"
371#include "nsJSPrincipals.h"
372#include "nsJSUtils.h"
373#include "nsLayoutUtils.h"
374#include "nsLiteralString.h"
375#include "nsMargin.h"
376#include "nsMimeTypes.h"
377#include "nsNameSpaceManager.h"
378#include "nsNetCID.h"
379#include "nsNetUtil.h"
380#include "nsNodeInfoManager.h"
381#include "nsPIDOMWindow.h"
382#include "nsPIDOMWindowInlines.h"
383#include "nsParser.h"
384#include "nsParserConstants.h"
385#include "nsPoint.h"
386#include "nsPointerHashKeys.h"
387#include "nsPresContext.h"
388#include "nsQueryFrame.h"
389#include "nsQueryObject.h"
390#include "nsRange.h"
391#include "nsReadableUtils.h"
392#include "nsRefPtrHashtable.h"
393#include "nsSandboxFlags.h"
394#include "nsScriptSecurityManager.h"
395#include "nsServiceManagerUtils.h"
396#include "nsStreamUtils.h"
397#include "nsString.h"
398#include "nsStringBundle.h"
399#include "nsStringFlags.h"
400#include "nsStringFwd.h"
401#include "nsStringIterator.h"
402#include "nsStringStream.h"
403#include "nsTArray.h"
404#include "nsTLiteralString.h"
405#include "nsTPromiseFlatString.h"
406#include "nsTStringRepr.h"
407#include "nsTextNode.h"
408#include "nsThreadManager.h"
409#include "nsThreadUtils.h"
410#include "nsTreeSanitizer.h"
411#include "nsUGenCategory.h"
412#include "nsURLHelper.h"
413#include "nsUnicodeProperties.h"
414#include "nsVariant.h"
415#include "nsWhitespaceTokenizer.h"
416#include "nsWidgetsCID.h"
417#include "nsXPCOM.h"
418#include "nsXPCOMCID.h"
419#include "nsXULAppAPI.h"
420#include "nsXULElement.h"
421#include "nsXULPopupManager.h"
422#include "nscore.h"
423#include "prinrval.h"
424#include "xpcprivate.h"
425#include "xpcpublic.h"
426
427#if defined(XP_WIN)
428// Undefine LoadImage to prevent naming conflict with Windows.
429# undef LoadImage
430#endif
431
432extern "C" int MOZ_XMLTranslateEntity(const char* ptr, const char* end,
433 const char** next, char16_t* result);
434extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end, int ns_aware,
435 const char** colon);
436
437using namespace mozilla::dom;
438using namespace mozilla::ipc;
439using namespace mozilla::gfx;
440using namespace mozilla::layers;
441using namespace mozilla::widget;
442using namespace mozilla;
443
444const char kLoadAsData[] = "loadAsData";
445
446nsIXPConnect* nsContentUtils::sXPConnect;
447nsIScriptSecurityManager* nsContentUtils::sSecurityManager;
448nsIPrincipal* nsContentUtils::sSystemPrincipal;
449nsIPrincipal* nsContentUtils::sNullSubjectPrincipal;
450nsIPrincipal* nsContentUtils::sFingerprintingProtectionPrincipal;
451nsIConsoleService* nsContentUtils::sConsoleService;
452
453static nsTHashMap<RefPtr<nsAtom>, EventNameMapping>* sAtomEventTable;
454static nsTHashMap<nsStringHashKey, EventNameMapping>* sStringEventTable;
455static nsTArray<RefPtr<nsAtom>>* sUserDefinedEvents;
456nsIStringBundleService* nsContentUtils::sStringBundleService;
457
458static constexpr size_t kPropertiesFileCount =
459 static_cast<size_t>(PropertiesFile::COUNT);
460
461static StaticRefPtr<nsIStringBundle> sStringBundles[kPropertiesFileCount];
462
463nsIContentPolicy* nsContentUtils::sContentPolicyService;
464bool nsContentUtils::sTriedToGetContentPolicy = false;
465StaticRefPtr<nsIBidiKeyboard> nsContentUtils::sBidiKeyboard;
466uint32_t nsContentUtils::sScriptBlockerCount = 0;
467uint32_t nsContentUtils::sDOMNodeRemovedSuppressCount = 0;
468AutoTArray<nsCOMPtr<nsIRunnable>, 8>* nsContentUtils::sBlockedScriptRunners =
469 nullptr;
470uint32_t nsContentUtils::sRunnersCountAtFirstBlocker = 0;
471nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nullptr;
472
473bool nsContentUtils::sIsHandlingKeyBoardEvent = false;
474
475nsString* nsContentUtils::sShiftText = nullptr;
476nsString* nsContentUtils::sControlText = nullptr;
477nsString* nsContentUtils::sCommandOrWinText = nullptr;
478nsString* nsContentUtils::sAltText = nullptr;
479nsString* nsContentUtils::sModifierSeparator = nullptr;
480
481bool nsContentUtils::sInitialized = false;
482#ifndef RELEASE_OR_BETA
483bool nsContentUtils::sBypassCSSOMOriginCheck = false;
484#endif
485
486nsCString* nsContentUtils::sJSScriptBytecodeMimeType = nullptr;
487nsCString* nsContentUtils::sJSModuleBytecodeMimeType = nullptr;
488
489nsContentUtils::UserInteractionObserver*
490 nsContentUtils::sUserInteractionObserver = nullptr;
491
492nsHtml5StringParser* nsContentUtils::sHTMLFragmentParser = nullptr;
493nsParser* nsContentUtils::sXMLFragmentParser = nullptr;
494nsIFragmentContentSink* nsContentUtils::sXMLFragmentSink = nullptr;
495bool nsContentUtils::sFragmentParsingActive = false;
496
497mozilla::LazyLogModule nsContentUtils::gResistFingerprintingLog(
498 "nsResistFingerprinting");
499mozilla::LazyLogModule nsContentUtils::sDOMDumpLog("Dump");
500// Log when "input" and "beforeinput" events are dispatched or enqueued with
501// InputEvent:3,sync.
502mozilla::LazyLogModule gInputEventLog("InputEvent");
503
504int32_t nsContentUtils::sInnerOrOuterWindowCount = 0;
505uint32_t nsContentUtils::sInnerOrOuterWindowSerialCounter = 0;
506
507#define INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
508 aResultType, aMethodName, aTreeKind, ...) \
509 template aResultType aMethodName<aTreeKind>(__VA_ARGS__);
510
511#define INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS( \
512 aResultType, aMethodName, aTreeKind, ...) \
513 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
514 aResultType, aMethodName, aTreeKind, const RangeBoundary&, \
515 const RangeBoundary&, __VA_ARGS__) \
516 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
517 aResultType, aMethodName, aTreeKind, const RangeBoundary&, \
518 const RawRangeBoundary&, __VA_ARGS__) \
519 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
520 aResultType, aMethodName, aTreeKind, const RawRangeBoundary&, \
521 const RangeBoundary&, __VA_ARGS__) \
522 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
523 aResultType, aMethodName, aTreeKind, const RawRangeBoundary&, \
524 const RawRangeBoundary&, __VA_ARGS__) \
525 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
526 aResultType, aMethodName, aTreeKind, const ConstRawRangeBoundary&, \
527 const ConstRawRangeBoundary&, __VA_ARGS__) \
528 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
529 aResultType, aMethodName, aTreeKind, const ConstRawRangeBoundary&, \
530 const RangeBoundary&, __VA_ARGS__) \
531 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
532 aResultType, aMethodName, aTreeKind, const ConstRawRangeBoundary&, \
533 const RawRangeBoundary&, __VA_ARGS__) \
534 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
535 aResultType, aMethodName, aTreeKind, const RangeBoundary&, \
536 const ConstRawRangeBoundary&, __VA_ARGS__) \
537 INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM( \
538 aResultType, aMethodName, aTreeKind, const RawRangeBoundary&, \
539 const ConstRawRangeBoundary&, __VA_ARGS__)
540
541INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS(Maybe<int32_t>,
542 nsContentUtils::ComparePoints,
543 TreeKind::DOM,
544 NodeIndexCache*);
545INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS(Maybe<int32_t>,
546 nsContentUtils::ComparePoints,
547 TreeKind::ShadowIncludingDOM,
548 NodeIndexCache*);
549INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS(Maybe<int32_t>,
550 nsContentUtils::ComparePoints,
551 TreeKind::Flat,
552 NodeIndexCache*);
553INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS(Maybe<int32_t>,
554 nsContentUtils::ComparePoints,
555 TreeKind::FlatForSelection,
556 NodeIndexCache*);
557
558#undef INSTANTIATE_METHOD_FOR_CONST_RANGE_BOUNDARY_REFS
559#undef INSTANTIATE_METHOD_FOR_TREEKIND_TEMPLATE_PARAM
560
561// Subset of
562// http://www.whatwg.org/specs/web-apps/current-work/#autofill-field-name
563enum AutocompleteUnsupportedFieldName : uint8_t {
564#define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
565 eAutocompleteUnsupportedFieldName_##name_,
566#include "AutocompleteFieldList.h"
567#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
568};
569
570enum AutocompleteNoPersistFieldName : uint8_t {
571#define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \
572 eAutocompleteNoPersistFieldName_##name_,
573#include "AutocompleteFieldList.h"
574#undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME
575};
576
577enum AutocompleteUnsupportFieldContactHint : uint8_t {
578#define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
579 eAutocompleteUnsupportedFieldContactHint_##name_,
580#include "AutocompleteFieldList.h"
581#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
582};
583
584enum AutocompleteFieldName : uint8_t {
585#define AUTOCOMPLETE_FIELD_NAME(name_, value_) eAutocompleteFieldName_##name_,
586#define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
587 AUTOCOMPLETE_FIELD_NAME(name_, value_)
588#include "AutocompleteFieldList.h"
589#undef AUTOCOMPLETE_FIELD_NAME
590#undef AUTOCOMPLETE_CONTACT_FIELD_NAME
591};
592
593enum AutocompleteFieldHint : uint8_t {
594#define AUTOCOMPLETE_FIELD_HINT(name_, value_) eAutocompleteFieldHint_##name_,
595#include "AutocompleteFieldList.h"
596#undef AUTOCOMPLETE_FIELD_HINT
597};
598
599enum AutocompleteFieldContactHint : uint8_t {
600#define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
601 eAutocompleteFieldContactHint_##name_,
602#include "AutocompleteFieldList.h"
603#undef AUTOCOMPLETE_FIELD_CONTACT_HINT
604};
605
606enum AutocompleteCredentialType : uint8_t {
607#define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \
608 eAutocompleteCredentialType_##name_,
609#include "AutocompleteFieldList.h"
610#undef AUTOCOMPLETE_CREDENTIAL_TYPE
611};
612
613enum AutocompleteCategory {
614#define AUTOCOMPLETE_CATEGORY(name_, value_) eAutocompleteCategory_##name_,
615#include "AutocompleteFieldList.h"
616#undef AUTOCOMPLETE_CATEGORY
617};
618
619static constexpr nsAttrValue::EnumTableEntry
620 kAutocompleteUnsupportedFieldNameTable[]{
621#define AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME(name_, value_) \
622 {value_, eAutocompleteUnsupportedFieldName_##name_},
623#include "AutocompleteFieldList.h"
624#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_NAME
625 };
626
627static constexpr nsAttrValue::EnumTableEntry
628 kAutocompleteNoPersistFieldNameTable[] = {
629#define AUTOCOMPLETE_NO_PERSIST_FIELD_NAME(name_, value_) \
630 {value_, eAutocompleteNoPersistFieldName_##name_},
631#include "AutocompleteFieldList.h"
632#undef AUTOCOMPLETE_NO_PERSIST_FIELD_NAME
633};
634static constexpr nsAttrValue::EnumTableEntry
635 kAutocompleteUnsupportedContactFieldHintTable[] = {
636#define AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT(name_, value_) \
637 {value_, eAutocompleteUnsupportedFieldContactHint_##name_},
638#include "AutocompleteFieldList.h"
639#undef AUTOCOMPLETE_UNSUPPORTED_FIELD_CONTACT_HINT
640};
641
642static constexpr nsAttrValue::EnumTableEntry kAutocompleteFieldNameTable[] = {
643#define AUTOCOMPLETE_FIELD_NAME(name_, value_) \
644 {value_, eAutocompleteFieldName_##name_},
645#include "AutocompleteFieldList.h"
646#undef AUTOCOMPLETE_FIELD_NAME
647};
648
649static constexpr nsAttrValue::EnumTableEntry
650 kAutocompleteContactFieldNameTable[] = {
651#define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
652 {value_, eAutocompleteFieldName_##name_},
653#include "AutocompleteFieldList.h"
654#undef AUTOCOMPLETE_CONTACT_FIELD_NAME
655};
656
657static constexpr nsAttrValue::EnumTableEntry kAutocompleteFieldHintTable[] = {
658#define AUTOCOMPLETE_FIELD_HINT(name_, value_) \
659 {value_, eAutocompleteFieldHint_##name_},
660#include "AutocompleteFieldList.h"
661#undef AUTOCOMPLETE_FIELD_HINT
662};
663
664static constexpr nsAttrValue::EnumTableEntry
665 kAutocompleteContactFieldHintTable[] = {
666#define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
667 {value_, eAutocompleteFieldContactHint_##name_},
668#include "AutocompleteFieldList.h"
669#undef AUTOCOMPLETE_FIELD_CONTACT_HINT
670};
671
672static constexpr nsAttrValue::EnumTableEntry
673 kAutocompleteCredentialTypeTable[] = {
674#define AUTOCOMPLETE_CREDENTIAL_TYPE(name_, value_) \
675 {value_, eAutocompleteCredentialType_##name_},
676#include "AutocompleteFieldList.h"
677#undef AUTOCOMPLETE_CREDENTIAL_TYPE
678};
679
680namespace {
681
682// Non-owning list of the managers nodes store themselves; the managers remove
683// themselves from it when deleted. Documents keep their manager in
684// Document::mListenerManager and are not in this list.
685constinit DoublyLinkedList<EventListenerManager> sNodeEventListenerManagers;
686
687// A global hashtable to for keeping the arena alive for cross docGroup node
688// adoption.
689static nsRefPtrHashtable<nsPtrHashKey<const nsINode>, mozilla::dom::DOMArena>*
690 sDOMArenaHashtable;
691
692class SameOriginCheckerImpl final : public nsIChannelEventSink,
693 public nsIInterfaceRequestor {
694 ~SameOriginCheckerImpl() = default;
695
696 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
697 NS_DECL_NSICHANNELEVENTSINKvirtual nsresult AsyncOnChannelRedirect(nsIChannel *oldChannel
, nsIChannel *newChannel, uint32_t flags, nsIAsyncVerifyRedirectCallback
*callback) override;
698 NS_DECL_NSIINTERFACEREQUESTORvirtual nsresult GetInterface(const nsIID & uuid, void * *
result) override;
699};
700
701} // namespace
702
703void AutoSuppressEventHandling::SuppressDocument(Document* aDoc) {
704 // Note: Document::SuppressEventHandling will also automatically suppress
705 // event handling for any in-process sub-documents. However, since we need
706 // to deal with cases where remote BrowsingContexts may be interleaved
707 // with in-process ones, we still need to walk the entire tree ourselves.
708 // This may be slightly redundant in some cases, but since event handling
709 // suppressions maintain a count of current blockers, it does not cause
710 // any problems.
711 aDoc->SuppressEventHandling();
712}
713
714void AutoSuppressEventHandling::UnsuppressDocument(Document* aDoc) {
715 aDoc->UnsuppressEventHandlingAndFireEvents(true);
716}
717
718AutoSuppressEventHandling::~AutoSuppressEventHandling() {
719 UnsuppressDocuments();
720}
721
722void AutoSuppressEventHandlingAndSuspend::SuppressDocument(Document* aDoc) {
723 AutoSuppressEventHandling::SuppressDocument(aDoc);
724 if (nsCOMPtr<nsPIDOMWindowInner> win = aDoc->GetInnerWindow()) {
725 win->Suspend();
726 mWindows.AppendElement(win);
727 }
728}
729
730AutoSuppressEventHandlingAndSuspend::~AutoSuppressEventHandlingAndSuspend() {
731 for (const auto& win : mWindows) {
732 win->Resume();
733 }
734}
735
736// The following structs are used by CommonAncestors. They must have:
737// NodeType, Get(), ComputeChildIndex(), GetChildCount() and CanComputeIndex().
738// If CanComputeIndex() returns false, ComputeChildIndex() nor GetChildCount()
739// is not used by CommonAncestors to assert the odd result.
740
741/**
742 * GetParentNodeForComparison is used for implementing
743 * nsContentUtils::ComparePoints and its relatives and helpers.
744 */
745template <TreeKind aKind>
746struct GetParentNodeForComparison {
747 using NodeType = nsINode;
748 static NodeType* Get(const NodeType* aNode) {
749 if constexpr (aKind == TreeKind::DOM) {
750 return aNode->GetParentNode();
751 }
752 // We want to list up ShadowRoot as the parent of a child of ShadowRoot and
753 // its host as the parent of the ShadowRoot. GetFlattenedTreeParentNode()
754 // won't return ShadowRoot so that we cannot use
755 // nsINode::GetParentNode<aKind>() here.
756 if constexpr (ShouldHandleAssignedNodesOnSlot<aKind>()) {
757 if (aNode->IsContent()) {
758 if (HTMLSlotElement* const slot =
759 aNode->AsContent()->GetAssignedSlot<aKind>()) {
760 return slot;
761 }
762 // FIXME: If aNode->GetParentNode()->GetShadowRoot<aKind>() returns
763 // non-nullptr, we should always return nullptr here. However, if aKind
764 // is TreeKind::FlatForSelection, we cannot do that because
765 // GetFlattenedTreeParentNode<nsINode::eForSelection>() returns the
766 // shadow host element as-is. Therefore, we do the strict behavior only
767 // here causes assertion failures with the extant tests. This should
768 // be fixed in bug 2014622.
769 if constexpr (aKind != TreeKind::FlatForSelection) {
770 // If we're handling a flattened tree, we should return nullptr if the
771 // node is not part of a flattened tree.
772 if (nsINode* const parentNode = aNode->GetParentNode()) {
773 if (parentNode->GetShadowRoot<aKind>()) {
774 return nullptr;
775 }
776 }
777 }
778 }
779 }
780 return aNode->GetParentOrShadowHostNode();
781 }
782 static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent,
783 const nsIContent* aPossibleChild) {
784 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
785 return aParent->ComputeIndexOf(aPossibleChild);
786 } else {
787 return aParent->ComputeIndexOf<aKind>(aPossibleChild);
788 }
789 }
790 static uint32_t GetChildCount(const NodeType* aParent) {
791 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
792 return aParent->GetChildCount();
793 } else {
794 return aParent->GetChildCount<aKind>();
795 }
796 }
797 constexpr static bool CanComputeIndex() {
798 // The helpers of nsContentUtils::ComparePoints() and relatives require
799 // ComputeChildIndex() and GetChildCount(). Therefore, we implement them and
800 // return true.
801 return true;
802 }
803};
804
805/**
806 * GetParentNode is used for implementing
807 * nsContentUtils::GetClosestCommonInclusiveAncestor().
808 */
809using GetParentNode = GetParentNodeForComparison<TreeKind::DOM>;
810
811/**
812 * GetParentOrShadowHostNode is used for implementing
813 * nsContentUtils::GetClosestCommonShadowIncludingInclusiveAncestor().
814 */
815struct GetParentOrShadowHostNode {
816 using NodeType = nsINode;
817 static NodeType* Get(const NodeType* aNode) {
818 return aNode->GetParentOrShadowHostNode();
819 }
820 static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent,
821 const nsIContent* aPossibleChild) {
822 return aParent->ComputeIndexOf(aPossibleChild);
823 }
824 static uint32_t GetChildCount(const NodeType* aParent) {
825 return aParent->GetChildCount();
826 }
827 constexpr static bool CanComputeIndex() {
828 // Neither ComputeChildIndex() nor GetChildCount() is required by
829 // nsContentUtils::GetClosestCommonShadowIncludingInclusiveAncestor(), but
830 // let's implement them to make CommonAncestors asserts the odd situations
831 // so that return true.
832 return true;
833 }
834};
835
836/**
837 * GetFlattenedTreeParent is used for implementing
838 * nsContentUtils::GetCommonFlattenedTreeAncestor().
839 */
840struct GetFlattenedTreeParent {
841 using NodeType = nsIContent;
842 static NodeType* Get(const NodeType* aContent) {
843 return aContent->GetFlattenedTreeParent();
844 }
845 static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent,
846 const nsIContent* aPossibleChild) {
847 return aParent->ComputeFlatTreeIndexOf(aPossibleChild);
848 }
849 static uint32_t GetChildCount(const NodeType* aParent) {
850 return aParent->GetFlatTreeChildCount();
851 }
852 constexpr static bool CanComputeIndex() {
853 // Neither ComputeChildIndex() nor GetChildCount() is required by
854 // nsContentUtils::GetCommonFlattenedTreeAncestor(), but let's implement
855 // them to make CommonAncestors asserts the odd situations so that return
856 // true.
857 return true;
858 }
859};
860
861/**
862 * GetFlattenedTreeParentNodeForSelection is used for implementing
863 * nsContentUtils::GetCommonFlattenedTreeAncestorForSelection().
864 */
865struct GetFlattenedTreeParentNodeForSelection {
866 using NodeType = nsINode;
867 static NodeType* Get(const NodeType* aNode) {
868 return aNode->GetFlattenedTreeParentNodeForSelection();
869 }
870 static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent,
871 const nsIContent* aPossibleChild) {
872 return aParent->ComputeFlatTreeForSelectionIndexOf(aPossibleChild);
873 }
874 static uint32_t GetChildCount(const NodeType* aParent) {
875 return aParent->GetFlatTreeForSelectionChildCount();
876 }
877 constexpr static bool CanComputeIndex() {
878 // Neither ComputeChildIndex() nor GetChildCount() is required by
879 // nsContentUtils::GetCommonFlattenedTreeAncestorForSelection(), but let's
880 // implement them to make CommonAncestors asserts the odd situations so that
881 // return true.
882 return true;
883 }
884};
885
886/**
887 * GetFlattenedTreeParentElementForStyle is used for implementing
888 * nsContentUtils::GetCommonFlattenedTreeAncestorForStyle().
889 */
890struct GetFlattenedTreeParentElementForStyle {
891 using NodeType = Element;
892 static NodeType* Get(const NodeType* aElement) {
893 return aElement->GetFlattenedTreeParentElementForStyle();
894 }
895 static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent,
896 const nsIContent* aPossibleChild) {
897 return Nothing();
898 }
899 static uint32_t GetChildCount(const NodeType* aParent) {
900 return 0; // This should be called only when CanComputeIndex() returns true
901 }
902 constexpr static bool CanComputeIndex() {
903 // Neither ComputeChildIndex() nor GetChildCount() is required by
904 // nsContentUtils::GetCommonFlattenedTreeAncestorForStyle() and there is no
905 // API to get child count nor compute index of a child in the flattened tree
906 // for style. Therefore, we don't implement them so that return false.
907 return false;
908 }
909};
910
911/**
912 * GetParentBrowserParent is used for implementing
913 * nsContentUtils::GetCommonBrowserParentAncestor().
914 */
915struct GetParentBrowserParent {
916 using NodeType = BrowserParent;
917 static NodeType* Get(const NodeType* aBrowserParent) {
918 return aBrowserParent->GetBrowserBridgeParent()
919 ? aBrowserParent->GetBrowserBridgeParent()->Manager()
920 : nullptr;
921 }
922 static Maybe<uint32_t> ComputeChildIndex(const NodeType* aParent,
923 const nsIContent* aPossibleChild) {
924 return Nothing();
925 }
926 static uint32_t GetChildCount(const NodeType* aParent) {
927 return 0; // This should be called only when CanComputeIndex() returns true
928 }
929 constexpr static bool CanComputeIndex() {
930 // Neither ComputeChildIndex() nor GetChildCount() is required by
931 // nsContentUtils::GetCommonBrowserParentAncestor() and there is no API to
932 // get child count of a BrowserParent nor compute index of a child of
933 // BrowserParent. Therefore, we don't implement them so that return false.
934 return false;
935 }
936};
937
938template <TreeKind aKind>
939static bool ChildNodeIsInShadowDOMHostedByParent(const nsINode* aParent,
940 const nsINode* aChild) {
941 ShadowRoot* const shadowRoot = aParent->GetShadowRoot<aKind>();
942 if (!shadowRoot) {
943 return false;
944 }
945 // We already checked whether aChild is in a shadow in the tree kind.
946 // Therefore, we don't need to use GetContainingShadowForSelection() here.
947 return shadowRoot == aChild->GetContainingShadow();
948}
949
950// If we're comparing 2 DOM points in TreeKind::ShadowIncludingDOM mode, we want
951// to compare the direct children of the parent node even if the parent is a
952// shadow host. So, we want to compare them as TreeKind::DOM.
953template <TreeKind aKind>
954constexpr TreeKind TreeKindToCompareChildren() {
955 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
956 return TreeKind::DOM;
957 } else {
958 return aKind;
959 }
960}
961
962template <class GetParentStruct>
963class MOZ_STACK_CLASS CommonAncestors final {
964 public:
965 using NodeType = GetParentStruct::NodeType;
966
967 /**
968 * @param aNode1 A DOM node or something which may have ancestors.
969 * @param aNode2 Another DOM node or something.
970 * @param aGetParentStruct A struct containing static GetParent(),
971 * ComputeChildIndex(), GetChildCount() and CanComputeIndex(). If
972 * CanComputeIndex() returns false, ComputeChildIndex() nor GetChildCount() is
973 * never used.
974 */
975 CommonAncestors(const NodeType& aNode1, const NodeType& aNode2) {
976#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1
977 mAssertNoGC.emplace();
978#endif // #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
979
980 AppendInclusiveAncestors(const_cast<NodeType*>(&aNode1),
981 mInclusiveAncestors1);
982 AppendInclusiveAncestors(const_cast<NodeType*>(&aNode2),
983 mInclusiveAncestors2);
984
985 // Find where the parent chain differs
986 size_t depth1 = mInclusiveAncestors1.Length();
987 size_t depth2 = mInclusiveAncestors2.Length();
988 const size_t shorterLength = std::min(depth1, depth2);
989 NodeType** const inclusiveAncestors1 = mInclusiveAncestors1.Elements();
990 NodeType** const inclusiveAncestors2 = mInclusiveAncestors2.Elements();
991 for ([[maybe_unused]] const size_t unused : IntegerRange(shorterLength)) {
992 NodeType* const inclusiveAncestor1 = inclusiveAncestors1[--depth1];
993 NodeType* const inclusiveAncestor2 = inclusiveAncestors2[--depth2];
994 if (inclusiveAncestor1 != inclusiveAncestor2) {
995 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"
, 996); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inclusiveAncestor1 == GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 996); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
996 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"
, 996); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inclusiveAncestor1 == GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 996); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
997 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"
, 998); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inclusiveAncestor2 == GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 998); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
998 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"
, 998); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inclusiveAncestor2 == GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 998); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
999 return;
1000 }
1001 mNumberOfCommonAncestors++;
1002 mClosestCommonAncestor = inclusiveAncestor1;
1003 }
1004 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", 1004); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mClosestCommonAncestor" ")"); do { MOZ_CrashSequence
(__null, 1004); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1005 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", 1005); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mNumberOfCommonAncestors" ")"); do { MOZ_CrashSequence
(__null, 1005); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1006 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", 1006); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!depth1 || !depth2" ")"); do { MOZ_CrashSequence
(__null, 1006); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1007 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", 1007); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!GetClosestCommonAncestorChild1()" ")"); do
{ MOZ_CrashSequence(__null, 1007); __attribute__((nomerge)) ::
abort(); } while (false); } } 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(!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", 1009); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!GetClosestCommonAncestorChild2()" ")"); 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 }
1012
1013#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1
1014 ~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", 1014); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "!mMutationGuard.Mutated(0)" ")"
); do { MOZ_CrashSequence(__null, 1014); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; }
1015#endif // #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
1016
1017 [[nodiscard]] NodeType* GetClosestCommonAncestor() const {
1018 return mClosestCommonAncestor;
1019 }
1020 [[nodiscard]] NodeType* GetClosestCommonAncestorChild1() const {
1021 return GetClosestCommonAncestorChild(mInclusiveAncestors1);
1022 }
1023 [[nodiscard]] NodeType* GetClosestCommonAncestorChild2() const {
1024 return GetClosestCommonAncestorChild(mInclusiveAncestors2);
1025 }
1026
1027 template <TreeKind aKind>
1028 void WarnIfClosestCommonAncestorChildrenAreNotInChildList() const {
1029 WarnIfClosestCommonAncestorChildIsNotInChildList<aKind>(
1030 mInclusiveAncestors1);
1031 WarnIfClosestCommonAncestorChildIsNotInChildList<aKind>(
1032 mInclusiveAncestors2);
1033 }
1034
1035 private:
1036 static void AppendInclusiveAncestors(NodeType* aNode,
1037 nsTArray<NodeType*>& aArrayOfParents) {
1038 NodeType* node = aNode;
1039 while (node) {
1040 aArrayOfParents.AppendElement(node);
1041 node = GetParentStruct::Get(node);
1042 }
1043 }
1044
1045 Maybe<size_t> GetClosestCommonAncestorChildIndex(
1046 const nsTArray<NodeType*>& aInclusiveAncestors) const {
1047 if (!mClosestCommonAncestor ||
1048 aInclusiveAncestors.Length() <= mNumberOfCommonAncestors) {
1049 return Nothing();
1050 }
1051 return Some((aInclusiveAncestors.Length() - 1) // last index
1052 - mNumberOfCommonAncestors); // before closest common ancestor
1053 }
1054
1055 [[nodiscard]] NodeType* GetClosestCommonAncestorChild(
1056 const nsTArray<NodeType*>& aInclusiveAncestors) const {
1057 const Maybe<size_t> index =
1058 GetClosestCommonAncestorChildIndex(aInclusiveAncestors);
1059 if (index.isNothing()) {
1060 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", 1061); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aInclusiveAncestors.Length() == mNumberOfCommonAncestors"
")"); do { MOZ_CrashSequence(__null, 1061); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
1061 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", 1061); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aInclusiveAncestors.Length() == mNumberOfCommonAncestors"
")"); do { MOZ_CrashSequence(__null, 1061); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1062 return nullptr;
1063 }
1064 NodeType* const child = aInclusiveAncestors[*index];
1065 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"
, 1065); AnnotateMozCrashReason("MOZ_ASSERT" "(" "child" ")")
; do { MOZ_CrashSequence(__null, 1065); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1066 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"
, 1066); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetParentStruct::Get(child) == mClosestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 1066); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1067 return child;
1068 }
1069
1070 template <TreeKind aKind>
1071 void WarnIfClosestCommonAncestorChildIsNotInChildList(
1072 const nsTArray<NodeType*>& aInclusiveAncestors) const {
1073#ifdef DEBUG1
1074 if constexpr (std::is_base_of_v<nsINode, NodeType>) {
1075 if (!GetParentStruct::CanComputeIndex()) {
1076 return;
1077 }
1078 const nsIContent* const child = nsIContent::FromNodeOrNull(
1079 GetClosestCommonAncestorChild(aInclusiveAncestors));
1080 if (!child) {
1081 return;
1082 }
1083
1084 if (child->IsShadowRoot() ||
1085 (ShouldHandleAssignedNodesOnSlot<aKind>() &&
1086 child->GetAssignedSlot<aKind>() &&
1087 mClosestCommonAncestor != child->GetAssignedSlot<aKind>())) {
1088 return;
1089 }
1090
1091 if (MOZ_LIKELY((__builtin_expect(!!(GetParentStruct::ComputeChildIndex(mClosestCommonAncestor
, child) .isSome()), 1))
1092 GetParentStruct::ComputeChildIndex(mClosestCommonAncestor, child)(__builtin_expect(!!(GetParentStruct::ComputeChildIndex(mClosestCommonAncestor
, child) .isSome()), 1))
1093 .isSome())(__builtin_expect(!!(GetParentStruct::ComputeChildIndex(mClosestCommonAncestor
, child) .isSome()), 1))
) {
1094 return;
1095 }
1096 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
1097 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"
, 1097)
;
1098 const nsINode* const parentOrShadowHostNode =
1099 child->GetParentOrShadowHostNode();
1100 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"
, 1110)
1101 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"
, 1110)
1102 "\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"
, 1110)
1103 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"
, 1110)
1104 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"
, 1110)
1105 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"
, 1110)
1106 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"
, 1110)
1107 ? 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"
, 1110)
1108 : 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"
, 1110)
1109 .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"
, 1110)
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"
, 1110)
;
1111 } else if constexpr (aKind == TreeKind::FlatForSelection) {
1112 if (child->GetParentNode() == mClosestCommonAncestor) {
1113 // It's okay to compare the non-assigned children of a shadow host
1114 // with the shadow root or another non-assigned child if we're
1115 // handling the flattened tree for selection.
1116 if (mClosestCommonAncestor->GetShadowRootForSelection()) {
1117 return;
1118 }
1119 // It's okay to compare the fallback content of a <slot> which has
1120 // some assigned nodes and a parent of the flattened tree if we're
1121 // handling the flattened tree for selection.
1122 if (mClosestCommonAncestor
1123 ->GetAsHTMLSlotElementIfFilledForSelection()) {
1124 return;
1125 }
1126 }
1127 }
1128 const Maybe<size_t> index =
1129 GetClosestCommonAncestorChildIndex(aInclusiveAncestors);
1130 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"
, 1142)
1131 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"
, 1142)
1132 "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"
, 1142)
1133 "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"
, 1142)
1134 "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"
, 1142)
1135 " {}\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"
, 1142)
1136 " + {}\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"
, 1142)
1137 "{}", // 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"
, 1142)
1138 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"
, 1142)
1139 *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"
, 1142)
1140 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"
, 1142)
1141 : "")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"
, 1142)
1142 .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"
, 1142)
;
1143 }
1144#endif
1145 }
1146
1147 AutoTArray<NodeType*, 30> mInclusiveAncestors1;
1148 AutoTArray<NodeType*, 30> mInclusiveAncestors2;
1149 NodeType* mClosestCommonAncestor = nullptr;
1150 uint32_t mNumberOfCommonAncestors = 0;
1151
1152#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED1
1153 nsMutationGuard mMutationGuard;
1154 Maybe<JS::AutoAssertNoGC> mAssertNoGC;
1155#endif
1156};
1157
1158/**
1159 * This class is used to determine whether or not the user is currently
1160 * interacting with the browser. It listens to observer events to toggle the
1161 * value of the sUserActive static.
1162 *
1163 * This class is an internal implementation detail.
1164 * nsContentUtils::GetUserIsInteracting() should be used to access current
1165 * user interaction status.
1166 */
1167class nsContentUtils::UserInteractionObserver final
1168 : public nsIObserver,
1169 public BackgroundHangAnnotator {
1170 public:
1171 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:
1172 NS_DECL_NSIOBSERVERvirtual nsresult Observe(nsISupports *aSubject, const char * aTopic
, const char16_t * aData) override;
1173
1174 void Init();
1175 void Shutdown();
1176 void AnnotateHang(BackgroundHangAnnotations& aAnnotations) override;
1177
1178 static Atomic<bool> sUserActive;
1179
1180 private:
1181 ~UserInteractionObserver() = default;
1182};
1183
1184static constexpr nsLiteralCString kRfpPrefs[] = {
1185 "privacy.resistFingerprinting"_ns,
1186 "privacy.resistFingerprinting.pbmode"_ns,
1187 "privacy.fingerprintingProtection"_ns,
1188 "privacy.fingerprintingProtection.pbmode"_ns,
1189 "privacy.fingerprintingProtection.overrides"_ns,
1190 "privacy.baselineFingerprintingProtection"_ns,
1191 "privacy.baselineFingerprintingProtection.overrides"_ns,
1192};
1193
1194static void RecomputeResistFingerprintingAllDocs(const char*, void*) {
1195 AutoTArray<RefPtr<Document>, 64> allDocuments;
1196 Document::GetAllInProcessDocuments(allDocuments);
1197 for (auto& doc : allDocuments) {
1198 doc->RecomputeResistFingerprinting(
1199 /* aForceRefreshRTPCallerType= */ true);
1200 if (auto* pc = doc->GetPresContext()) {
1201 pc->MediaFeatureValuesChanged(
1202 {MediaFeatureChangeReason::PreferenceChange},
1203 MediaFeatureChangePropagation::JustThisDocument);
1204 }
1205 }
1206}
1207
1208// static
1209nsresult nsContentUtils::Init() {
1210 if (sInitialized) {
1211 NS_WARNING("Init() called twice")NS_DebugBreak(NS_DEBUG_WARNING, "Init() called twice", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 1211)
;
1212
1213 return NS_OK;
1214 }
1215
1216 nsHTMLTags::AddRefTable();
1217
1218 sXPConnect = nsXPConnect::XPConnect();
1219 // We hold a strong ref to sXPConnect to ensure that it does not go away until
1220 // nsLayoutStatics::Shutdown is happening. Otherwise ~nsXPConnect can be
1221 // triggered by xpcModuleDtor late in shutdown and cause crashes due to
1222 // various stuff already being torn down by then. Note that this means that
1223 // we are effectively making sure that if we leak nsLayoutStatics then we also
1224 // leak nsXPConnect.
1225 NS_ADDREF(sXPConnect)(sXPConnect)->AddRef();
1226
1227 sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager();
1228 if (!sSecurityManager) return NS_ERROR_FAILURE;
1229 NS_ADDREF(sSecurityManager)(sSecurityManager)->AddRef();
1230
1231 sSecurityManager->GetSystemPrincipal(&sSystemPrincipal);
1232 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", 1232); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sSystemPrincipal" ")"); do { MOZ_CrashSequence
(__null, 1232); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1233
1234 RefPtr<NullPrincipal> nullPrincipal =
1235 NullPrincipal::CreateWithoutOriginAttributes();
1236 if (!nullPrincipal) {
1237 return NS_ERROR_FAILURE;
1238 }
1239
1240 nullPrincipal.forget(&sNullSubjectPrincipal);
1241
1242 RefPtr<nsIPrincipal> fingerprintingProtectionPrincipal =
1243 BasePrincipal::CreateContentPrincipal(
1244 "about:fingerprintingprotection"_ns);
1245 if (!fingerprintingProtectionPrincipal) {
1246 return NS_ERROR_FAILURE;
1247 }
1248
1249 fingerprintingProtectionPrincipal.forget(&sFingerprintingProtectionPrincipal);
1250
1251 if (!InitializeEventTable()) return NS_ERROR_FAILURE;
1252
1253 sBlockedScriptRunners = new AutoTArray<nsCOMPtr<nsIRunnable>, 8>;
1254
1255#ifndef RELEASE_OR_BETA
1256 sBypassCSSOMOriginCheck = getenv("MOZ_BYPASS_CSSOM_ORIGIN_CHECK");
1257#endif
1258
1259 Element::InitCCCallbacks();
1260
1261 RefPtr<nsRFPService> rfpService = nsRFPService::GetOrCreate();
1262 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"
, 1262); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rfpService"
")"); do { MOZ_CrashSequence(__null, 1262); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1263
1264 if (XRE_IsParentProcess()) {
1265 AsyncPrecreateStringBundles();
1266
1267#if defined(MOZ_WIDGET_ANDROID)
1268 // On Android, at-shutdown ping submission isn't reliable
1269 // (( because, on Android, we usually get killed, not shut down )).
1270 // To have a chance at submitting the ping, aim for idle after startup.
1271 nsresult rv = NS_DispatchToCurrentThreadQueue(
1272 NS_NewRunnableFunction(
1273 "AndroidUseCounterPingSubmitter",
1274 []() { glean_pings::UseCounters.Submit("idle_startup"_ns); }),
1275 EventQueuePriority::Idle);
1276 // This is mostly best-effort, so if it goes awry, just log.
1277 (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"
, 1277)
;
1278#endif // defined(MOZ_WIDGET_ANDROID)
1279
1280 RunOnShutdown(
1281 [&] { glean_pings::UseCounters.Submit("app_shutdown_confirmed"_ns); },
1282 ShutdownPhase::AppShutdownConfirmed);
1283
1284 // On child process, this is initialized in ContentChild.
1285 LookAndFeel::EnsureInit();
1286 }
1287
1288 RefPtr<UserInteractionObserver> uio = new UserInteractionObserver();
1289 uio->Init();
1290 uio.forget(&sUserInteractionObserver);
1291
1292 for (const auto& pref : kRfpPrefs) {
1293 Preferences::RegisterCallback(RecomputeResistFingerprintingAllDocs, pref);
1294 }
1295
1296 mozilla::dom::ReportDeliver::Initialize();
1297
1298 sInitialized = true;
1299
1300 return NS_OK;
1301}
1302
1303bool nsContentUtils::InitJSBytecodeMimeType() {
1304 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", 1304); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 1304); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1305 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", 1305); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!sJSScriptBytecodeMimeType" ")"); do { MOZ_CrashSequence
(__null, 1305); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1306 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", 1306); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!sJSModuleBytecodeMimeType" ")"); do { MOZ_CrashSequence
(__null, 1306); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1307
1308 JS::BuildIdCharVector jsBuildId;
1309 if (!JS::GetScriptTranscodingBuildId(&jsBuildId)) {
1310 return false;
1311 }
1312
1313 nsDependentCSubstring jsBuildIdStr(jsBuildId.begin(), jsBuildId.length());
1314 sJSScriptBytecodeMimeType =
1315 new nsCString("javascript/moz-script-bytecode-"_ns + jsBuildIdStr);
1316 sJSModuleBytecodeMimeType =
1317 new nsCString("javascript/moz-module-bytecode-"_ns + jsBuildIdStr);
1318 return true;
1319}
1320
1321void nsContentUtils::GetShiftText(nsAString& text) {
1322 if (!sShiftText) InitializeModifierStrings();
1323 text.Assign(*sShiftText);
1324}
1325
1326void nsContentUtils::GetControlText(nsAString& text) {
1327 if (!sControlText) InitializeModifierStrings();
1328 text.Assign(*sControlText);
1329}
1330
1331void nsContentUtils::GetCommandOrWinText(nsAString& text) {
1332 if (!sCommandOrWinText) {
1333 InitializeModifierStrings();
1334 }
1335 text.Assign(*sCommandOrWinText);
1336}
1337
1338void nsContentUtils::GetAltText(nsAString& text) {
1339 if (!sAltText) InitializeModifierStrings();
1340 text.Assign(*sAltText);
1341}
1342
1343void nsContentUtils::GetModifierSeparatorText(nsAString& text) {
1344 if (!sModifierSeparator) InitializeModifierStrings();
1345 text.Assign(*sModifierSeparator);
1346}
1347
1348void nsContentUtils::InitializeModifierStrings() {
1349 // load the display strings for the keyboard accelerators
1350 nsCOMPtr<nsIStringBundleService> bundleService =
1351 mozilla::components::StringBundle::Service();
1352 nsCOMPtr<nsIStringBundle> bundle;
1353 DebugOnly<nsresult> rv = NS_OK;
1354 if (bundleService) {
1355 rv = bundleService->CreateBundle(
1356 "chrome://global-platform/locale/platformKeys.properties",
1357 getter_AddRefs(bundle));
1358 }
1359
1360 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"
, 1362); MOZ_PretendNoReturn(); } } while (0)
1361 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"
, 1362); MOZ_PretendNoReturn(); } } while (0)
1362 "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"
, 1362); MOZ_PretendNoReturn(); } } while (0)
;
1363 nsAutoString shiftModifier;
1364 nsAutoString commandOrWinModifier;
1365 nsAutoString altModifier;
1366 nsAutoString controlModifier;
1367 nsAutoString modifierSeparator;
1368 if (bundle) {
1369 // macs use symbols for each modifier key, so fetch each from the bundle,
1370 // which also covers i18n
1371 bundle->GetStringFromName("VK_SHIFT", shiftModifier);
1372 bundle->GetStringFromName("VK_COMMAND_OR_WIN", commandOrWinModifier);
1373 bundle->GetStringFromName("VK_ALT", altModifier);
1374 bundle->GetStringFromName("VK_CONTROL", controlModifier);
1375 bundle->GetStringFromName("MODIFIER_SEPARATOR", modifierSeparator);
1376 }
1377 // if any of these don't exist, we get an empty string
1378 sShiftText = new nsString(std::move(shiftModifier));
1379 sCommandOrWinText = new nsString(std::move(commandOrWinModifier));
1380 sAltText = new nsString(std::move(altModifier));
1381 sControlText = new nsString(std::move(controlModifier));
1382 sModifierSeparator = new nsString(std::move(modifierSeparator));
1383}
1384
1385mozilla::EventClassID nsContentUtils::GetEventClassIDFromMessage(
1386 EventMessage aEventMessage) {
1387 switch (aEventMessage) {
1388#define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
1389 case message_: \
1390 return struct_;
1391#include "mozilla/EventNameList.inc"
1392#undef MESSAGE_TO_EVENT
1393 default:
1394 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"
, 1394); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Invalid event message?" ")"); do
{ MOZ_CrashSequence(__null, 1394); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1395 return eBasicEventClass;
1396 }
1397}
1398
1399bool nsContentUtils::IsExternalProtocol(nsIURI* aURI) {
1400 bool doesNotReturnData = false;
1401 nsresult rv = NS_URIChainHasFlags(
1402 aURI, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA, &doesNotReturnData);
1403 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && doesNotReturnData;
1404}
1405
1406/* static */
1407nsAtom* nsContentUtils::GetEventTypeFromMessage(EventMessage aEventMessage) {
1408 switch (aEventMessage) {
1409#define MESSAGE_TO_EVENT(name_, message_, type_, struct_) \
1410 case message_: \
1411 return nsGkAtoms::on##name_;
1412#include "mozilla/EventNameList.inc"
1413#undef MESSAGE_TO_EVENT
1414 default:
1415 return nullptr;
1416 }
1417}
1418
1419/* static */
1420already_AddRefed<nsAtom> nsContentUtils::GetEventType(
1421 const WidgetEvent* aEvent) {
1422 RefPtr<nsAtom> typeAtom =
1423 aEvent->mMessage == eUnidentifiedEvent
1424 ? aEvent->mSpecifiedEventType.get()
1425 : nsContentUtils::GetEventTypeFromMessage(aEvent->mMessage);
1426 return typeAtom.forget();
1427}
1428
1429bool nsContentUtils::InitializeEventTable() {
1430 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"
, 1430); MOZ_PretendNoReturn(); } } while (0)
;
1431 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"
, 1431); MOZ_PretendNoReturn(); } } while (0)
;
1432
1433 static const EventNameMapping eventArray[] = {
1434#define EVENT(name_, _message, _type, _class) \
1435 {nsGkAtoms::on##name_, _type, _message, _class},
1436#define WINDOW_ONLY_EVENT EVENT
1437#define DOCUMENT_ONLY_EVENTEVENT EVENT
1438#define NON_IDL_EVENT EVENT
1439#include "mozilla/EventNameList.inc"
1440#undef WINDOW_ONLY_EVENT
1441#undef NON_IDL_EVENT
1442#undef EVENT
1443 {nullptr}};
1444
1445 sAtomEventTable =
1446 new nsTHashMap<RefPtr<nsAtom>, EventNameMapping>(std::size(eventArray));
1447 sStringEventTable =
1448 new nsTHashMap<nsStringHashKey, EventNameMapping>(std::size(eventArray));
1449 sUserDefinedEvents = new nsTArray<RefPtr<nsAtom>>(64);
1450
1451 // Subtract one from the length because of the trailing null
1452 for (uint32_t i = 0; i < std::size(eventArray) - 1; ++i) {
1453 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", 1454
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sAtomEventTable->Contains(eventArray[i].mAtom)"
") (" "Double-defining event name; fix your EventNameList.inc"
")"); do { MOZ_CrashSequence(__null, 1454); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1454 "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", 1454
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sAtomEventTable->Contains(eventArray[i].mAtom)"
") (" "Double-defining event name; fix your EventNameList.inc"
")"); do { MOZ_CrashSequence(__null, 1454); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1455 sAtomEventTable->InsertOrUpdate(eventArray[i].mAtom, eventArray[i]);
1456 sStringEventTable->InsertOrUpdate(
1457 Substring(nsDependentAtomString(eventArray[i].mAtom), 2),
1458 eventArray[i]);
1459 }
1460
1461 return true;
1462}
1463
1464void nsContentUtils::InitializeTouchEventTable() {
1465 static bool sEventTableInitialized = false;
1466 if (!sEventTableInitialized && sAtomEventTable && sStringEventTable) {
1467 sEventTableInitialized = true;
1468 static const EventNameMapping touchEventArray[] = {
1469#define EVENT(name_, _message, _type, _class)
1470#define TOUCH_EVENT(name_, _message, _type, _class) \
1471 {nsGkAtoms::on##name_, _type, _message, _class},
1472#include "mozilla/EventNameList.inc"
1473#undef TOUCH_EVENT
1474#undef EVENT
1475 {nullptr}};
1476 // Subtract one from the length because of the trailing null
1477 for (uint32_t i = 0; i < std::size(touchEventArray) - 1; ++i) {
1478 sAtomEventTable->InsertOrUpdate(touchEventArray[i].mAtom,
1479 touchEventArray[i]);
1480 sStringEventTable->InsertOrUpdate(
1481 Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2),
1482 touchEventArray[i]);
1483 }
1484 }
1485}
1486
1487static bool Is8bit(const nsAString& aString) {
1488 static const char16_t EIGHT_BIT = char16_t(~0x00FF);
1489
1490 for (nsAString::const_char_iterator start = aString.BeginReading(),
1491 end = aString.EndReading();
1492 start != end; ++start) {
1493 if (*start & EIGHT_BIT) {
1494 return false;
1495 }
1496 }
1497
1498 return true;
1499}
1500
1501nsresult nsContentUtils::Btoa(const nsAString& aBinaryData,
1502 nsAString& aAsciiBase64String) {
1503 if (!Is8bit(aBinaryData)) {
1504 aAsciiBase64String.Truncate();
1505 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1506 }
1507
1508 return Base64Encode(aBinaryData, aAsciiBase64String);
1509}
1510
1511nsresult nsContentUtils::Atob(const nsAString& aAsciiBase64String,
1512 nsAString& aBinaryData) {
1513 if (!Is8bit(aAsciiBase64String)) {
1514 aBinaryData.Truncate();
1515 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1516 }
1517
1518 const char16_t* start = aAsciiBase64String.BeginReading();
1519 const char16_t* cur = start;
1520 const char16_t* end = aAsciiBase64String.EndReading();
1521 bool hasWhitespace = false;
1522
1523 while (cur < end) {
1524 if (nsContentUtils::IsHTMLWhitespace(*cur)) {
1525 hasWhitespace = true;
1526 break;
1527 }
1528 cur++;
1529 }
1530
1531 nsresult rv;
1532
1533 if (hasWhitespace) {
1534 nsString trimmedString;
1535
1536 if (!trimmedString.SetCapacity(aAsciiBase64String.Length(), fallible)) {
1537 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1538 }
1539
1540 trimmedString.Append(start, cur - start);
1541
1542 while (cur < end) {
1543 if (!nsContentUtils::IsHTMLWhitespace(*cur)) {
1544 trimmedString.Append(*cur);
1545 }
1546 cur++;
1547 }
1548 rv = Base64Decode(trimmedString, aBinaryData);
1549 } else {
1550 rv = Base64Decode(aAsciiBase64String, aBinaryData);
1551 }
1552
1553 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && rv == NS_ERROR_INVALID_ARG) {
1554 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
1555 }
1556 return rv;
1557}
1558
1559bool nsContentUtils::IsAutocompleteEnabled(mozilla::dom::Element* aElement) {
1560 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", 1560
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ") (" "aElement should not be null!"
")"); do { MOZ_CrashSequence(__null, 1560); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1561
1562 nsAutoString autocomplete;
1563
1564 if (auto* input = HTMLInputElement::FromNodeOrNull(aElement)) {
1565 input->GetAutocomplete(autocomplete);
1566 } else if (auto* textarea = HTMLTextAreaElement::FromNodeOrNull(aElement)) {
1567 textarea->GetAutocomplete(autocomplete);
1568 }
1569
1570 if (autocomplete.IsEmpty()) {
1571 auto* control = nsGenericHTMLFormControlElement::FromNode(aElement);
1572 auto* form = control->GetFormInternal();
1573 if (!form) {
1574 return true;
1575 }
1576
1577 form->GetAutocomplete(autocomplete);
1578 }
1579
1580 return !autocomplete.EqualsLiteral("off");
1581}
1582
1583nsContentUtils::AutocompleteAttrState
1584nsContentUtils::SerializeAutocompleteAttribute(
1585 const nsAttrValue* aAttr, nsAString& aResult,
1586 AutocompleteAttrState aCachedState) {
1587 if (!aAttr ||
1588 aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) {
1589 return aCachedState;
1590 }
1591
1592 if (aCachedState == nsContentUtils::eAutocompleteAttrState_Valid) {
1593 uint32_t atomCount = aAttr->GetAtomCount();
1594 for (uint32_t i = 0; i < atomCount; i++) {
1595 if (i != 0) {
1596 aResult.Append(' ');
1597 }
1598 aResult.Append(nsDependentAtomString(aAttr->AtomAt(i)));
1599 }
1600 nsContentUtils::ASCIIToLower(aResult);
1601 return aCachedState;
1602 }
1603
1604 aResult.Truncate();
1605
1606 mozilla::dom::AutocompleteInfo info;
1607 AutocompleteAttrState state =
1608 InternalSerializeAutocompleteAttribute(aAttr, info);
1609 if (state == eAutocompleteAttrState_Valid) {
1610 // Concatenate the info fields.
1611 aResult = info.mSection;
1612
1613 if (!info.mAddressType.IsEmpty()) {
1614 if (!aResult.IsEmpty()) {
1615 aResult += ' ';
1616 }
1617 aResult += info.mAddressType;
1618 }
1619
1620 if (!info.mContactType.IsEmpty()) {
1621 if (!aResult.IsEmpty()) {
1622 aResult += ' ';
1623 }
1624 aResult += info.mContactType;
1625 }
1626
1627 if (!info.mFieldName.IsEmpty()) {
1628 if (!aResult.IsEmpty()) {
1629 aResult += ' ';
1630 }
1631 aResult += info.mFieldName;
1632 }
1633
1634 // The autocomplete attribute value "webauthn" is interpreted as both a
1635 // field name and a credential type. The corresponding IDL-exposed autofill
1636 // value is "webauthn", not "webauthn webauthn".
1637 if (!info.mCredentialType.IsEmpty() &&
1638 !(info.mCredentialType.Equals(u"webauthn"_ns) &&
1639 info.mCredentialType.Equals(aResult))) {
1640 if (!aResult.IsEmpty()) {
1641 aResult += ' ';
1642 }
1643 aResult += info.mCredentialType;
1644 }
1645 }
1646
1647 return state;
1648}
1649
1650nsContentUtils::AutocompleteAttrState
1651nsContentUtils::SerializeAutocompleteAttribute(
1652 const nsAttrValue* aAttr, mozilla::dom::AutocompleteInfo& aInfo,
1653 AutocompleteAttrState aCachedState, bool aGrantAllValidValue) {
1654 if (!aAttr ||
1655 aCachedState == nsContentUtils::eAutocompleteAttrState_Invalid) {
1656 return aCachedState;
1657 }
1658
1659 return InternalSerializeAutocompleteAttribute(aAttr, aInfo,
1660 aGrantAllValidValue);
1661}
1662
1663/**
1664 * Helper to validate the @autocomplete tokens.
1665 *
1666 * @return {AutocompleteAttrState} The state of the attribute (invalid/valid).
1667 */
1668nsContentUtils::AutocompleteAttrState
1669nsContentUtils::InternalSerializeAutocompleteAttribute(
1670 const nsAttrValue* aAttrVal, mozilla::dom::AutocompleteInfo& aInfo,
1671 bool aGrantAllValidValue) {
1672 // No autocomplete attribute so we are done
1673 if (!aAttrVal) {
1674 return eAutocompleteAttrState_Invalid;
1675 }
1676
1677 uint32_t numTokens = aAttrVal->GetAtomCount();
1678 if (!numTokens || numTokens > INT32_MAX(2147483647)) {
1679 return eAutocompleteAttrState_Invalid;
1680 }
1681
1682 uint32_t index = numTokens - 1;
1683 nsString tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1684 AutocompleteCategory category;
1685 nsAttrValue enumValue;
1686 nsAutoString credentialTypeStr;
1687
1688 bool result = enumValue.ParseEnumValue(
1689 tokenString, kAutocompleteCredentialTypeTable, false);
1690 if (result) {
1691 if (!enumValue.Equals(u"webauthn"_ns, eIgnoreCase) || numTokens > 5) {
1692 return eAutocompleteAttrState_Invalid;
1693 }
1694 enumValue.ToString(credentialTypeStr);
1695 ASCIIToLower(credentialTypeStr);
1696 // category is Credential and the indexth token is "webauthn"
1697 if (index == 0) {
1698 aInfo.mFieldName.Assign(credentialTypeStr);
1699 aInfo.mCredentialType.Assign(credentialTypeStr);
1700 return eAutocompleteAttrState_Valid;
1701 }
1702
1703 --index;
1704 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1705
1706 // Only the Normal and Contact categories are allowed with webauthn
1707 // - disallow Credential
1708 if (enumValue.ParseEnumValue(tokenString, kAutocompleteCredentialTypeTable,
1709 false)) {
1710 return eAutocompleteAttrState_Invalid;
1711 }
1712 // - disallow Off and Automatic
1713 if (enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable,
1714 false)) {
1715 if (enumValue.Equals(u"off"_ns, eIgnoreCase) ||
1716 enumValue.Equals(u"on"_ns, eIgnoreCase)) {
1717 return eAutocompleteAttrState_Invalid;
1718 }
1719 }
1720
1721 // Proceed to process the remaining tokens as if "webauthn" was not present.
1722 // We need to decrement numTokens to enforce the correct per-category limits
1723 // on the maximum number of tokens.
1724 --numTokens;
1725 }
1726
1727 bool unsupported = false;
1728 if (!aGrantAllValidValue) {
1729 unsupported = enumValue.ParseEnumValue(
1730 tokenString, kAutocompleteUnsupportedFieldNameTable, false);
1731 if (unsupported) {
1732 return eAutocompleteAttrState_Invalid;
1733 }
1734 }
1735
1736 nsAutoString fieldNameStr;
1737 result =
1738 enumValue.ParseEnumValue(tokenString, kAutocompleteFieldNameTable, false);
1739
1740 if (result) {
1741 // Off/Automatic/Normal categories.
1742 if (enumValue.Equals(u"off"_ns, eIgnoreCase) ||
1743 enumValue.Equals(u"on"_ns, eIgnoreCase)) {
1744 if (numTokens > 1) {
1745 return eAutocompleteAttrState_Invalid;
1746 }
1747 enumValue.ToString(fieldNameStr);
1748 ASCIIToLower(fieldNameStr);
1749 aInfo.mFieldName.Assign(fieldNameStr);
1750 aInfo.mCredentialType.Assign(credentialTypeStr);
1751 aInfo.mCanAutomaticallyPersist =
1752 !enumValue.Equals(u"off"_ns, eIgnoreCase);
1753 return eAutocompleteAttrState_Valid;
1754 }
1755
1756 // Only allow on/off if form autofill @autocomplete values aren't enabled
1757 // and it doesn't grant all valid values.
1758 if (!StaticPrefs::dom_forms_autocomplete_formautofill() &&
1759 !aGrantAllValidValue) {
1760 return eAutocompleteAttrState_Invalid;
1761 }
1762
1763 // Normal category
1764 if (numTokens > 3) {
1765 return eAutocompleteAttrState_Invalid;
1766 }
1767 category = eAutocompleteCategory_NORMAL;
1768 } else { // Check if the last token is of the contact category instead.
1769 // Only allow on/off if form autofill @autocomplete values aren't enabled
1770 // and it doesn't grant all valid values.
1771 if (!StaticPrefs::dom_forms_autocomplete_formautofill() &&
1772 !aGrantAllValidValue) {
1773 return eAutocompleteAttrState_Invalid;
1774 }
1775
1776 result = enumValue.ParseEnumValue(
1777 tokenString, kAutocompleteContactFieldNameTable, false);
1778 if (!result || numTokens > 4) {
1779 return eAutocompleteAttrState_Invalid;
1780 }
1781
1782 category = eAutocompleteCategory_CONTACT;
1783 }
1784
1785 enumValue.ToString(fieldNameStr);
1786 ASCIIToLower(fieldNameStr);
1787
1788 aInfo.mFieldName.Assign(fieldNameStr);
1789 aInfo.mCredentialType.Assign(credentialTypeStr);
1790 aInfo.mCanAutomaticallyPersist = !enumValue.ParseEnumValue(
1791 tokenString, kAutocompleteNoPersistFieldNameTable, false);
1792
1793 // We are done if this was the only token.
1794 if (numTokens == 1) {
1795 return eAutocompleteAttrState_Valid;
1796 }
1797
1798 --index;
1799 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1800
1801 if (category == eAutocompleteCategory_CONTACT) {
1802 if (!aGrantAllValidValue) {
1803 unsupported = enumValue.ParseEnumValue(
1804 tokenString, kAutocompleteUnsupportedContactFieldHintTable, false);
1805 if (unsupported) {
1806 return eAutocompleteAttrState_Invalid;
1807 }
1808 }
1809
1810 nsAttrValue contactFieldHint;
1811 result = contactFieldHint.ParseEnumValue(
1812 tokenString, kAutocompleteContactFieldHintTable, false);
1813 if (result) {
1814 nsAutoString contactFieldHintString;
1815 contactFieldHint.ToString(contactFieldHintString);
1816 ASCIIToLower(contactFieldHintString);
1817 aInfo.mContactType.Assign(contactFieldHintString);
1818 if (index == 0) {
1819 return eAutocompleteAttrState_Valid;
1820 }
1821 --index;
1822 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1823 }
1824 }
1825
1826 // Check for billing/shipping tokens
1827 nsAttrValue fieldHint;
1828 if (fieldHint.ParseEnumValue(tokenString, kAutocompleteFieldHintTable,
1829 false)) {
1830 nsString fieldHintString;
1831 fieldHint.ToString(fieldHintString);
1832 ASCIIToLower(fieldHintString);
1833 aInfo.mAddressType.Assign(fieldHintString);
1834 if (index == 0) {
1835 return eAutocompleteAttrState_Valid;
1836 }
1837 --index;
1838 tokenString = nsDependentAtomString(aAttrVal->AtomAt(index));
1839 }
1840
1841 // Check for section-* token
1842 const nsDependentSubstring& section = Substring(tokenString, 0, 8);
1843 if (section.LowerCaseEqualsASCII("section-")) {
1844 ASCIIToLower(tokenString);
1845 aInfo.mSection.Assign(tokenString);
1846 if (index == 0) {
1847 return eAutocompleteAttrState_Valid;
1848 }
1849 }
1850
1851 // Clear the fields as the autocomplete attribute is invalid.
1852 aInfo.mSection.Truncate();
1853 aInfo.mAddressType.Truncate();
1854 aInfo.mContactType.Truncate();
1855 aInfo.mFieldName.Truncate();
1856 aInfo.mCredentialType.Truncate();
1857
1858 return eAutocompleteAttrState_Invalid;
1859}
1860
1861// Parse an integer according to HTML spec
1862template <class CharT>
1863int32_t nsContentUtils::ParseHTMLIntegerImpl(
1864 const CharT* aStart, const CharT* aEnd,
1865 ParseHTMLIntegerResultFlags* aResult) {
1866 int result = eParseHTMLInteger_NoFlags;
1867
1868 const CharT* iter = aStart;
1869
1870 while (iter != aEnd && nsContentUtils::IsHTMLWhitespace(*iter)) {
1871 result |= eParseHTMLInteger_NonStandard;
1872 ++iter;
1873 }
1874
1875 if (iter == aEnd) {
1876 result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
1877 *aResult = (ParseHTMLIntegerResultFlags)result;
1878 return 0;
1879 }
1880
1881 int sign = 1;
1882 if (*iter == CharT('-')) {
1883 sign = -1;
1884 result |= eParseHTMLInteger_Negative;
1885 ++iter;
1886 } else if (*iter == CharT('+')) {
1887 result |= eParseHTMLInteger_NonStandard;
1888 ++iter;
1889 }
1890
1891 bool foundValue = false;
1892 CheckedInt32 value = 0;
1893
1894 // Check for leading zeros first.
1895 uint64_t leadingZeros = 0;
1896 while (iter != aEnd) {
1897 if (*iter != CharT('0')) {
1898 break;
1899 }
1900
1901 ++leadingZeros;
1902 foundValue = true;
1903 ++iter;
1904 }
1905
1906 while (iter != aEnd) {
1907 if (*iter >= CharT('0') && *iter <= CharT('9')) {
1908 value = (value * 10) + (*iter - CharT('0')) * sign;
1909 ++iter;
1910 if (!value.isValid()) {
1911 result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorOverflow;
1912 break;
1913 }
1914 foundValue = true;
1915 } else {
1916 break;
1917 }
1918 }
1919
1920 if (!foundValue) {
1921 result |= eParseHTMLInteger_Error | eParseHTMLInteger_ErrorNoValue;
1922 }
1923
1924 if (value.isValid() &&
1925 ((leadingZeros > 1 || (leadingZeros == 1 && !(value == 0))) ||
1926 (sign == -1 && value == 0))) {
1927 result |= eParseHTMLInteger_NonStandard;
1928 }
1929
1930 if (iter != aEnd) {
1931 result |= eParseHTMLInteger_DidNotConsumeAllInput;
1932 }
1933
1934 *aResult = (ParseHTMLIntegerResultFlags)result;
1935 return value.isValid() ? value.value() : 0;
1936}
1937
1938// Parse an integer according to HTML spec
1939int32_t nsContentUtils::ParseHTMLInteger(const char16_t* aStart,
1940 const char16_t* aEnd,
1941 ParseHTMLIntegerResultFlags* aResult) {
1942 return ParseHTMLIntegerImpl(aStart, aEnd, aResult);
1943}
1944
1945int32_t nsContentUtils::ParseHTMLInteger(const char* aStart, const char* aEnd,
1946 ParseHTMLIntegerResultFlags* aResult) {
1947 return ParseHTMLIntegerImpl(aStart, aEnd, aResult);
1948}
1949
1950Maybe<double> nsContentUtils::ParseHTMLFloatingPointNumber(
1951 const nsAString& aString) {
1952 // Check if it is a valid floating-point number first since the result of
1953 // nsString.ToDouble() is more lenient than the spec,
1954 // https://html.spec.whatwg.org/#valid-floating-point-number
1955 nsAString::const_iterator iter, end;
1956 aString.BeginReading(iter);
1957 aString.EndReading(end);
1958
1959 if (iter == end) {
1960 return {};
1961 }
1962
1963 if (*iter == char16_t('-') && ++iter == end) {
1964 return {};
1965 }
1966
1967 if (IsAsciiDigit(*iter)) {
1968 for (; iter != end && IsAsciiDigit(*iter); ++iter);
1969 } else if (*iter == char16_t('.')) {
1970 // Do nothing, jumps to fraction part
1971 } else {
1972 return {};
1973 }
1974
1975 // Fraction
1976 if (*iter == char16_t('.')) {
1977 ++iter;
1978 if (iter == end || !IsAsciiDigit(*iter)) {
1979 // U+002E FULL STOP character (.) must be followed by one or more ASCII
1980 // digits
1981 return {};
1982 }
1983
1984 for (; iter != end && IsAsciiDigit(*iter); ++iter);
1985 }
1986
1987 if (iter != end && (*iter == char16_t('e') || *iter == char16_t('E'))) {
1988 ++iter;
1989 if (*iter == char16_t('-') || *iter == char16_t('+')) {
1990 ++iter;
1991 }
1992
1993 if (iter == end || !IsAsciiDigit(*iter)) {
1994 // Should have one or more ASCII digits
1995 return {};
1996 }
1997
1998 for (; iter != end && IsAsciiDigit(*iter); ++iter);
1999 }
2000
2001 if (iter != end) {
2002 return {};
2003 }
2004
2005 nsresult rv;
2006 double result = PromiseFlatStringTPromiseFlatString<char16_t>(aString).ToDouble(&rv);
2007 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2008 return {};
2009 }
2010 return Some(result);
2011}
2012
2013#define SKIP_WHITESPACE(iter, end_iter, end_res)while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(
iter))) { ++(iter); } if ((iter) == (end_iter)) { return (end_res
); }
\
2014 while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \
2015 ++(iter); \
2016 } \
2017 if ((iter) == (end_iter)) { \
2018 return (end_res); \
2019 }
2020
2021#define SKIP_ATTR_NAME(iter, end_iter)while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*
(iter)) && *(iter) != '=') { ++(iter); }
\
2022 while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*(iter)) && \
2023 *(iter) != '=') { \
2024 ++(iter); \
2025 }
2026
2027bool nsContentUtils::GetPseudoAttributeValue(const nsString& aSource,
2028 nsAtom* aName, nsAString& aValue) {
2029 aValue.Truncate();
2030
2031 const char16_t* start = aSource.get();
2032 const char16_t* end = start + aSource.Length();
2033 const char16_t* iter;
2034
2035 while (start != end) {
2036 SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start
))) { ++(start); } if ((start) == (end)) { return (false); }
2037 iter = start;
2038 SKIP_ATTR_NAME(iter, end)while ((iter) != (end) && !nsCRT::IsAsciiSpace(*(iter
)) && *(iter) != '=') { ++(iter); }
2039
2040 if (start == iter) {
2041 return false;
2042 }
2043
2044 // Remember the attr name.
2045 const nsDependentSubstring& attrName = Substring(start, iter);
2046
2047 // Now check whether this is a valid name="value" pair.
2048 start = iter;
2049 SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start
))) { ++(start); } if ((start) == (end)) { return (false); }
2050 if (*start != '=') {
2051 // No '=', so this is not a name="value" pair. We don't know
2052 // what it is, and we have no way to handle it.
2053 return false;
2054 }
2055
2056 // Have to skip the value.
2057 ++start;
2058 SKIP_WHITESPACE(start, end, false)while ((start) != (end) && nsCRT::IsAsciiSpace(*(start
))) { ++(start); } if ((start) == (end)) { return (false); }
2059 char16_t q = *start;
2060 if (q != kQuote && q != kApostrophe) {
2061 // Not a valid quoted value, so bail.
2062 return false;
2063 }
2064
2065 ++start; // Point to the first char of the value.
2066 iter = start;
2067
2068 while (iter != end && *iter != q) {
2069 ++iter;
2070 }
2071
2072 if (iter == end) {
2073 // Oops, unterminated quoted string.
2074 return false;
2075 }
2076
2077 // At this point attrName holds the name of the "attribute" and
2078 // the value is between start and iter.
2079
2080 if (aName->Equals(attrName)) {
2081 // We'll accumulate as many characters as possible (until we hit either
2082 // the end of the string or the beginning of an entity). Chunks will be
2083 // delimited by start and chunkEnd.
2084 const char16_t* chunkEnd = start;
2085 while (chunkEnd != iter) {
2086 if (*chunkEnd == kLessThan) {
2087 aValue.Truncate();
2088
2089 return false;
2090 }
2091
2092 if (*chunkEnd == kAmpersand) {
2093 aValue.Append(start, chunkEnd - start);
2094
2095 const char16_t* afterEntity = nullptr;
2096 char16_t result[2];
2097 uint32_t count = MOZ_XMLTranslateEntity(
2098 reinterpret_cast<const char*>(chunkEnd),
2099 reinterpret_cast<const char*>(iter),
2100 reinterpret_cast<const char**>(&afterEntity), result);
2101 if (count == 0) {
2102 aValue.Truncate();
2103
2104 return false;
2105 }
2106
2107 aValue.Append(result, count);
2108
2109 // Advance to after the entity and begin a new chunk.
2110 start = chunkEnd = afterEntity;
2111 } else {
2112 ++chunkEnd;
2113 }
2114 }
2115
2116 // Append remainder.
2117 aValue.Append(start, iter - start);
2118
2119 return true;
2120 }
2121
2122 // Resume scanning after the end of the attribute value (past the quote
2123 // char).
2124 start = iter + 1;
2125 }
2126
2127 return false;
2128}
2129
2130bool nsContentUtils::IsJavaScriptLanguage(const nsString& aName) {
2131 // Create MIME type as "text/" + given input
2132 nsAutoString mimeType(u"text/");
2133 mimeType.Append(aName);
2134
2135 return IsJavascriptMIMEType(mimeType);
2136}
2137
2138void nsContentUtils::SplitMimeType(const nsAString& aValue, nsString& aType,
2139 nsString& aParams) {
2140 aType.Truncate();
2141 aParams.Truncate();
2142 int32_t semiIndex = aValue.FindChar(char16_t(';'));
2143 if (-1 != semiIndex) {
2144 aType = Substring(aValue, 0, semiIndex);
2145 aParams =
2146 Substring(aValue, semiIndex + 1, aValue.Length() - (semiIndex + 1));
2147 aParams.StripWhitespace();
2148 } else {
2149 aType = aValue;
2150 }
2151 aType.StripWhitespace();
2152}
2153
2154/**
2155 * A helper function that parses a sandbox attribute (of an <iframe> or a CSP
2156 * directive) and converts it to the set of flags used internally.
2157 *
2158 * @param aSandboxAttr the sandbox attribute
2159 * @return the set of flags (SANDBOXED_NONE if aSandboxAttr is
2160 * null)
2161 */
2162uint32_t nsContentUtils::ParseSandboxAttributeToFlags(
2163 const nsAttrValue* aSandboxAttr) {
2164 if (!aSandboxAttr) {
2165 return SANDBOXED_NONE;
2166 }
2167
2168 uint32_t out = SANDBOX_ALL_FLAGS;
2169
2170#define SANDBOX_KEYWORD(string, atom, flags) \
2171 if (aSandboxAttr->Contains(nsGkAtoms::atom, eIgnoreCase)) { \
2172 out &= ~(flags); \
2173 }
2174#include "IframeSandboxKeywordList.inc"
2175#undef SANDBOX_KEYWORD
2176
2177 return out;
2178}
2179
2180/**
2181 * A helper function that checks if a string matches a valid sandbox flag.
2182 *
2183 * @param aFlag the potential sandbox flag.
2184 * @return true if the flag is a sandbox flag.
2185 */
2186bool nsContentUtils::IsValidSandboxFlag(const nsAString& aFlag) {
2187#define SANDBOX_KEYWORD(string, atom, flags) \
2188 if (EqualsIgnoreASCIICase(nsDependentAtomString(nsGkAtoms::atom), aFlag)) { \
2189 return true; \
2190 }
2191#include "IframeSandboxKeywordList.inc"
2192#undef SANDBOX_KEYWORD
2193 return false;
2194}
2195
2196/**
2197 * A helper function that returns a string attribute corresponding to the
2198 * sandbox flags.
2199 *
2200 * @param aFlags the sandbox flags
2201 * @param aString the attribute corresponding to the flags (null if aFlags
2202 * is zero)
2203 */
2204void nsContentUtils::SandboxFlagsToString(uint32_t aFlags, nsAString& aString) {
2205 if (!aFlags) {
2206 SetDOMStringToNull(aString);
2207 return;
2208 }
2209
2210 aString.Truncate();
2211
2212#define SANDBOX_KEYWORD(string, atom, flags) \
2213 if (!(aFlags & (flags))) { \
2214 if (!aString.IsEmpty()) { \
2215 aString.AppendLiteral(u" "); \
2216 } \
2217 aString.Append(nsDependentAtomString(nsGkAtoms::atom)); \
2218 }
2219#include "IframeSandboxKeywordList.inc"
2220#undef SANDBOX_KEYWORD
2221}
2222
2223nsIBidiKeyboard* nsContentUtils::GetBidiKeyboard() {
2224 if (!sBidiKeyboard) {
2225 sBidiKeyboard = nsIWidget::CreateBidiKeyboard();
2226 }
2227 return sBidiKeyboard;
2228}
2229
2230// static
2231bool nsContentUtils::IsAlphanumeric(uint32_t aChar) {
2232 nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);
2233
2234 return (cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber);
2235}
2236
2237// static
2238bool nsContentUtils::IsAlphanumericOrSymbol(uint32_t aChar) {
2239 nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);
2240
2241 return cat == nsUGenCategory::kLetter || cat == nsUGenCategory::kNumber ||
2242 cat == nsUGenCategory::kSymbol;
2243}
2244
2245// static
2246bool nsContentUtils::IsHyphen(uint32_t aChar) {
2247 // Characters treated as hyphens for the purpose of "emergency" breaking
2248 // when the content would otherwise overflow.
2249 return aChar == uint32_t('-') || // HYPHEN-MINUS
2250 aChar == 0x2010 || // HYPHEN
2251 aChar == 0x2012 || // FIGURE DASH
2252 aChar == 0x2013 || // EN DASH
2253 aChar == 0x058A; // ARMENIAN HYPHEN
2254}
2255
2256/* static */
2257bool nsContentUtils::IsHTMLWhitespace(char16_t aChar) {
2258 return aChar == char16_t(0x0009) || aChar == char16_t(0x000A) ||
2259 aChar == char16_t(0x000C) || aChar == char16_t(0x000D) ||
2260 aChar == char16_t(0x0020);
2261}
2262
2263/* static */
2264bool nsContentUtils::IsHTMLWhitespaceOrNBSP(char16_t aChar) {
2265 return IsHTMLWhitespace(aChar) || aChar == char16_t(0xA0);
2266}
2267
2268/* static */
2269bool nsContentUtils::IsHTMLBlockLevelElement(nsIContent* aContent) {
2270 return aContent->IsAnyOfHTMLElements(
2271 nsGkAtoms::address, nsGkAtoms::article, nsGkAtoms::aside,
2272 nsGkAtoms::blockquote, nsGkAtoms::center, nsGkAtoms::dir, nsGkAtoms::div,
2273 nsGkAtoms::dl, // XXX why not dt and dd?
2274 nsGkAtoms::fieldset,
2275 nsGkAtoms::figure, // XXX shouldn't figcaption be on this list
2276 nsGkAtoms::footer, nsGkAtoms::form, nsGkAtoms::h1, nsGkAtoms::h2,
2277 nsGkAtoms::h3, nsGkAtoms::h4, nsGkAtoms::h5, nsGkAtoms::h6,
2278 nsGkAtoms::header, nsGkAtoms::hgroup, nsGkAtoms::hr, nsGkAtoms::li,
2279 nsGkAtoms::listing, nsGkAtoms::menu, nsGkAtoms::nav, nsGkAtoms::ol,
2280 nsGkAtoms::p, nsGkAtoms::pre, nsGkAtoms::section, nsGkAtoms::table,
2281 nsGkAtoms::ul, nsGkAtoms::xmp);
2282}
2283
2284// static
2285int32_t nsContentUtils::ParseLegacyFontSize(const nsAString& aValue) {
2286 nsAString::const_iterator iter, end;
2287 aValue.BeginReading(iter);
2288 aValue.EndReading(end);
2289
2290 while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
2291 ++iter;
2292 }
2293
2294 if (iter == end) {
2295 return 0;
2296 }
2297
2298 bool relative = false;
2299 bool negate = false;
2300 if (*iter == char16_t('-')) {
2301 relative = true;
2302 negate = true;
2303 ++iter;
2304 } else if (*iter == char16_t('+')) {
2305 relative = true;
2306 ++iter;
2307 }
2308
2309 if (iter == end || *iter < char16_t('0') || *iter > char16_t('9')) {
2310 return 0;
2311 }
2312
2313 // We don't have to worry about overflow, since we can bail out as soon as
2314 // we're bigger than 7.
2315 int32_t value = 0;
2316 while (iter != end && *iter >= char16_t('0') && *iter <= char16_t('9')) {
2317 value = 10 * value + (*iter - char16_t('0'));
2318 if (value >= 7) {
2319 break;
2320 }
2321 ++iter;
2322 }
2323
2324 if (relative) {
2325 if (negate) {
2326 value = 3 - value;
2327 } else {
2328 value = 3 + value;
2329 }
2330 }
2331
2332 return std::clamp(value, 1, 7);
2333}
2334
2335/* static */
2336void nsContentUtils::GetOfflineAppManifest(Document* aDocument, nsIURI** aURI) {
2337 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", 2337); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2337); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2338 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"
, 2338); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { MOZ_CrashSequence(__null, 2338); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2339 *aURI = nullptr;
2340
2341 if (aDocument->GetController().isSome()) {
2342 return;
2343 }
2344
2345 Element* docElement = aDocument->GetRootElement();
2346 if (!docElement) {
2347 return;
2348 }
2349
2350 nsAutoString manifestSpec;
2351 docElement->GetAttr(nsGkAtoms::manifest, manifestSpec);
2352
2353 // Manifest URIs can't have fragment identifiers.
2354 if (manifestSpec.IsEmpty() || manifestSpec.Contains('#')) {
2355 return;
2356 }
2357
2358 nsContentUtils::NewURIWithDocumentCharset(aURI, manifestSpec, aDocument,
2359 aDocument->GetDocBaseURI());
2360}
2361
2362/* static */
2363bool nsContentUtils::OfflineAppAllowed(nsIURI* aURI) { return false; }
2364
2365/* static */
2366bool nsContentUtils::OfflineAppAllowed(nsIPrincipal* aPrincipal) {
2367 return false;
2368}
2369// Static
2370bool nsContentUtils::IsErrorPage(nsIURI* aURI) {
2371 if (!aURI) {
2372 return false;
2373 }
2374
2375 if (!aURI->SchemeIs("about")) {
2376 return false;
2377 }
2378
2379 nsAutoCString name;
2380 nsresult rv = NS_GetAboutModuleName(aURI, name);
2381 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"
, 2381); return false; } } while (false)
;
2382
2383 return name.EqualsLiteral("certerror") || name.EqualsLiteral("neterror") ||
2384 name.EqualsLiteral("blocked");
2385}
2386
2387// static
2388void nsContentUtils::Shutdown() {
2389 sInitialized = false;
2390
2391 nsHTMLTags::ReleaseTable();
2392
2393 NS_IF_RELEASE(sContentPolicyService)do { if (sContentPolicyService) { (sContentPolicyService)->
Release(); (sContentPolicyService) = 0; } } while (0)
;
2394 sTriedToGetContentPolicy = false;
2395 for (StaticRefPtr<nsIStringBundle>& bundle : sStringBundles) {
2396 bundle = nullptr;
2397 }
2398
2399 NS_IF_RELEASE(sStringBundleService)do { if (sStringBundleService) { (sStringBundleService)->Release
(); (sStringBundleService) = 0; } } while (0)
;
2400 NS_IF_RELEASE(sConsoleService)do { if (sConsoleService) { (sConsoleService)->Release(); (
sConsoleService) = 0; } } while (0)
;
2401 NS_IF_RELEASE(sXPConnect)do { if (sXPConnect) { (sXPConnect)->Release(); (sXPConnect
) = 0; } } while (0)
;
2402 NS_IF_RELEASE(sSecurityManager)do { if (sSecurityManager) { (sSecurityManager)->Release()
; (sSecurityManager) = 0; } } while (0)
;
2403 NS_IF_RELEASE(sSystemPrincipal)do { if (sSystemPrincipal) { (sSystemPrincipal)->Release()
; (sSystemPrincipal) = 0; } } while (0)
;
2404 NS_IF_RELEASE(sNullSubjectPrincipal)do { if (sNullSubjectPrincipal) { (sNullSubjectPrincipal)->
Release(); (sNullSubjectPrincipal) = 0; } } while (0)
;
2405 NS_IF_RELEASE(sFingerprintingProtectionPrincipal)do { if (sFingerprintingProtectionPrincipal) { (sFingerprintingProtectionPrincipal
)->Release(); (sFingerprintingProtectionPrincipal) = 0; } }
while (0)
;
2406
2407 sBidiKeyboard = nullptr;
2408
2409 delete sAtomEventTable;
2410 sAtomEventTable = nullptr;
2411 delete sStringEventTable;
2412 sStringEventTable = nullptr;
2413 delete sUserDefinedEvents;
2414 sUserDefinedEvents = nullptr;
2415
2416 // Managers left in the list remove themselves from it when they're deleted,
2417 // which can happen after this point.
2418 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"
, 2419); MOZ_PretendNoReturn(); } } while (0)
2419 "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"
, 2419); MOZ_PretendNoReturn(); } } while (0)
;
2420
2421 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", 2421); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sDOMArenaHashtable->Count() == 0" ")");
do { MOZ_CrashSequence(__null, 2421); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2422 delete sDOMArenaHashtable;
2423 sDOMArenaHashtable = nullptr;
2424
2425 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", 2426); MOZ_PretendNoReturn
(); } } while (0)
2426 "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", 2426); MOZ_PretendNoReturn
(); } } while (0)
;
2427 delete sBlockedScriptRunners;
2428 sBlockedScriptRunners = nullptr;
2429
2430 delete sShiftText;
2431 sShiftText = nullptr;
2432 delete sControlText;
2433 sControlText = nullptr;
2434 delete sCommandOrWinText;
2435 sCommandOrWinText = nullptr;
2436 delete sAltText;
2437 sAltText = nullptr;
2438 delete sModifierSeparator;
2439 sModifierSeparator = nullptr;
2440
2441 delete sJSScriptBytecodeMimeType;
2442 sJSScriptBytecodeMimeType = nullptr;
2443
2444 delete sJSModuleBytecodeMimeType;
2445 sJSModuleBytecodeMimeType = nullptr;
2446
2447 NS_IF_RELEASE(sSameOriginChecker)do { if (sSameOriginChecker) { (sSameOriginChecker)->Release
(); (sSameOriginChecker) = 0; } } while (0)
;
2448
2449 if (sUserInteractionObserver) {
2450 sUserInteractionObserver->Shutdown();
2451 NS_RELEASE(sUserInteractionObserver)do { (sUserInteractionObserver)->Release(); (sUserInteractionObserver
) = 0; } while (0)
;
2452 }
2453
2454 for (const auto& pref : kRfpPrefs) {
2455 Preferences::UnregisterCallback(RecomputeResistFingerprintingAllDocs, pref);
2456 }
2457
2458 TextControlState::Shutdown();
2459}
2460
2461/**
2462 * Checks whether two nodes come from the same origin. aTrustedNode is
2463 * considered 'safe' in that a user can operate on it.
2464 */
2465// static
2466nsresult nsContentUtils::CheckSameOrigin(const nsINode* aTrustedNode,
2467 const nsINode* unTrustedNode) {
2468 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"
, 2468); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTrustedNode"
")"); do { MOZ_CrashSequence(__null, 2468); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2469 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", 2469); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "unTrustedNode" ")"); do { MOZ_CrashSequence
(__null, 2469); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2470
2471 /*
2472 * Get hold of each node's principal
2473 */
2474
2475 nsIPrincipal* trustedPrincipal = aTrustedNode->NodePrincipal();
2476 nsIPrincipal* unTrustedPrincipal = unTrustedNode->NodePrincipal();
2477
2478 if (trustedPrincipal == unTrustedPrincipal) {
2479 return NS_OK;
2480 }
2481
2482 bool equal;
2483 // XXXbz should we actually have a Subsumes() check here instead? Or perhaps
2484 // a separate method for that, with callers using one or the other?
2485 if (NS_FAILED(trustedPrincipal->Equals(unTrustedPrincipal, &equal))((bool)(__builtin_expect(!!(NS_FAILED_impl(trustedPrincipal->
Equals(unTrustedPrincipal, &equal))), 0)))
||
2486 !equal) {
2487 return NS_ERROR_DOM_PROP_ACCESS_DENIED;
2488 }
2489
2490 return NS_OK;
2491}
2492
2493// static
2494bool nsContentUtils::CanCallerAccess(nsIPrincipal* aSubjectPrincipal,
2495 nsIPrincipal* aPrincipal) {
2496 bool subsumes;
2497 nsresult rv = aSubjectPrincipal->Subsumes(aPrincipal, &subsumes);
2498 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"
, 2498); return false; } } while (false)
;
2499
2500 if (subsumes) {
2501 return true;
2502 }
2503
2504 // The subject doesn't subsume aPrincipal. Allow access only if the subject
2505 // is chrome.
2506 return IsCallerChrome();
2507}
2508
2509// static
2510bool nsContentUtils::CanCallerAccess(const nsINode* aNode) {
2511 nsIPrincipal* subject = SubjectPrincipal();
2512 if (subject->IsSystemPrincipal()) {
2513 return true;
2514 }
2515
2516 if (aNode->ChromeOnlyAccess()) {
2517 return false;
2518 }
2519
2520 return CanCallerAccess(subject, aNode->NodePrincipal());
2521}
2522
2523// static
2524bool nsContentUtils::CanCallerAccess(nsPIDOMWindowInner* aWindow) {
2525 nsCOMPtr<nsIScriptObjectPrincipal> scriptObject = do_QueryInterface(aWindow);
2526 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",
2526); return false; } } while (false)
;
2527
2528 return CanCallerAccess(SubjectPrincipal(), scriptObject->GetPrincipal());
2529}
2530
2531// static
2532bool nsContentUtils::PrincipalHasPermission(nsIPrincipal& aPrincipal,
2533 const nsAtom* aPerm) {
2534 // Chrome gets access by default.
2535 if (aPrincipal.IsSystemPrincipal()) {
2536 return true;
2537 }
2538
2539 // Otherwise, only allow if caller is an addon with the permission.
2540 return BasePrincipal::Cast(aPrincipal).AddonHasPermission(aPerm);
2541}
2542
2543// static
2544bool nsContentUtils::CallerHasPermission(JSContext* aCx, const nsAtom* aPerm) {
2545 return PrincipalHasPermission(*SubjectPrincipal(aCx), aPerm);
2546}
2547
2548// static
2549nsIPrincipal* nsContentUtils::GetAttrTriggeringPrincipal(
2550 nsIContent* aContent, const nsAString& aAttrValue,
2551 nsIPrincipal* aSubjectPrincipal) {
2552 nsIPrincipal* contentPrin = aContent ? aContent->NodePrincipal() : nullptr;
2553
2554 // If the subject principal is the same as the content principal, or no
2555 // explicit subject principal was provided, we don't need to do any further
2556 // checks. Just return the content principal.
2557 if (contentPrin == aSubjectPrincipal || !aSubjectPrincipal) {
2558 return contentPrin;
2559 }
2560
2561 // Only use the subject principal if the URL string we are going to end up
2562 // fetching is under the control of that principal, which is never the case
2563 // for relative URLs.
2564 if (aAttrValue.IsEmpty() ||
2565 !IsAbsoluteURL(NS_ConvertUTF16toUTF8(aAttrValue))) {
2566 return contentPrin;
2567 }
2568
2569 // Only use the subject principal as the attr triggering principal if it
2570 // should override the CSP of the node's principal.
2571 if (BasePrincipal::Cast(aSubjectPrincipal)->OverridesCSP(contentPrin)) {
2572 return aSubjectPrincipal;
2573 }
2574
2575 return contentPrin;
2576}
2577
2578// static
2579bool nsContentUtils::CanNavigate(mozilla::dom::BrowsingContext* aSource,
2580 mozilla::dom::BrowsingContext* aTarget,
2581 nsIPrincipal* aDocumentPrincipal,
2582 bool aConsiderOpener) {
2583 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", 2585
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aSource->Group() == aTarget->Group()"
") (" "Source and target BrowsingContexts must be in the same group"
")"); do { MOZ_CrashSequence(__null, 2585); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2584 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", 2585
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aSource->Group() == aTarget->Group()"
") (" "Source and target BrowsingContexts must be in the same group"
")"); do { MOZ_CrashSequence(__null, 2585); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2585 "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", 2585
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aSource->Group() == aTarget->Group()"
") (" "Source and target BrowsingContexts must be in the same group"
")"); do { MOZ_CrashSequence(__null, 2585); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2586 if (aSource->Group() != aTarget->Group()) {
2587 return false;
2588 }
2589
2590 auto isFileScheme = [](nsIPrincipal* aPrincipal) -> bool {
2591 // NOTE: This code previously checked for a file scheme using
2592 // `nsIPrincipal::GetURI()` combined with `NS_GetInnermostURI`. We no longer
2593 // use GetURI, as it has been deprecated, and it makes more sense to take
2594 // advantage of the pre-computed origin, which will already use the
2595 // innermost URI (bug 1810619)
2596 nsAutoCString origin, scheme;
2597 return NS_SUCCEEDED(aPrincipal->GetOriginNoSuffix(origin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->GetOriginNoSuffix
(origin))), 1)))
&&
2598 NS_SUCCEEDED(net_ExtractURLScheme(origin, scheme))((bool)(__builtin_expect(!!(!NS_FAILED_impl(net_ExtractURLScheme
(origin, scheme))), 1)))
&&
2599 scheme == "file"_ns;
2600 };
2601
2602 // A frame can navigate itself and its own root.
2603 if (aTarget == aSource || aTarget == aSource->Top()) {
2604 return true;
2605 }
2606
2607 // If the target frame doesn't yet have a WindowContext, start checking
2608 // principals from its direct ancestor instead. It would inherit its principal
2609 // from this document upon creation.
2610 dom::WindowContext* initialWc = aTarget->GetCurrentWindowContext();
2611 if (!initialWc) {
2612 initialWc = aTarget->GetParentWindowContext();
2613 }
2614
2615 // A frame can navigate any frame with a same-origin ancestor.
2616 bool isFileDocument = isFileScheme(aDocumentPrincipal);
2617 for (dom::WindowContext* wc = initialWc; wc;
2618 wc = wc->GetParentWindowContext()) {
2619 nsIPrincipal* documentPrincipal = nullptr;
2620 if (XRE_IsParentProcess()) {
2621 dom::WindowGlobalParent* wgp = wc->Canonical();
2622 if (!wgp) {
2623 continue;
2624 }
2625 documentPrincipal = wgp->DocumentPrincipal();
2626 } else {
2627 dom::WindowGlobalChild* wgc = wc->GetWindowGlobalChild();
2628 if (!wgc) {
2629 continue; // not same-origin.
2630 }
2631 documentPrincipal = wgc->DocumentPrincipal();
2632 }
2633
2634 if (aDocumentPrincipal->Equals(documentPrincipal)) {
2635 return true;
2636 }
2637
2638 // Not strictly equal, special case if both are file: URIs.
2639 //
2640 // file: URIs are considered the same domain for the purpose of frame
2641 // navigation, regardless of script accessibility (bug 420425).
2642 if (isFileDocument && isFileScheme(documentPrincipal)) {
2643 return true;
2644 }
2645 }
2646
2647 // If the target is a top-level document, a frame can navigate it
2648 // when the source is allowed to navigate the opener
2649 if (aConsiderOpener && !aTarget->GetParent()) {
2650 if (RefPtr<dom::BrowsingContext> opener = aTarget->GetOpener()) {
2651 return CanNavigate(aSource, opener, aDocumentPrincipal, false);
2652 }
2653 }
2654
2655 return false;
2656}
2657
2658// static
2659bool nsContentUtils::IsAbsoluteURL(const nsACString& aURL) {
2660 nsAutoCString scheme;
2661 if (NS_FAILED(net_ExtractURLScheme(aURL, scheme))((bool)(__builtin_expect(!!(NS_FAILED_impl(net_ExtractURLScheme
(aURL, scheme))), 0)))
) {
2662 // If we can't extract a scheme, it's not an absolute URL.
2663 return false;
2664 }
2665
2666 // If it parses as an absolute StandardURL, it's definitely an absolute URL,
2667 // so no need to check with the IO service.
2668 if (net_IsAbsoluteURL(aURL)) {
2669 return true;
2670 }
2671
2672 nsresult rv = NS_OK;
2673 nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service(&rv);
2674 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"
, 2674); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2674); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2675 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2676 return false;
2677 }
2678
2679 uint32_t flags;
2680 if (NS_SUCCEEDED(io->GetProtocolFlags(scheme.get(), &flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(io->GetProtocolFlags
(scheme.get(), &flags))), 1)))
) {
2681 return flags & nsIProtocolHandler::URI_NORELATIVE;
2682 }
2683
2684 return false;
2685}
2686
2687// static
2688bool nsContentUtils::InProlog(nsINode* aNode) {
2689 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", 2689
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode" ") (" "missing node to nsContentUtils::InProlog"
")"); do { MOZ_CrashSequence(__null, 2689); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2690
2691 nsINode* parent = aNode->GetParentNode();
2692 if (!parent || !parent->IsDocument()) {
2693 return false;
2694 }
2695
2696 const Document* doc = parent->AsDocument();
2697 const nsIContent* root = doc->GetRootElement();
2698 if (!root) {
2699 return true;
2700 }
2701 const Maybe<uint32_t> indexOfNode = doc->ComputeIndexOf(aNode);
2702 const Maybe<uint32_t> indexOfRoot = doc->ComputeIndexOf(root);
2703 if (MOZ_LIKELY(indexOfNode.isSome() && indexOfRoot.isSome())(__builtin_expect(!!(indexOfNode.isSome() && indexOfRoot
.isSome()), 1))
) {
2704 return *indexOfNode < *indexOfRoot;
2705 }
2706 // XXX Keep the odd traditional behavior for now.
2707 return indexOfNode.isNothing() && indexOfRoot.isSome();
2708}
2709
2710bool nsContentUtils::IsCallerChrome() {
2711 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", 2711); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 2711); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2712 return SubjectPrincipal() == sSystemPrincipal;
2713}
2714
2715#ifdef FUZZING
2716bool nsContentUtils::IsFuzzingEnabled() {
2717 return StaticPrefs::fuzzing_enabled();
2718}
2719#endif
2720
2721/* static */
2722bool nsContentUtils::IsCallerChromeOrElementTransformGettersEnabled(
2723 JSContext* aCx, JSObject*) {
2724 return ThreadsafeIsSystemCaller(aCx) ||
2725 StaticPrefs::dom_element_transform_getters_enabled();
2726}
2727
2728// Older Should RFP Functions ----------------------------------
2729
2730/* static */
2731bool nsContentUtils::ShouldResistFingerprinting(bool aIsPrivateMode,
2732 RFPTarget aTarget) {
2733 return nsRFPService::IsRFPEnabledFor(aIsPrivateMode, aTarget, Nothing());
2734}
2735
2736/* static */
2737bool nsContentUtils::ShouldResistFingerprinting(nsIGlobalObject* aGlobalObject,
2738 RFPTarget aTarget) {
2739 if (!aGlobalObject) {
2740 return ShouldResistFingerprinting("Null Object", aTarget);
2741 }
2742 return aGlobalObject->ShouldResistFingerprinting(aTarget);
2743}
2744
2745// Newer Should RFP Functions ----------------------------------
2746// Utilities ---------------------------------------------------
2747
2748inline void LogDomainAndList(const char* urlType, nsAutoCString& list,
2749 nsAutoCString& url, bool isExemptDomain) {
2750 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)
2751 ("%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)
2752 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)
2753 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)
;
2754}
2755
2756inline already_AddRefed<nsICookieJarSettings> GetCookieJarSettings(
2757 nsILoadInfo* aLoadInfo) {
2758 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
2759 nsresult rv =
2760 aLoadInfo->GetCookieJarSettings(getter_AddRefs(cookieJarSettings));
2761 if (rv == NS_ERROR_NOT_IMPLEMENTED) {
2762 // The TRRLoadInfo in particular does not implement this method
2763 // In that instance. We will return false and let other code decide if
2764 // we shouldRFP for this connection
2765 return nullptr;
2766 }
2767 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"
, 2767)
) {
2768 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)
2769 ("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)
2770 "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)
;
2771 return nullptr;
2772 }
2773
2774 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", 2774); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "cookieJarSettings" ")"); do { MOZ_CrashSequence
(__null, 2774); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2775 return cookieJarSettings.forget();
2776}
2777
2778bool nsContentUtils::ETPSaysShouldNotResistFingerprinting(
2779 nsICookieJarSettings* aCookieJarSettings, bool aIsPBM) {
2780 // A positive return from this function should always be obeyed.
2781 // A negative return means we should keep checking things.
2782
2783 // We do not want this check to apply to RFP, only to FPP.
2784 if (nsRFPService::IsRFPPrefEnabled(aIsPBM)) {
2785 // In RFP, never use the ETP toggle to exempt.
2786 // We can safely return false here even if we are not in PBM mode
2787 // and RFP_pbmode is enabled because we will later see that and
2788 // return false from the ShouldRFP function entirely.
2789 return false;
2790 }
2791
2792 return ContentBlockingAllowList::Check(aCookieJarSettings);
2793}
2794
2795bool nsContentUtils::ETPSaysShouldNotResistFingerprinting(
2796 nsIChannel* aChannel, nsILoadInfo* aLoadInfo) {
2797 bool isPBM = NS_UsePrivateBrowsing(aChannel);
2798
2799 nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
2800 GetCookieJarSettings(aLoadInfo);
2801 if (!cookieJarSettings) {
2802 return false;
2803 }
2804
2805 return ETPSaysShouldNotResistFingerprinting(cookieJarSettings, isPBM);
2806}
2807
2808inline bool CookieJarSettingsSaysShouldResistFingerprinting(
2809 nsILoadInfo* aLoadInfo) {
2810 // A positive return from this function should always be obeyed.
2811 // A negative return means we should keep checking things.
2812
2813 nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
2814 GetCookieJarSettings(aLoadInfo);
2815 if (!cookieJarSettings) {
2816 return false;
2817 }
2818 return cookieJarSettings->GetShouldResistFingerprinting();
2819}
2820
2821inline bool SchemeSaysShouldNotResistFingerprinting(nsIURI* aURI) {
2822 return aURI->SchemeIs("chrome") || aURI->SchemeIs("resource") ||
2823 aURI->SchemeIs("view-source") || aURI->SchemeIs("moz-extension") ||
2824 (aURI->SchemeIs("about") && !NS_IsContentAccessibleAboutURI(aURI));
2825}
2826
2827inline bool SchemeSaysShouldNotResistFingerprinting(nsIPrincipal* aPrincipal) {
2828 if (aPrincipal->SchemeIs("chrome") || aPrincipal->SchemeIs("resource") ||
2829 aPrincipal->SchemeIs("view-source") ||
2830 aPrincipal->SchemeIs("moz-extension")) {
2831 return true;
2832 }
2833
2834 if (!aPrincipal->SchemeIs("about")) {
2835 return false;
2836 }
2837
2838 bool isContentAccessibleAboutURI;
2839 (void)aPrincipal->IsContentAccessibleAboutURI(&isContentAccessibleAboutURI);
2840 return !isContentAccessibleAboutURI;
2841}
2842
2843// mFirstPartyDomain and mPartitionKey are serialized either as a bare host
2844// ("example.com") or in site format ("(https,example.com[,port][,f])"),
2845// depending on privacy.firstparty.isolate.use_site and
2846// privacy.dynamic_firstparty.use_site respectively. Those two prefs are
2847// independent, and ParsePartitionKey() only consults the latter, so detect the
2848// format here instead of letting it decide for a first-party domain.
2849inline void TopLevelInfoToBaseDomain(const nsAString& aInfo,
2850 nsAString& aBaseDomain) {
2851 if (aInfo.IsEmpty() || aInfo.First() != '(') {
2852 aBaseDomain = aInfo;
2853 return;
2854 }
2855
2856 nsAutoString scheme;
2857 int32_t port;
2858 bool foreignByAncestorContext;
2859 if (!OriginAttributes::ParsePartitionKey(aInfo, scheme, aBaseDomain, port,
2860 foreignByAncestorContext)) {
2861 aBaseDomain.Truncate();
2862 }
2863}
2864
2865inline bool PartionKeyIsAlsoExempted(
2866 const mozilla::OriginAttributes& aOriginAttributes) {
2867 // If we've gotten here we have (probably) passed the CookieJarSettings
2868 // check that would tell us that if we _are_ a subdocument, then we are on
2869 // an exempted top-level domain and we should see if we ourselves are
2870 // exempted. But we may have gotten here because we directly called the
2871 // _dangerous function and we haven't done that check, but we _were_
2872 // instatiated from a state where we could have been partitioned.
2873 // So perform this last-ditch check for that scenario.
2874 // We arbitrarily use https as the scheme, but it doesn't matter.
2875 nsAutoString baseDomain;
2876 if (StaticPrefs::privacy_firstparty_isolate() &&
2877 !aOriginAttributes.mFirstPartyDomain.IsEmpty()) {
2878 TopLevelInfoToBaseDomain(aOriginAttributes.mFirstPartyDomain, baseDomain);
2879 } else if (!aOriginAttributes.mPartitionKey.IsEmpty()) {
2880 TopLevelInfoToBaseDomain(aOriginAttributes.mPartitionKey, baseDomain);
2881 }
2882
2883 nsresult rv = NS_ERROR_NOT_INITIALIZED;
2884 nsCOMPtr<nsIURI> uri;
2885 if (!baseDomain.IsEmpty()) {
2886 rv = NS_NewURI(getter_AddRefs(uri), u"https://"_ns + baseDomain);
2887 }
2888
2889 if (!NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2890 nsAutoCString list;
2891 nsRFPService::GetExemptedDomainsLowercase(list);
2892 bool isExemptPartitionKey = nsContentUtils::IsURIInList(uri, list);
2893 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
2894 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
2895 nsAutoCString url;
2896 uri->GetHost(url);
2897 LogDomainAndList("Partition Key", list, url, isExemptPartitionKey);
2898 }
2899 return isExemptPartitionKey;
2900 }
2901 return true;
2902}
2903
2904// Functions ---------------------------------------------------
2905
2906/* static */
2907bool nsContentUtils::ShouldResistFingerprinting(const char* aJustification,
2908 RFPTarget aTarget) {
2909 // See comment in header file for information about usage
2910 // We hardcode PBM to true to be the more restrictive option.
2911 return nsContentUtils::ShouldResistFingerprinting(true, aTarget);
2912}
2913
2914namespace {
2915
2916// This function is only called within this file for Positive Return Checks
2917bool ShouldResistFingerprinting_(const char* aJustification,
2918 bool aIsPrivateMode, RFPTarget aTarget) {
2919 // See comment in header file for information about usage
2920 return nsContentUtils::ShouldResistFingerprinting(aIsPrivateMode, aTarget);
2921}
2922
2923} // namespace
2924
2925/* static */
2926bool nsContentUtils::ShouldResistFingerprinting(CallerType aCallerType,
2927 nsIGlobalObject* aGlobalObject,
2928 RFPTarget aTarget) {
2929 if (aCallerType == CallerType::System) {
2930 return false;
2931 }
2932 return ShouldResistFingerprinting(aGlobalObject, aTarget);
2933}
2934
2935/* static */
2936bool nsContentUtils::ShouldResistFingerprinting(nsIDocShell* aDocShell,
2937 RFPTarget aTarget) {
2938 if (!aDocShell) {
2939 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)
2940 ("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)
2941 "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)
;
2942 return ShouldResistFingerprinting("Null Object", aTarget);
2943 }
2944 return ShouldResistFingerprinting(aDocShell->GetDocument(), aTarget);
2945}
2946
2947/* static */
2948bool nsContentUtils::ShouldResistFingerprinting(const Document* aDocument,
2949 RFPTarget aTarget) {
2950 if (!aDocument) {
2951 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)
2952 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)
2953 ("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)
2954 "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)
;
2955 return ShouldResistFingerprinting("Null Object", aTarget);
2956 }
2957 return aDocument->ShouldResistFingerprinting(aTarget);
2958}
2959
2960/* static */
2961bool nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel,
2962 RFPTarget aTarget) {
2963 if (!aChannel) {
2964 MOZ_LOG(nsContentUtils::ResistFingerprintingLog(), LogLevel::Info,do { const ::mozilla::LogModule* moz_real_module = nsContentUtils
::ResistFingerprintingLog(); if ((__builtin_expect(!!(mozilla
::detail::log_test(moz_real_module, LogLevel::Info)), 0))) { mozilla
::detail::log_print(moz_real_module, LogLevel::Info, "Called nsContentUtils::ShouldResistFingerprinting(nsIChannel* "
"aChannel) with NULL channel"); } } while (0)
2965 ("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)
2966 "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)
;
2967 return ShouldResistFingerprinting("Null Object", aTarget);
2968 }
2969
2970 bool isPBM = NS_UsePrivateBrowsing(aChannel);
2971
2972 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
2973 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
2974 nsCOMPtr<nsIURI> channelURI;
2975 (void)NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
2976 nsAutoCString channelSpec;
2977 channelURI->GetSpec(channelSpec);
2978 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)
2979 ("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)
2980 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)
;
2981 }
2982
2983 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
2984 if (!loadInfo) {
2985 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)
2986 ("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)
2987 "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)
;
2988 return ShouldResistFingerprinting("Null Object", aTarget);
2989 }
2990
2991 // With this check, we can ensure that the prefs and target say yes, so only
2992 // an exemption would cause us to return false.
2993 if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) {
2994 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)
2995 ("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)
2996 " 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)
2997 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)
;
2998 return false;
2999 }
3000
3001 auto contentType = loadInfo->GetExternalContentPolicyType();
3002
3003 if (sSecurityManager && (contentType == ExtContentPolicy::TYPE_DOCUMENT ||
3004 contentType == ExtContentPolicy::TYPE_SUBDOCUMENT)) {
3005 nsCOMPtr<nsIPrincipal> resultPrincipal;
3006 nsresult rv = sSecurityManager->GetChannelResultPrincipal(
3007 aChannel, getter_AddRefs(resultPrincipal));
3008 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && IsPDFJS(resultPrincipal)) {
3009 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)
3010 ("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)
3011 " 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)
;
3012 return false;
3013 }
3014 }
3015
3016 if (ETPSaysShouldNotResistFingerprinting(aChannel, loadInfo)) {
3017 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)
3018 ("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)
3019 " 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)
;
3020 return false;
3021 }
3022
3023 if (CookieJarSettingsSaysShouldResistFingerprinting(loadInfo)) {
3024 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)
3025 ("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)
3026 " 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)
;
3027 return true;
3028 }
3029
3030 // Document types have no loading principal. Subdocument types do have a
3031 // loading principal, but it is the loading principal of the parent
3032 // document; not the subdocument.
3033 // Case 1: Document or Subdocument load
3034 if (contentType == ExtContentPolicy::TYPE_DOCUMENT ||
3035 contentType == ExtContentPolicy::TYPE_SUBDOCUMENT) {
3036 nsCOMPtr<nsIURI> channelURI;
3037 nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
3038 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", 3041
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { MOZ_CrashSequence(__null, 3041); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3039 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", 3041
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { MOZ_CrashSequence(__null, 3041); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3040 "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", 3041
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { MOZ_CrashSequence(__null, 3041); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3041 "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", 3041
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Failed to get URI in " "nsContentUtils::ShouldResistFingerprinting(nsIChannel* aChannel)"
")"); do { MOZ_CrashSequence(__null, 3041); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3042 // this check is to ensure that we do not crash in non-debug builds.
3043 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3044 return true;
3045 }
3046
3047 nsAutoCString loadingPrincipalSpec;
3048 nsAutoCString channelSpec;
3049 channelURI->GetSpec(channelSpec);
3050
3051 if (contentType == ExtContentPolicy::TYPE_SUBDOCUMENT) {
3052 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)
3053 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)
3054 ("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)
3055 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)
3056 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)
3057 ? 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)
3058 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)
;
3059 } else {
3060 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)
3061 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)
3062 ("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)
3063 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)
3064 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)
3065 ? 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)
3066 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)
;
3067 }
3068
3069 return ShouldResistFingerprinting_dangerous(
3070 channelURI, loadInfo->GetOriginAttributes(), "Internal Call", aTarget);
3071 }
3072
3073 // Case 2: Subresource Load
3074 // Because this code is only used for subresource loads, this
3075 // will check the parent's principal
3076 nsIPrincipal* principal = loadInfo->GetLoadingPrincipal();
3077
3078 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", 3081); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { MOZ_CrashSequence(__null, 3081); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3079 !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", 3081); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { MOZ_CrashSequence(__null, 3081); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3080 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", 3081); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { MOZ_CrashSequence(__null, 3081); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3081 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", 3081); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "BasePrincipal::Cast(principal)->OriginAttributesRef() == loadInfo->GetOriginAttributes()"
")"); do { MOZ_CrashSequence(__null, 3081); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3082 return ShouldResistFingerprinting_dangerous(principal, "Internal Call",
3083 aTarget);
3084}
3085
3086/* static */
3087bool nsContentUtils::ShouldResistFingerprinting_dangerous(
3088 nsIURI* aURI, const mozilla::OriginAttributes& aOriginAttributes,
3089 const char* aJustification, RFPTarget aTarget) {
3090 // With this check, we can ensure that the prefs and target say yes, so only
3091 // an exemption would cause us to return false.
3092 bool isPBM = aOriginAttributes.IsPrivateBrowsing();
3093
3094 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)
3095 ("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)
3096 " 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)
3097 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)
;
3098
3099 if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) {
3100 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)
3101 ("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)
3102 " 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)
3103 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)
;
3104 return false;
3105 }
3106
3107 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)
3108 ("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)
3109 " 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)
3110 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)
;
3111
3112 // Exclude internal schemes and web extensions
3113 if (SchemeSaysShouldNotResistFingerprinting(aURI)) {
3114 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)
3115 ("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)
3116 " 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)
;
3117 return false;
3118 }
3119
3120 bool isExemptDomain = false;
3121 nsAutoCString list;
3122 nsRFPService::GetExemptedDomainsLowercase(list);
3123 isExemptDomain = IsURIInList(aURI, list);
3124
3125 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
3126 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
3127 nsAutoCString url;
3128 aURI->GetHost(url);
3129 LogDomainAndList("URI", list, url, isExemptDomain);
3130 }
3131
3132 if (isExemptDomain) {
3133 isExemptDomain &= PartionKeyIsAlsoExempted(aOriginAttributes);
3134 }
3135
3136 return !isExemptDomain;
3137}
3138
3139/* static */
3140bool nsContentUtils::ShouldResistFingerprinting_dangerous(
3141 nsIPrincipal* aPrincipal, const char* aJustification, RFPTarget aTarget) {
3142 if (!aPrincipal) {
3143 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)
3144 ("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)
3145 "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)
;
3146 return ShouldResistFingerprinting("Null object", aTarget);
3147 }
3148
3149 const auto& originAttributes =
3150 BasePrincipal::Cast(aPrincipal)->OriginAttributesRef();
3151 // With this check, we can ensure that the prefs and target say yes, so only
3152 // an exemption would cause us to return false.
3153 bool isPBM = originAttributes.IsPrivateBrowsing();
3154
3155 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
3156 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
3157 nsAutoCString origin;
3158 aPrincipal->GetOrigin(origin);
3159 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)
3160 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)
3161 ("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)
3162 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)
;
3163 }
3164
3165 if (!ShouldResistFingerprinting_("Positive return check", isPBM, aTarget)) {
3166 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)
3167 ("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)
3168 "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)
3169 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)
;
3170 return false;
3171 }
3172
3173 if (aPrincipal->IsSystemPrincipal()) {
3174 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)
3175 ("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)
3176 "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)
;
3177 return false;
3178 }
3179
3180 // Exclude internal schemes and web extensions
3181 if (SchemeSaysShouldNotResistFingerprinting(aPrincipal)) {
3182 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)
3183 ("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)
3184 " 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)
;
3185 return false;
3186 }
3187
3188 // Web extension principals are also excluded
3189 if (BasePrincipal::Cast(aPrincipal)->AddonPolicyCore()) {
3190 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)
3191 ("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)
3192 " 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)
;
3193 return false;
3194 }
3195
3196 bool isExemptDomain = false;
3197 nsAutoCString list;
3198 nsRFPService::GetExemptedDomainsLowercase(list);
3199 aPrincipal->IsURIInList(list, &isExemptDomain);
3200
3201 if (MOZ_LOG_TEST(nsContentUtils::ResistFingerprintingLog(),(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
3202 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(nsContentUtils
::ResistFingerprintingLog(), mozilla::LogLevel::Debug)), 0))
) {
3203 nsAutoCString origin;
3204 aPrincipal->GetOrigin(origin);
3205 LogDomainAndList("URI", list, origin, isExemptDomain);
3206 }
3207
3208 if (isExemptDomain) {
3209 isExemptDomain &= PartionKeyIsAlsoExempted(originAttributes);
3210 }
3211
3212 return !isExemptDomain;
3213}
3214
3215// --------------------------------------------------------------------
3216
3217/* static */
3218void nsContentUtils::CalcRoundedWindowSizeForResistingFingerprinting(
3219 int32_t aChromeWidth, int32_t aChromeHeight, int32_t aScreenWidth,
3220 int32_t aScreenHeight, int32_t aInputWidth, int32_t aInputHeight,
3221 bool aSetOuterWidth, bool aSetOuterHeight, int32_t* aOutputWidth,
3222 int32_t* aOutputHeight) {
3223 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"
, 3223); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOutputWidth"
")"); do { MOZ_CrashSequence(__null, 3223); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3224 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", 3224); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aOutputHeight" ")"); do { MOZ_CrashSequence
(__null, 3224); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3225
3226 int32_t availContentWidth = 0;
3227 int32_t availContentHeight = 0;
3228
3229 availContentWidth = std::min(StaticPrefs::privacy_window_maxInnerWidth(),
3230 aScreenWidth - aChromeWidth);
3231#ifdef MOZ_WIDGET_GTK1
3232 // In the GTK window, it will not report outside system decorations
3233 // when we get available window size, see Bug 581863. So, we leave a
3234 // 40 pixels space for them when calculating the available content
3235 // height. It is not necessary for the width since the content width
3236 // is usually pretty much the same as the chrome width.
3237 availContentHeight = std::min(StaticPrefs::privacy_window_maxInnerHeight(),
3238 (-40 + aScreenHeight) - aChromeHeight);
3239#else
3240 availContentHeight = std::min(StaticPrefs::privacy_window_maxInnerHeight(),
3241 aScreenHeight - aChromeHeight);
3242#endif
3243
3244 // Ideally, we'd like to round window size to 1000x1000, but the
3245 // screen space could be too small to accommodate this size in some
3246 // cases. If it happens, we would round the window size to the nearest
3247 // 200x100.
3248 availContentWidth = availContentWidth - (availContentWidth % 200);
3249 availContentHeight = availContentHeight - (availContentHeight % 100);
3250
3251 // If aIsOuter is true, we are setting the outer window. So we
3252 // have to consider the chrome UI.
3253 int32_t chromeOffsetWidth = aSetOuterWidth ? aChromeWidth : 0;
3254 int32_t chromeOffsetHeight = aSetOuterHeight ? aChromeHeight : 0;
3255 int32_t resultWidth = 0, resultHeight = 0;
3256
3257 // if the original size is greater than the maximum available size, we set
3258 // it to the maximum size. And if the original value is less than the
3259 // minimum rounded size, we set it to the minimum 200x100.
3260 if (aInputWidth > (availContentWidth + chromeOffsetWidth)) {
3261 resultWidth = availContentWidth + chromeOffsetWidth;
3262 } else if (aInputWidth < (200 + chromeOffsetWidth)) {
3263 resultWidth = 200 + chromeOffsetWidth;
3264 } else {
3265 // Otherwise, we round the window to the nearest upper rounded 200x100.
3266 resultWidth = NSToIntCeil((aInputWidth - chromeOffsetWidth) / 200.0) * 200 +
3267 chromeOffsetWidth;
3268 }
3269
3270 if (aInputHeight > (availContentHeight + chromeOffsetHeight)) {
3271 resultHeight = availContentHeight + chromeOffsetHeight;
3272 } else if (aInputHeight < (100 + chromeOffsetHeight)) {
3273 resultHeight = 100 + chromeOffsetHeight;
3274 } else {
3275 resultHeight =
3276 NSToIntCeil((aInputHeight - chromeOffsetHeight) / 100.0) * 100 +
3277 chromeOffsetHeight;
3278 }
3279
3280 *aOutputWidth = resultWidth;
3281 *aOutputHeight = resultHeight;
3282}
3283
3284bool nsContentUtils::ThreadsafeIsCallerChrome() {
3285 return NS_IsMainThread() ? IsCallerChrome()
3286 : IsCurrentThreadRunningChromeWorker();
3287}
3288
3289bool nsContentUtils::IsCallerUAWidget() {
3290 JSContext* cx = GetCurrentJSContext();
3291 if (!cx) {
3292 return false;
3293 }
3294
3295 JS::Realm* realm = JS::GetCurrentRealmOrNull(cx);
3296 if (!realm) {
3297 return false;
3298 }
3299
3300 return xpc::IsUAWidgetScope(realm);
3301}
3302
3303bool nsContentUtils::IsSystemCaller(JSContext* aCx) {
3304 // Note that SubjectPrincipal() assumes we are in a compartment here.
3305 return SubjectPrincipal(aCx) == sSystemPrincipal;
3306}
3307
3308bool nsContentUtils::ThreadsafeIsSystemCaller(JSContext* aCx) {
3309 CycleCollectedJSContext* ccjscx = CycleCollectedJSContext::Get();
3310 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", 3310); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ccjscx->Context() == aCx" ")"); do { MOZ_CrashSequence
(__null, 3310); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3311
3312 return ccjscx->IsSystemCaller();
3313}
3314
3315// static
3316bool nsContentUtils::LookupBindingMember(
3317 JSContext* aCx, nsIContent* aContent, JS::Handle<jsid> aId,
3318 JS::MutableHandle<JS::PropertyDescriptor> aDesc) {
3319 return true;
3320}
3321
3322nsINode* nsContentUtils::GetNearestInProcessCrossDocParentNode(
3323 nsINode* aChild) {
3324 if (aChild->IsDocument()) {
3325 for (BrowsingContext* bc = aChild->AsDocument()->GetBrowsingContext(); bc;
3326 bc = bc->GetParent()) {
3327 if (bc->GetEmbedderElement()) {
3328 return bc->GetEmbedderElement();
3329 }
3330 }
3331 return nullptr;
3332 }
3333
3334 nsINode* parent = aChild->GetParentNode();
3335 if (parent && parent->IsContent() && aChild->IsContent()) {
3336 parent = aChild->AsContent()->GetFlattenedTreeParent();
3337 }
3338
3339 return parent;
3340}
3341
3342bool nsContentUtils::ContentIsHostIncludingDescendantOf(
3343 const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) {
3344 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"
, 3344); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { MOZ_CrashSequence
(__null, 3344); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3345 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"
, 3345); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { MOZ_CrashSequence
(__null, 3345); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3346
3347 while (true) {
3348 if (aPossibleDescendant == aPossibleAncestor) {
3349 return true;
3350 }
3351 if (nsINode* parent = aPossibleDescendant->GetParentNode()) {
3352 aPossibleDescendant = parent;
3353 continue;
3354 }
3355 if (auto* df = DocumentFragment::FromNode(aPossibleDescendant)) {
3356 if (nsINode* host = df->GetHost()) {
3357 aPossibleDescendant = host;
3358 continue;
3359 }
3360 }
3361 break;
3362 }
3363 return false;
3364}
3365
3366// static
3367bool nsContentUtils::ContentIsCrossDocDescendantOf(nsINode* aPossibleDescendant,
3368 nsINode* aPossibleAncestor) {
3369 MOZ_ASSERT(aPossibleDescendant, "The possible descendant is null!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPossibleDescendant)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPossibleDescendant))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("aPossibleDescendant"
" (" "The possible descendant is null!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3369); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { MOZ_CrashSequence
(__null, 3369); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3370 MOZ_ASSERT(aPossibleAncestor, "The possible ancestor is null!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPossibleAncestor)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aPossibleAncestor))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("aPossibleAncestor"
" (" "The possible ancestor is null!" ")", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { MOZ_CrashSequence
(__null, 3370); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3371
3372 do {
3373 if (aPossibleDescendant == aPossibleAncestor) {
3374 return true;
3375 }
3376
3377 aPossibleDescendant =
3378 GetNearestInProcessCrossDocParentNode(aPossibleDescendant);
3379 } while (aPossibleDescendant);
3380
3381 return false;
3382}
3383
3384// static
3385bool nsContentUtils::ContentIsFlattenedTreeDescendantOf(
3386 const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) {
3387 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"
, 3387); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { MOZ_CrashSequence
(__null, 3387); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3388 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"
, 3388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { MOZ_CrashSequence
(__null, 3388); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3389
3390 do {
3391 if (aPossibleDescendant == aPossibleAncestor) {
3392 return true;
3393 }
3394 aPossibleDescendant = aPossibleDescendant->GetFlattenedTreeParentNode();
3395 } while (aPossibleDescendant);
3396
3397 return false;
3398}
3399
3400// static
3401bool nsContentUtils::ContentIsFlattenedTreeDescendantOfForStyle(
3402 const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) {
3403 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"
, 3403); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleDescendant"
") (" "The possible descendant is null!" ")"); do { MOZ_CrashSequence
(__null, 3403); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3404 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"
, 3404); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPossibleAncestor"
") (" "The possible ancestor is null!" ")"); do { MOZ_CrashSequence
(__null, 3404); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3405
3406 do {
3407 if (aPossibleDescendant == aPossibleAncestor) {
3408 return true;
3409 }
3410 aPossibleDescendant =
3411 aPossibleDescendant->GetFlattenedTreeParentNodeForStyle();
3412 } while (aPossibleDescendant);
3413
3414 return false;
3415}
3416
3417// static
3418nsINode* nsContentUtils::Retarget(nsINode* aTargetA, const nsINode* aTargetB) {
3419 while (true && aTargetA) {
3420 // If A's root is not a shadow root...
3421 nsINode* root = aTargetA->SubtreeRoot();
3422 if (!root->IsShadowRoot()) {
3423 // ...then return A.
3424 return aTargetA;
3425 }
3426
3427 // or A's root is a shadow-including inclusive ancestor of B...
3428 if (aTargetB && aTargetB->IsShadowIncludingInclusiveDescendantOf(root)) {
3429 // ...then return A.
3430 return aTargetA;
3431 }
3432
3433 aTargetA = ShadowRoot::FromNode(root)->GetHost();
3434 }
3435
3436 return nullptr;
3437}
3438
3439// static
3440Element* nsContentUtils::GetAnElementForTiming(Element* aTarget,
3441 const Document* aDocument,
3442 nsIGlobalObject* aGlobal) {
3443 if (!aTarget->IsInComposedDoc()) {
3444 return nullptr;
3445 }
3446
3447 if (!aDocument) {
3448 nsCOMPtr<nsPIDOMWindowInner> inner = do_QueryInterface(aGlobal);
3449 if (!inner) {
3450 return nullptr;
3451 }
3452 aDocument = inner->GetExtantDoc();
3453 }
3454
3455 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"
, 3455); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { MOZ_CrashSequence(__null, 3455); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3456
3457 if (aTarget->GetUncomposedDocOrConnectedShadowRoot() != aDocument ||
3458 !aDocument->IsCurrentActiveDocument()) {
3459 return nullptr;
3460 }
3461
3462 return aTarget;
3463}
3464
3465// static
3466nsresult nsContentUtils::GetInclusiveAncestors(nsINode* aNode,
3467 nsTArray<nsINode*>& aArray) {
3468 while (aNode) {
3469 aArray.AppendElement(aNode);
3470 aNode = aNode->GetParentNode();
3471 }
3472 return NS_OK;
3473}
3474
3475// static
3476template <typename GetParentFunc, typename ComputeChildIndexFunc>
3477nsresult static GetInclusiveAncestorsAndOffsetsHelper(
3478 nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes,
3479 nsTArray<Maybe<uint32_t>>& aAncestorOffsets, GetParentFunc aGetParentFunc,
3480 ComputeChildIndexFunc aComputeChildIndexFunc) {
3481 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", 3481); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
3482
3483 if (!aNode->IsContent()) {
3484 return NS_ERROR_FAILURE;
3485 }
3486 nsIContent* content = aNode->AsContent();
3487
3488 if (!aAncestorNodes.IsEmpty()) {
3489 NS_WARNING("aAncestorNodes is not empty")NS_DebugBreak(NS_DEBUG_WARNING, "aAncestorNodes is not empty"
, nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp",
3489)
;
3490 aAncestorNodes.Clear();
3491 }
3492
3493 if (!aAncestorOffsets.IsEmpty()) {
3494 NS_WARNING("aAncestorOffsets is not empty")NS_DebugBreak(NS_DEBUG_WARNING, "aAncestorOffsets is not empty"
, nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp",
3494)
;
3495 aAncestorOffsets.Clear();
3496 }
3497
3498 // insert the node itself
3499 aAncestorNodes.AppendElement(content);
3500 aAncestorOffsets.AppendElement(Some(aOffset));
3501
3502 // insert all the ancestors
3503 nsIContent* child = content;
3504 nsIContent* parent = aGetParentFunc(child);
3505 while (parent) {
3506 aAncestorNodes.AppendElement(parent->AsContent());
3507 aAncestorOffsets.AppendElement(aComputeChildIndexFunc(parent, child));
3508 child = parent;
3509 parent = aGetParentFunc(child);
3510 }
3511
3512 return NS_OK;
3513}
3514
3515nsresult nsContentUtils::GetInclusiveAncestorsAndOffsets(
3516 nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes,
3517 nsTArray<Maybe<uint32_t>>& aAncestorOffsets) {
3518 return GetInclusiveAncestorsAndOffsetsHelper(
3519 aNode, aOffset, aAncestorNodes, aAncestorOffsets,
3520 [](nsIContent* aContent) { return aContent->GetParent(); },
3521 [](nsIContent* aParent, nsIContent* aChild) {
3522 return aParent->ComputeIndexOf(aChild);
3523 });
3524}
3525
3526nsresult nsContentUtils::GetFlattenedTreeAncestorsAndOffsetsForSelection(
3527 nsINode* aNode, uint32_t aOffset, nsTArray<nsIContent*>& aAncestorNodes,
3528 nsTArray<Maybe<uint32_t>>& aAncestorOffsets) {
3529 return GetInclusiveAncestorsAndOffsetsHelper(
3530 aNode, aOffset, aAncestorNodes, aAncestorOffsets,
3531 [](nsIContent* aContent) -> nsIContent* {
3532 return nsIContent::FromNodeOrNull(
3533 GetParentNodeForComparison<TreeKind::FlatForSelection>::Get(
3534 aContent));
3535 },
3536 [](nsIContent* aParent, nsIContent* aChild) {
3537 return GetParentNodeForComparison<
3538 TreeKind::FlatForSelection>::ComputeChildIndex(aParent, aChild);
3539 });
3540}
3541
3542/* static */
3543nsINode* nsContentUtils::GetCommonAncestorHelper(nsINode* aNode1,
3544 nsINode* aNode2) {
3545 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"
, 3545); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ")"
); do { MOZ_CrashSequence(__null, 3545); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3546 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"
, 3546); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ")"
); do { MOZ_CrashSequence(__null, 3546); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3547 return CommonAncestors<GetParentNode>(*aNode1, *aNode2)
3548 .GetClosestCommonAncestor();
3549}
3550
3551/* static */
3552nsINode* nsContentUtils::GetClosestCommonShadowIncludingInclusiveAncestor(
3553 nsINode* aNode1, nsINode* aNode2) {
3554 if (aNode1 == aNode2) {
3555 return aNode1;
3556 }
3557
3558 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"
, 3558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ")"
); do { MOZ_CrashSequence(__null, 3558); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3559 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"
, 3559); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ")"
); do { MOZ_CrashSequence(__null, 3559); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3560 return CommonAncestors<GetParentOrShadowHostNode>(*aNode1, *aNode2)
3561 .GetClosestCommonAncestor();
3562}
3563
3564/* static */
3565nsIContent* nsContentUtils::GetCommonFlattenedTreeAncestorHelper(
3566 nsIContent* aContent1, nsIContent* aContent2) {
3567 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"
, 3567); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent1" ")"
); do { MOZ_CrashSequence(__null, 3567); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3568 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"
, 3568); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent2" ")"
); do { MOZ_CrashSequence(__null, 3568); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3569 return CommonAncestors<GetFlattenedTreeParent>(*aContent1, *aContent2)
3570 .GetClosestCommonAncestor();
3571}
3572
3573/* static */
3574nsINode* nsContentUtils::GetCommonFlattenedTreeAncestorForSelection(
3575 nsINode* aNode1, nsINode* aNode2) {
3576 if (aNode1 == aNode2) {
3577 return aNode1;
3578 }
3579 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"
, 3579); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ")"
); do { MOZ_CrashSequence(__null, 3579); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3580 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"
, 3580); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ")"
); do { MOZ_CrashSequence(__null, 3580); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3581 return CommonAncestors<GetFlattenedTreeParentNodeForSelection>(*aNode1,
3582 *aNode2)
3583 .GetClosestCommonAncestor();
3584}
3585
3586/* static */
3587Element* nsContentUtils::GetCommonFlattenedTreeAncestorForStyle(
3588 Element* aElement1, Element* aElement2) {
3589 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"
, 3589); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement1" ")"
); do { MOZ_CrashSequence(__null, 3589); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3590 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"
, 3590); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement2" ")"
); do { MOZ_CrashSequence(__null, 3590); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3591 return CommonAncestors<GetFlattenedTreeParentElementForStyle>(*aElement1,
3592 *aElement2)
3593 .GetClosestCommonAncestor();
3594}
3595
3596/* static */
3597template <TreeKind aKind, typename Dummy>
3598Maybe<int32_t> nsContentUtils::CompareChildNodes(
3599 const nsINode& aParent, const nsIContent* aChild1,
3600 const nsIContent* aChild2, NodeIndexCache* aIndexCache /* = nullptr */) {
3601 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", 3602); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3602); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3602 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", 3602); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3602); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3603 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", 3604); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3604); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3604 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", 3604); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3604); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3605 // See the explanation of TreeKindToCompareChildren. aParent may be computed
3606 // with TreeKind::ShadowIncludingDOM if aKind is TreeKind::DOM.
3607 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", 3611); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3611); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3608 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", 3611); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3611); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3609 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", 3611); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3611); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3610 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", 3611); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3611); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3611 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", 3611); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3611); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3612 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", 3616); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3616); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3613 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", 3616); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3616); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3614 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", 3616); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3616); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3615 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", 3616); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3616); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3616 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", 3616); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3616); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3617
3618 // FIXME: bug 1946003 and bug 1946008.
3619 if ((aChild1 && NS_WARN_IF(aChild1->IsDocumentFragment())NS_warn_if_impl(aChild1->IsDocumentFragment(), "aChild1->IsDocumentFragment()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3619)
) ||
3620 (aChild2 && NS_WARN_IF(aChild2->IsDocumentFragment())NS_warn_if_impl(aChild2->IsDocumentFragment(), "aChild2->IsDocumentFragment()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 3620)
)) [[unlikely]] {
3621 return Nothing();
3622 }
3623 if (MOZ_UNLIKELY(aChild1 == aChild2)(__builtin_expect(!!(aChild1 == aChild2), 0))) {
3624 return Some(0);
3625 }
3626 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", 3626); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aChild1 || aChild2" ")"); do { MOZ_CrashSequence
(__null, 3626); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3627 // Native anonymous content (e.g. ::before/::after pseudo-elements) is not in
3628 // the regular child list, so the sibling/index fast paths below cannot order
3629 // it against regular children or the end-of-children boundary (a null child).
3630 // GetIndexInParent assigns flat-tree-consistent indices to NAC roots, so use
3631 // it to order the points instead.
3632 if (MOZ_UNLIKELY((aChild1 && aChild1->IsRootOfNativeAnonymousSubtree()) ||(__builtin_expect(!!((aChild1 && aChild1->IsRootOfNativeAnonymousSubtree
()) || (aChild2 && aChild2->IsRootOfNativeAnonymousSubtree
())), 0))
3633 (aChild2 && aChild2->IsRootOfNativeAnonymousSubtree()))(__builtin_expect(!!((aChild1 && aChild1->IsRootOfNativeAnonymousSubtree
()) || (aChild2 && aChild2->IsRootOfNativeAnonymousSubtree
())), 0))
) {
3634 const nsINode& parent =
3635 aChild1 ? *GetParentNodeForComparison<aKind>::Get(aChild1)
3636 : *GetParentNodeForComparison<aKind>::Get(aChild2);
3637 // A null child is the boundary at the end of the parent's regular child
3638 // list (offset == number of regular children). Regular children occupy
3639 // indices [0, regularCount) in the index space assigned by
3640 // GetIndexInParent, while trailing NAC (other anonymous subtrees and
3641 // ::after) start at regularCount. The discriminator here must match the
3642 // one in GetIndexInParent so the boundary lands in the same index space:
3643 // only the flat tree indexes regular children via the flattened iterator;
3644 // DOM and ShadowIncludingDOM both index them via ComputeIndexOf.
3645 const int32_t regularCount =
3646 aKind == TreeKind::Flat
3647 ? int32_t(FlattenedChildIterator::GetLength(&parent))
3648 : int32_t(parent.GetChildCount());
3649 const auto indexOf = [&](const nsIContent* aChild) -> Maybe<int32_t> {
3650 if (!aChild) {
3651 return Some(regularCount);
3652 }
3653 return aIndexCache ? aIndexCache->ComputeIndexOf<aKind>(&parent, aChild)
3654 : GetIndexInParent<aKind>(&parent, aChild);
3655 };
3656 const Maybe<int32_t> child1Index = indexOf(aChild1);
3657 const Maybe<int32_t> child2Index = indexOf(aChild2);
3658 if (MOZ_LIKELY(child1Index.isSome() && child2Index.isSome())(__builtin_expect(!!(child1Index.isSome() && child2Index
.isSome()), 1))
) {
3659 if (*child1Index != *child2Index) {
3660 return Some(*child1Index < *child2Index ? -1 : 1);
3661 }
3662 // Equal indices only happen when one child is the end-of-children
3663 // boundary (null) and the other is the first trailing NAC subtree at the
3664 // same index. The boundary precedes trailing NAC in tree order.
3665 if (!aChild1) {
3666 return Some(-1);
3667 }
3668 if (!aChild2) {
3669 return Some(1);
3670 }
3671 }
3672 // XXX Keep the odd traditional behavior for now.
3673 return Some(1);
3674 }
3675 if (!aChild1) { // i.e., end of parent vs aChild2
3676 return Some(1);
3677 }
3678 if (!aChild2) { // i.e., aChild1 vs. end of parent
3679 return Some(-1);
3680 }
3681
3682 if constexpr (aKind == TreeKind::FlatForSelection) {
3683 // If we're handling flattened tree for selection, aChild1 and/or aChild2
3684 // may be:
3685 // - fallback content of a <slot> which has some assigned nodes
3686 // - unassigned child node of a shadow host
3687 // Even though they are not part of the flattened tree, but they are also
3688 // valid for range boundaries. Therefore, we need to handle the case here.
3689 if (aParent.GetAsHTMLSlotElementIfFilledForSelection() ||
3690 aParent.GetShadowRootForSelection()) {
3691 if (aChild1->GetParentNode() == &aParent) {
3692 if (aChild2->GetParentNode() == &aParent) {
3693 // If both aChild1 and aChild2 are the fallback content or the
3694 // unassigned children of a shadow host, compare them in the DOM.
3695 return CompareChildNodes<TreeKind::DOM>(aParent, aChild1, aChild2);
3696 }
3697 // If only aChild1 is the fallback content or the unassigned child,
3698 // let's treat it as after the last assigned node.
3699 return Some(1);
3700 }
3701 if (aChild2->GetParentNode() == &aParent) {
3702 // If only aChild2 is the fallback content or the unassigned child,
3703 // let's treat it as after the last assigned node for now.
3704 return Some(-1);
3705 }
3706 }
3707 }
3708
3709 if constexpr (ShouldHandleAssignedNodesOnSlot<aKind>()) {
3710 HTMLSlotElement* const slot1 = aChild1->GetAssignedSlot<aKind>();
3711 HTMLSlotElement* const slot2 = aChild2->GetAssignedSlot<aKind>();
3712 if (slot1 || slot2) {
3713 // If they are assigned into a same <slot>, compare the index.
3714 if (slot1 == slot2) {
3715 const auto* slot = HTMLSlotElement::FromNode(aParent);
3716 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"
, 3716); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slot" ")");
do { MOZ_CrashSequence(__null, 3716); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3717
3718 constexpr auto NoIndex = size_t(-1);
3719 auto child1Index = NoIndex;
3720 auto child2Index = NoIndex;
3721 size_t index = 0;
3722 for (nsINode* node : slot->AssignedNodes()) {
3723 if (node == aChild1) {
3724 child1Index = index;
3725 if (child2Index != NoIndex) {
3726 break;
3727 }
3728 } else if (node == aChild2) {
3729 child2Index = index;
3730 if (child1Index != NoIndex) {
3731 break;
3732 }
3733 }
3734 index++;
3735 }
3736
3737 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", 3737); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "child1Index != NoIndex" ")"); do { MOZ_CrashSequence
(__null, 3737); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3738 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", 3738); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "child2Index != NoIndex" ")"); do { MOZ_CrashSequence
(__null, 3738); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3739
3740 return Some(child1Index < child2Index ? -1 : 1);
3741 }
3742 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"
, 3748)
3743 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"
, 3748)
3744 "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"
, 3748)
3745 "<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"
, 3748)
3746 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"
, 3748)
3747 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"
, 3748)
3748 .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"
, 3748)
;
3749 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"
, 3749); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!slot1" ")"
); do { MOZ_CrashSequence(__null, 3749); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3750 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"
, 3750); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!slot2" ")"
); do { MOZ_CrashSequence(__null, 3750); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3751 return Nothing();
3752 }
3753 }
3754
3755 ChildIteratorBase<aKind> iter(&aParent);
3756
3757 // If the parent node is not a shadow host, we can use
3758 // nsINode::GetNextSibling() and nsINode::GetPreviousSibling() in any trees
3759 // so that we can check whether aChild1 and aChild2 are adjacent siblings.
3760 if (MOZ_LIKELY(!iter.ShadowDOMInvolved())(__builtin_expect(!!(!iter.ShadowDOMInvolved()), 1))) {
3761 if (aChild1->GetNextSibling() == aChild2) {
3762 return Some(-1);
3763 }
3764 if (aChild2->GetNextSibling() == aChild1) {
3765 return Some(1);
3766 }
3767 }
3768
3769 // Retrieving the first child and the last child is not expensive so, let's
3770 // check whether aChild1 or aChild2 is the first/last child.
3771 const nsIContent* lastChild = iter.GetLastChild();
3772 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"
, 3772); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lastChild" ")"
); do { MOZ_CrashSequence(__null, 3772); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3773 if (aChild1 == lastChild) {
3774 return Some(1);
3775 }
3776 if (aChild2 == lastChild) {
3777 return Some(-1);
3778 }
3779 const nsIContent* firstChild = iter.GetFirstChild();
3780 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"
, 3780); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstChild"
")"); do { MOZ_CrashSequence(__null, 3780); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3781 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", 3781); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "firstChild != lastChild" ")"); do { MOZ_CrashSequence
(__null, 3781); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
3782 if (aChild1 == firstChild) {
3783 return Some(-1);
3784 }
3785 if (aChild2 == firstChild) {
3786 return Some(1);
3787 }
3788
3789 // nsINode::ComputeIndexOf() computes the index with scanning siblings from
3790 // the first child in the worst case. However, if the node caches the
3791 // computed result, the scan range may be narrowed in fortunate cases.
3792 // Therefore, if the node uses the cache, we should use it because the callers
3793 // may need to compute the index again. In such cases, the cache saves the
3794 // computation cost.
3795 if (aParent.MaybeCachesComputedIndex()) {
3796 Maybe<uint32_t> child1Index;
3797 Maybe<uint32_t> child2Index;
3798 if (aIndexCache) {
3799 Maybe<int32_t> maybeGenContentChild1Index;
3800 Maybe<int32_t> maybeGenContentChild2Index;
3801 aIndexCache->ComputeIndicesOf<aKind>(&aParent, aChild1, aChild2,
3802 maybeGenContentChild1Index,
3803 maybeGenContentChild2Index);
3804 // Negative offset if the child is generated content or native anonymous
3805 // content. However, this method does not support such nodes. Therefore,
3806 // we should treat them as "disconnected".
3807 if (maybeGenContentChild1Index && *maybeGenContentChild1Index >= 0) {
3808 child1Index.emplace(static_cast<uint32_t>(*maybeGenContentChild1Index));
3809 }
3810 if (maybeGenContentChild2Index && *maybeGenContentChild2Index >= 0) {
3811 child2Index.emplace(static_cast<uint32_t>(*maybeGenContentChild2Index));
3812 }
3813#ifdef DEBUG1
3814 const Maybe<uint32_t> child1IndexDebug =
3815 aParent.ComputeIndexOf<aKind>(aChild1);
3816 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"
, 3822); } } while (false)
3817 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"
, 3822); } } while (false)
3818 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"
, 3822); } } while (false)
3819 "{}\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"
, 3822); } } while (false)
3820 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"
, 3822); } } while (false)
3821 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"
, 3822); } } while (false)
3822 .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"
, 3822); } } while (false)
;
3823 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"
, 3823); AnnotateMozCrashReason("MOZ_ASSERT" "(" "child1Index == child1IndexDebug"
")"); do { MOZ_CrashSequence(__null, 3823); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3824 const Maybe<uint32_t> child2IndexDebug =
3825 aParent.ComputeIndexOf<aKind>(aChild2);
3826 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"
, 3832); } } while (false)
3827 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"
, 3832); } } while (false)
3828 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"
, 3832); } } while (false)
3829 "{}\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"
, 3832); } } while (false)
3830 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"
, 3832); } } while (false)
3831 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"
, 3832); } } while (false)
3832 .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"
, 3832); } } while (false)
;
3833 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"
, 3833); AnnotateMozCrashReason("MOZ_ASSERT" "(" "child2Index == child2IndexDebug"
")"); do { MOZ_CrashSequence(__null, 3833); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3834#endif // #ifdef DEBUG
3835 } else {
3836 child1Index = aParent.ComputeIndexOf<aKind>(aChild1);
3837 child2Index = aParent.ComputeIndexOf<aKind>(aChild2);
3838 }
3839 if (MOZ_LIKELY(child1Index.isSome() && child2Index.isSome())(__builtin_expect(!!(child1Index.isSome() && child2Index
.isSome()), 1))
) {
3840 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"
, 3840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "*child1Index != *child2Index"
")"); do { MOZ_CrashSequence(__null, 3840); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3841 return Some(*child1Index < *child2Index ? -1 : 1);
3842 }
3843 // XXX Keep the odd traditional behavior for now.
3844 return Some(child1Index.isNothing() && child2Index.isSome() ? -1 : 1);
3845 }
3846
3847 // On the other hand, it does not use the cache, let's scan siblings starting
3848 // from aChild1. Then, if we find aChild2, the position is aChild1 < aChild2.
3849 // Otherwise, aChild2 < aChild1. This narrows the scanning range than using
3850 // ComputeIndexOf(), i.e., even in the worst case, this is faster than a call
3851 // of ComputeIndexOf().
3852 if (NS_WARN_IF(!iter.Seek(aChild1))NS_warn_if_impl(!iter.Seek(aChild1), "!iter.Seek(aChild1)", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 3852)
) {
3853 return Nothing{};
3854 }
3855 for (const nsIContent* followingSiblingOfChild1 = iter.GetNextChild();
3856 followingSiblingOfChild1;
3857 followingSiblingOfChild1 = iter.GetNextChild()) {
3858 if (followingSiblingOfChild1 == aChild2) {
3859 return Some(-1);
3860 }
3861 }
3862 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"
, 3862); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent.ComputeIndexOf<aKind>(aChild2).isSome()"
")"); do { MOZ_CrashSequence(__null, 3862); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3863 return Some(1);
3864}
3865
3866/* static */
3867template <TreeKind aKind, typename Dummy>
3868Maybe<int32_t> nsContentUtils::CompareClosestCommonAncestorChildren(
3869 const nsINode& aParent, const nsIContent* aChild1,
3870 const nsIContent* aChild2, nsContentUtils::NodeIndexCache* aIndexCache) {
3871 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", 3872); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3872); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3872 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", 3872); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3872); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3873 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", 3874); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3874); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3874 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", 3874); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3874); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3875 // See the explanation of TreeKindToCompareChildren. aParent may be computed
3876 // with TreeKind::ShadowIncludingDOM if aKind is TreeKind::DOM.
3877 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", 3881); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3881); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3878 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", 3881); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3881); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3879 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", 3881); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3881); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3880 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", 3881); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3881); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3881 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", 3881); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild1) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild1) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3881); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3882 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", 3886); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3886); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3883 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", 3886); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3886); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3884 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", 3886); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3886); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3885 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", 3886); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3886); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3886 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", 3886); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 3886); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3887
3888 if (aChild1 && aChild2) {
3889 if (MOZ_UNLIKELY(aChild1->IsShadowRoot())(__builtin_expect(!!(aChild1->IsShadowRoot()), 0))) {
3890 // Shadow roots come before light DOM per
3891 // https://dom.spec.whatwg.org/#concept-shadow-including-tree-order
3892 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"
, 3892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aChild2->IsShadowRoot()"
") (" "Two shadow roots?" ")"); do { MOZ_CrashSequence(__null
, 3892); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
3893 return Some(-1);
3894 }
3895 if (MOZ_UNLIKELY(aChild2->IsShadowRoot())(__builtin_expect(!!(aChild2->IsShadowRoot()), 0))) {
3896 return Some(1);
3897 }
3898 }
3899 // FIXME: bug 1946003 and bug 1946008.
3900 if (MOZ_UNLIKELY((aChild1 && aChild1->IsDocumentFragment()) ||(__builtin_expect(!!((aChild1 && aChild1->IsDocumentFragment
()) || (aChild2 && aChild2->IsDocumentFragment()))
, 0))
3901 (aChild2 && aChild2->IsDocumentFragment()))(__builtin_expect(!!((aChild1 && aChild1->IsDocumentFragment
()) || (aChild2 && aChild2->IsDocumentFragment()))
, 0))
) {
3902 // XXX Keep the odd traditional behavior for now. I think that we should
3903 // return Nothing in this case.
3904 return Some(1);
3905 }
3906
3907 const Maybe<int32_t> comp = nsContentUtils::CompareChildNodes<aKind>(
3908 aParent, aChild1, aChild2, aIndexCache);
3909 if (MOZ_UNLIKELY(comp.isNothing())(__builtin_expect(!!(comp.isNothing()), 0))) {
3910 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", 3912); MOZ_PretendNoReturn
(); } } while (0)
3911 "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", 3912); MOZ_PretendNoReturn
(); } } while (0)
3912 "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", 3912); MOZ_PretendNoReturn
(); } } while (0)
;
3913 // XXX Keep the odd traditional behavior for now. I think that we should
3914 // return Nothing in this case.
3915 return Some(1);
3916 }
3917#ifdef DEBUG1
3918 const auto NodeIsNullOrValidChild = [](const nsINode& aParent,
3919 const nsIContent* aChild) {
3920 if (!aChild || aParent.ComputeIndexOf<aKind>(aChild).isSome()) {
3921 return true;
3922 }
3923 if constexpr (aKind == TreeKind::FlatForSelection) {
3924 const Element* const excluderShadowHostOrSlotElement =
3925 aChild->GetClosestFlatTreeAncestorElementForNonFlatTreeNode<
3926 TreeKind::FlatForSelection>();
3927 if (excluderShadowHostOrSlotElement &&
3928 (excluderShadowHostOrSlotElement == &aParent ||
3929 excluderShadowHostOrSlotElement->GetShadowRootForSelection() ==
3930 &aParent)) {
3931 return true;
3932 }
3933 }
3934 return false;
3935 };
3936 const auto ChildrenHaveSameIndex = [](const nsIContent* aChild1,
3937 const nsIContent* aChild2) {
3938 if (aChild1 == aChild2) {
3939 return true;
3940 }
3941 const bool child1IsAtEndOfParent =
3942 !aChild1 ||
3943 (aKind == TreeKind::FlatForSelection &&
3944 aChild1->GetClosestFlatTreeAncestorElementForNonFlatTreeNode<
3945 TreeKind::FlatForSelection>());
3946 const bool child2IsAtEndOfParent =
3947 !aChild2 ||
3948 (aKind == TreeKind::FlatForSelection &&
3949 aChild2->GetClosestFlatTreeAncestorElementForNonFlatTreeNode<
3950 TreeKind::FlatForSelection>());
3951 return child1IsAtEndOfParent && child2IsAtEndOfParent;
3952 };
3953 const auto ChildIndexIsLessThanTheOtherChildIndex =
3954 [](const nsINode& aParent, const nsIContent* aChild1,
3955 const nsIContent* aChild2) {
3956 const uint32_t child1Index =
3957 aChild1 ? aParent.ComputeIndexOf<aKind>(aChild1).valueOr(
3958 aParent.GetChildCount<aKind>())
3959 : aParent.GetChildCount<aKind>();
3960 const uint32_t child2Index =
3961 aChild2 ? aParent.ComputeIndexOf<aKind>(aChild2).valueOr(
3962 aParent.GetChildCount<aKind>())
3963 : aParent.GetChildCount<aKind>();
3964 return child1Index < child2Index;
3965 };
3966 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", 3970); }
} while (false)
3967 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", 3970); }
} while (false)
3968 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", 3970); }
} while (false)
3969 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", 3970); }
} while (false)
3970 .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", 3970); }
} while (false)
;
3971 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", 3975); }
} while (false)
3972 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", 3975); }
} while (false)
3973 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", 3975); }
} while (false)
3974 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", 3975); }
} while (false)
3975 .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", 3975); }
} while (false)
;
3976 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", 3976); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aChild1 == aChild2" ")"); do { MOZ_CrashSequence
(__null, 3976); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
3977 const DebugOnly<bool> eitherIsNAC =
3978 (aChild1 && aChild1->IsRootOfNativeAnonymousSubtree()) ||
3979 (aChild2 && aChild2->IsRootOfNativeAnonymousSubtree());
3980 const DebugOnly<bool> eitherIsNotPartOfTree =
3981 ShouldHandleAssignedNodesOnSlot<aKind>() &&
3982 ((aParent.GetShadowRoot<aKind>() &&
3983 ((aChild1 && aChild1->GetParentNode() == &aParent) ||
3984 (aChild2 && aChild2->GetParentNode() == &aParent))) ||
3985 ((aParent.GetAsHTMLSlotElementIfFilled<aKind>() &&
3986 ((aChild1 && !aChild1->GetAssignedSlot<aKind>()) ||
3987 (aChild2 && !aChild2->GetAssignedSlot<aKind>())))));
3988 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"
, 3989); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChildrenHaveSameIndex(aChild1, aChild2)"
")"); do { MOZ_CrashSequence(__null, 3989); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3989 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"
, 3989); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChildrenHaveSameIndex(aChild1, aChild2)"
")"); do { MOZ_CrashSequence(__null, 3989); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3990 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", 3992); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2)"
")"); do { MOZ_CrashSequence(__null, 3992); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3991 !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", 3992); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2)"
")"); do { MOZ_CrashSequence(__null, 3992); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3992 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", 3992); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild1, aChild2)"
")"); do { MOZ_CrashSequence(__null, 3992); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3993 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", 3995); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1)"
")"); do { MOZ_CrashSequence(__null, 3995); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3994 !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", 3995); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1)"
")"); do { MOZ_CrashSequence(__null, 3995); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
3995 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", 3995); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChildIndexIsLessThanTheOtherChildIndex(aParent, aChild2, aChild1)"
")"); do { MOZ_CrashSequence(__null, 3995); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3996#endif // #ifdef DEBUG
3997 return comp;
3998}
3999
4000/* static */
4001template <TreeKind aKind, typename Dummy>
4002Maybe<int32_t> nsContentUtils::CompareChildOffsetAndChildNode(
4003 const nsINode& aParent, uint32_t aOffset1, const nsIContent& aChild2,
4004 NodeIndexCache* aIndexCache /* = nullptr */) {
4005 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", 4006); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4006); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4006 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", 4006); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4006); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4007 // See the explanation of TreeKindToCompareChildren. aParent may be computed
4008 // with TreeKind::ShadowIncludingDOM if aKind is TreeKind::DOM.
4009 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", 4013); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4013); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4010 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", 4013); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4013); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4011 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", 4013); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4013); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4012 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", 4013); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4013); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4013 &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", 4013); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<TreeKind::DOM>::Get(&aChild2) == &aParent || GetParentNodeForComparison<TreeKind::ShadowIncludingDOM>::Get( &aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4013); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4014
4015 if (NS_WARN_IF(aChild2.IsDocumentFragment())NS_warn_if_impl(aChild2.IsDocumentFragment(), "aChild2.IsDocumentFragment()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4015)
) {
4016 return Nothing();
4017 }
4018 // Native anonymous content (e.g. ::before/::after) is not in the regular
4019 // child list, so order it against the [parentNode, aOffset1] boundary using
4020 // the flat-tree index space from GetIndexInParent. aOffset1 indexes regular
4021 // children [0, N); the NAC child sits at child2Index in the same space, and
4022 // the boundary precedes it iff aOffset1 <= child2Index.
4023 if (MOZ_UNLIKELY(aChild2.IsRootOfNativeAnonymousSubtree())(__builtin_expect(!!(aChild2.IsRootOfNativeAnonymousSubtree()
), 0))
) {
4024 const Maybe<int32_t> child2Index =
4025 aIndexCache ? aIndexCache->ComputeIndexOf<aKind>(&aParent, &aChild2)
4026 : GetIndexInParent<aKind>(&aParent, &aChild2);
4027 if (NS_WARN_IF(child2Index.isNothing())NS_warn_if_impl(child2Index.isNothing(), "child2Index.isNothing()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4027)
) {
4028 // XXX Keep the odd traditional behavior for now.
4029 return Some(1);
4030 }
4031 return Some(int32_t(aOffset1) <= *child2Index ? -1 : 1);
4032 }
4033
4034 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", 4034); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get(&aChild2) == &aParent"
")"); do { MOZ_CrashSequence(__null, 4034); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4035
4036 const uint32_t parentNodeChildCount = aParent.GetChildCount<aKind>();
4037 if (NS_WARN_IF(aOffset1 > parentNodeChildCount)NS_warn_if_impl(aOffset1 > parentNodeChildCount, "aOffset1 > parentNodeChildCount"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4037)
) {
4038 // If the root caller's boundary points after end of aParent, let's treat
4039 // it's after the fallback content for now... If you find a bug and you know
4040 // better result in this case, feel free to change.
4041 return Some(1);
4042 }
4043
4044 if constexpr (aKind == TreeKind::FlatForSelection) {
4045 // If we're handling flattened tree for selection, aChild2 may be a fallback
4046 // content of a <slot> which has some assigned nodes or an unassigned child
4047 // node of a shadow host. Then, aChild2 is not part of the flattened tree,
4048 // but it is also valid for range boundaries. Therefore, we need to handle
4049 // the case here.
4050 if (aChild2.GetParentNode() == &aParent &&
4051 (aParent.GetAsHTMLSlotElementIfFilledForSelection() ||
4052 aParent.GetShadowRootForSelection())) {
4053 // Treat the fallback content and the unassigned node is after the last
4054 // assigned node or the shadow.
4055 // XXX I'm not sure whether we should treat the end of aParent and a
4056 // fallback content node are the same position or not. For now, we treat
4057 // them as the same, but if you find a bug and you know better result in
4058 // this case, feel free to change here.
4059 return aOffset1 == parentNodeChildCount ? Some(0) : Some(-1);
4060 }
4061 }
4062
4063 if (aOffset1 == parentNodeChildCount) {
4064 return Some(1); // Comparing with after the last child and a child.
4065 }
4066
4067 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"
, 4067); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent.GetFirstChild<aKind>()"
")"); do { MOZ_CrashSequence(__null, 4067); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4068 const nsIContent& firstChild = *aParent.GetFirstChild<aKind>();
4069 if (&aChild2 == &firstChild) {
4070 return Some(!aOffset1 ? 0 : 1);
4071 }
4072
4073 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"
, 4073); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent.GetLastChild<aKind>()"
")"); do { MOZ_CrashSequence(__null, 4073); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4074 const nsIContent& lastChild = *aParent.GetLastChild<aKind>();
4075 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", 4079); }
} while (false)
4076 &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", 4079); }
} while (false)
4077 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", 4079); }
} while (false)
4078 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", 4079); }
} while (false)
4079 .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", 4079); }
} while (false)
;
4080 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"
, 4080); AnnotateMozCrashReason("MOZ_ASSERT" "(" "&firstChild != &lastChild"
")"); do { MOZ_CrashSequence(__null, 4080); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4081 if (&aChild2 == &lastChild) {
4082 return Some(aOffset1 == parentNodeChildCount - 1 ? 0 : -1);
4083 }
4084 Maybe<uint32_t> child2Index;
4085 if (aIndexCache) {
4086 const Maybe<int32_t> maybeGenContentChild2Index =
4087 aIndexCache->ComputeIndexOf<aKind>(&aParent, &aChild2);
4088 if (maybeGenContentChild2Index && *maybeGenContentChild2Index >= 0) {
4089 child2Index.emplace(static_cast<uint32_t>(*maybeGenContentChild2Index));
4090 }
4091#ifdef DEBUG1
4092 const Maybe<uint32_t> child2IndexDebug =
4093 aParent.ComputeIndexOf<aKind>(&aChild2);
4094 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"
, 4100); } } while (false)
4095 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"
, 4100); } } while (false)
4096 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"
, 4100); } } while (false)
4097 "{}\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"
, 4100); } } while (false)
4098 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"
, 4100); } } while (false)
4099 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"
, 4100); } } while (false)
4100 .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"
, 4100); } } while (false)
;
4101 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"
, 4101); AnnotateMozCrashReason("MOZ_ASSERT" "(" "child2Index == child2IndexDebug"
")"); do { MOZ_CrashSequence(__null, 4101); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4102#endif // #ifdef DEBUG
4103 } else {
4104 child2Index = aParent.ComputeIndexOf<aKind>(&aChild2);
4105 }
4106 if (NS_WARN_IF(child2Index.isNothing())NS_warn_if_impl(child2Index.isNothing(), "child2Index.isNothing()"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 4106)
) {
4107 return Some(1);
4108 }
4109 return Some(aOffset1 == *child2Index ? 0
4110 : (aOffset1 < *child2Index ? -1 : 1));
4111}
4112
4113/* static */
4114template <TreeKind aKind, typename Dummy>
4115Maybe<int32_t> nsContentUtils::CompareChildNodeAndChildOffset(
4116 const nsINode& aParent, const nsIContent& aChild1, uint32_t aOffset2,
4117 NodeIndexCache* aIndexCache /* = nullptr */) {
4118 const Maybe<int32_t> comp = CompareChildOffsetAndChildNode<aKind>(
4119 aParent, aOffset2, aChild1, aIndexCache);
4120 if (comp.isNothing()) {
4121 return comp;
4122 }
4123 return Some(*comp * -1);
4124}
4125
4126/* static */
4127template <TreeKind aKind>
4128Maybe<int32_t> nsContentUtils::ComparePointsWithIndices(
4129 const nsINode* aParent1, uint32_t aOffset1, const nsINode* aParent2,
4130 uint32_t aOffset2, NodeIndexCache* aIndexCache) {
4131 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"
, 4131); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent1" ")"
); do { MOZ_CrashSequence(__null, 4131); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4132 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"
, 4132); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent2" ")"
); do { MOZ_CrashSequence(__null, 4132); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4133
4134 if (aParent1 == aParent2) {
4135 return Some(aOffset1 < aOffset2 ? -1 : (aOffset1 > aOffset2 ? 1 : 0));
4136 }
4137
4138 const CommonAncestors<GetParentNodeForComparison<aKind>> commonAncestors(
4139 *aParent1, *aParent2);
4140 const nsINode* const closestCommonAncestor =
4141 commonAncestors.GetClosestCommonAncestor();
4142 if (MOZ_UNLIKELY(!closestCommonAncestor)(__builtin_expect(!!(!closestCommonAncestor), 0))) {
4143 return Nothing();
4144 }
4145
4146 const nsIContent* closestCommonAncestorChild1 = nsIContent::FromNodeOrNull(
4147 commonAncestors.GetClosestCommonAncestorChild1());
4148 const nsIContent* closestCommonAncestorChild2 = nsIContent::FromNodeOrNull(
4149 commonAncestors.GetClosestCommonAncestorChild2());
4150 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", 4150); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1 != closestCommonAncestorChild2"
")"); do { MOZ_CrashSequence(__null, 4150); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4151 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"
, 4152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 4152); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4152 !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"
, 4152); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 4152); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4153 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"
, 4154); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 4154); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4154 !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"
, 4154); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 4154); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4155 commonAncestors
4156 .template WarnIfClosestCommonAncestorChildrenAreNotInChildList<aKind>();
4157 if (closestCommonAncestorChild1 && closestCommonAncestorChild2) {
4158 return CompareClosestCommonAncestorChildren<
4159 TreeKindToCompareChildren<aKind>()>(
4160 *closestCommonAncestor, closestCommonAncestorChild1,
4161 closestCommonAncestorChild2, aIndexCache);
4162 }
4163
4164 if (closestCommonAncestorChild2) {
4165 // aParent1 is the common ancestor.
4166 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", 4167); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aParent1"
")"); do { MOZ_CrashSequence(__null, 4167); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4167 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", 4167); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aParent1"
")"); do { MOZ_CrashSequence(__null, 4167); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4168 if (aKind != TreeKind::DOM && ChildNodeIsInShadowDOMHostedByParent<aKind>(
4169 aParent1, closestCommonAncestorChild2)) {
4170 // Comparing a shadow host with its shadow root.
4171 // We consider:
4172 // [aParent1, 0] < closestCommonAncestorChild2 < [aParent1, 1]
4173 return aOffset1 > 0 ? Some(1) : Some(-1);
4174 }
4175
4176 // FIXME: bug 1946003 and bug 1946008.
4177 if (MOZ_UNLIKELY(closestCommonAncestorChild2->IsDocumentFragment())(__builtin_expect(!!(closestCommonAncestorChild2->IsDocumentFragment
()), 0))
) {
4178 // XXX Keep the odd traditional behavior for now.
4179 return Some(1);
4180 }
4181 // If the common ancestor is a shadow host, closestCommonAncestorChild2 must
4182 // be a child node of the host and we shouldn't handle the flattened tree.
4183 // Therefore, we can compare closestCommonAncestorChild2 and the child at
4184 // aBoundary1 can be compared within TreeKind::DOM tree.
4185 // NOTE: When aKind is TreeKind::FlatForSelection,
4186 // GetParentNodeForComparison returns the shadow host as the parent node
4187 // of a child node even if it's not assigned to any <slot>. Therefore, even
4188 // when we should return Nothing, we may return Some value for now.
4189 // Therefore, we need to relax this assertion for TreeKind::FlatForSelection
4190 // until fixing bug 2014622. And it's okay to compare the child nodes not a
4191 // part of flattened tree as in the DOM since anyway we return wrong value.
4192 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", 4195); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4195); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4193 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", 4195); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4195); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4194 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", 4195); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4195); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4195 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", 4195); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4195); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4196 const Maybe<int32_t> comp = nsContentUtils::CompareChildOffsetAndChildNode<
4197 TreeKindToCompareChildren<aKind>()>(*closestCommonAncestor, aOffset1,
4198 *closestCommonAncestorChild2,
4199 aIndexCache);
4200 if (NS_WARN_IF(comp.isNothing())NS_warn_if_impl(comp.isNothing(), "comp.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4200)
) {
4201 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", 4204); MOZ_PretendNoReturn
(); } } while (0)
4202 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", 4204); MOZ_PretendNoReturn
(); } } while (0)
4203 "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", 4204); MOZ_PretendNoReturn
(); } } while (0)
4204 "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", 4204); MOZ_PretendNoReturn
(); } } while (0)
;
4205 // XXX Keep the odd traditional behavior for now.
4206 return Some(1);
4207 }
4208 // If the child of the closest common ancestor is at aOffset1 of aParent1,
4209 // it means that aOffset2 of aParent2 refers a descendant of the child.
4210 // So, aOffset2 of aParent2 refers a descendant of aOffset1 of aParent1.
4211 if (!*comp) {
4212 return Some(-1);
4213 }
4214 return comp;
4215 }
4216
4217 // aParent2 is the common ancestor.
4218 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", 4218); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1" ")"); do { MOZ_CrashSequence
(__null, 4218); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4219 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", 4220); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aParent2"
")"); do { MOZ_CrashSequence(__null, 4220); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4220 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", 4220); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aParent2"
")"); do { MOZ_CrashSequence(__null, 4220); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4221 if (aKind != TreeKind::DOM && ChildNodeIsInShadowDOMHostedByParent<aKind>(
4222 aParent2, closestCommonAncestorChild1)) {
4223 // Comparing a shadow host with its shadow root.
4224 // We consider: [aParent2, 0] < closestCommonAncestorChild1 < [aParent2, 1]
4225 return aOffset2 > 0 ? Some(-1) : Some(1);
4226 }
4227
4228 // FIXME: bug 1946003 and bug 1946008.
4229 if (MOZ_UNLIKELY(closestCommonAncestorChild1->IsDocumentFragment())(__builtin_expect(!!(closestCommonAncestorChild1->IsDocumentFragment
()), 0))
) {
4230 // XXX Keep the odd traditional behavior for now.
4231 return Some(-1);
4232 }
4233 // If the common ancestor is a shadow host, closestCommonAncestorChild1 must
4234 // be a child node of the host and we shouldn't handle the flattened tree.
4235 // Therefore, we can compare closestCommonAncestorChild1 and the child at
4236 // aBoundary2 can be compared within TreeKind::DOM tree.
4237 // NOTE: When aKind is TreeKind::FlatForSelection,
4238 // GetParentNodeForComparison returns the shadow host as the parent node
4239 // of a child node even if it's not assigned to any <slot>. Therefore, even
4240 // when we should return Nothing, we may return Some value for now.
4241 // Therefore, we need to relax this assertion for TreeKind::FlatForSelection
4242 // until fixing bug 2014622. And it's okay to compare the child nodes not a
4243 // part of flattened tree as in the DOM since anyway we return wrong value.
4244 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", 4247); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4247); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4245 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", 4247); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4247); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4246 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", 4247); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4247); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4247 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", 4247); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4247); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4248 const Maybe<int32_t> comp = nsContentUtils::CompareChildNodeAndChildOffset<
4249 TreeKindToCompareChildren<aKind>()>(*closestCommonAncestor,
4250 *closestCommonAncestorChild1,
4251 aOffset2, aIndexCache);
4252 if (NS_WARN_IF(comp.isNothing())NS_warn_if_impl(comp.isNothing(), "comp.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4252)
) {
4253 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"
, 4255); MOZ_PretendNoReturn(); } } while (0)
4254 "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"
, 4255); MOZ_PretendNoReturn(); } } while (0)
4255 "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"
, 4255); MOZ_PretendNoReturn(); } } while (0)
;
4256 // XXX Keep the odd traditional behavior for now.
4257 return Some(-1);
4258 }
4259 // If the child of the closet common ancestor is at aOffset2 of aParent2, it
4260 // means that aOffset1 of aParent1 refers a descendant of the child.
4261 // So, aOffset1 of aParent1 refers a descendant of aOffset2 of aParent2.
4262 if (!*comp) {
4263 return Some(1);
4264 }
4265 return comp;
4266}
4267
4268/* static */
4269BrowserParent* nsContentUtils::GetCommonBrowserParentAncestor(
4270 BrowserParent* aBrowserParent1, BrowserParent* aBrowserParent2) {
4271 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", 4271); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aBrowserParent1" ")"); do { MOZ_CrashSequence
(__null, 4271); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4272 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", 4272); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aBrowserParent2" ")"); do { MOZ_CrashSequence
(__null, 4272); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4273 return CommonAncestors<GetParentBrowserParent>(*aBrowserParent1,
4274 *aBrowserParent2)
4275 .GetClosestCommonAncestor();
4276}
4277
4278/* static */
4279Element* nsContentUtils::GetTargetElement(Document* aDocument,
4280 const nsAString& aAnchorName) {
4281 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"
, 4281); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument" ")"
); do { MOZ_CrashSequence(__null, 4281); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4282
4283 if (aAnchorName.IsEmpty()) {
4284 return nullptr;
4285 }
4286 // 1. If there is an element in the document tree that has an ID equal to
4287 // fragment, then return the first such element in tree order.
4288 if (Element* el = aDocument->GetElementById(aAnchorName)) {
4289 return el;
4290 }
4291
4292 // 2. If there is an a element in the document tree that has a name
4293 // attribute whose value is equal to fragment, then return the first such
4294 // element in tree order.
4295 //
4296 // FIXME(emilio): Why the different code-paths for HTML and non-HTML docs?
4297 if (aDocument->IsHTMLDocument()) {
4298 RefPtr<NodeList> list = aDocument->GetElementsByName(aAnchorName);
4299 // Loop through the named nodes looking for the first anchor
4300 uint32_t length = list->Length();
4301 for (uint32_t i = 0; i < length; i++) {
4302 nsIContent* node = list->Item(i);
4303 if (node->IsHTMLElement(nsGkAtoms::a)) {
4304 return node->AsElement();
4305 }
4306 }
4307 } else {
4308 constexpr auto nameSpace = u"http://www.w3.org/1999/xhtml"_ns;
4309 // Get the list of anchor elements
4310 RefPtr<NodeList> list =
4311 aDocument->GetElementsByTagNameNS(nameSpace, u"a"_ns);
4312 // Loop through the anchors looking for the first one with the given name.
4313 for (uint32_t i = 0; true; i++) {
4314 nsIContent* node = list->Item(i);
4315 if (!node) { // End of list
4316 break;
4317 }
4318
4319 // Compare the name attribute
4320 if (node->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
4321 aAnchorName, eCaseMatters)) {
4322 return node->AsElement();
4323 }
4324 }
4325 }
4326
4327 // 3. Return null.
4328 return nullptr;
4329}
4330
4331/* static */
4332template <TreeKind aKind, typename PT1, typename RT1, typename PT2,
4333 typename RT2>
4334Maybe<int32_t> nsContentUtils::ComparePoints(
4335 const RangeBoundaryBase<PT1, RT1>& aBoundary1,
4336 const RangeBoundaryBase<PT2, RT2>& aBoundary2,
4337 NodeIndexCache* aIndexCache /* = nullptr */) {
4338 if (!aBoundary1.IsSet() || !aBoundary2.IsSet()) {
4339 return Nothing{};
4340 }
4341 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"
, 4341); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aBoundary1.GetTreeKind() == aBoundary2.GetTreeKind()"
")"); do { MOZ_CrashSequence(__null, 4341); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4342
4343 const auto kValidOrInvalidOffsets1 =
4344 RangeBoundaryBase<PT1, RT1>::OffsetFilter::kValidOrInvalidOffsets;
4345 const auto kValidOrInvalidOffsets2 =
4346 RangeBoundaryBase<PT2, RT2>::OffsetFilter::kValidOrInvalidOffsets;
4347
4348 // RangeBoundaryBase instances may be initialized only with a child node or an
4349 // offset in the container. If both instances have computed offset, we can
4350 // use ComparePointsWithIndices() which works with offsets.
4351 if (aBoundary1.HasOffset() && aBoundary2.HasOffset()) {
4352 return ComparePointsWithIndices<aKind>(
4353 aBoundary1.GetContainer(), *aBoundary1.Offset(kValidOrInvalidOffsets1),
4354 aBoundary2.GetContainer(), *aBoundary2.Offset(kValidOrInvalidOffsets2),
4355 aIndexCache);
4356 }
4357
4358 // Otherwise, i.e., at least one RangeBoundaryBase stores the child node.
4359 // In the most cases, RangeBoundaryBase has it, so, the worst scenario here
4360 // is, one of the boundaries comes from a StaticRange or is initialized with
4361 // offset and RangeBoundarySetBy::Offset. However, for making it faster in
4362 // the most cases, we should compare the child nodes without offsets if
4363 // possible.
4364
4365 // If we're comparing children in the same container, we don't need to compute
4366 // common ancestors. So, we can skip it and just compare the children.
4367 if (aBoundary1.GetContainer() == aBoundary2.GetContainer()) {
4368 const nsIContent* const child1 = aBoundary1.GetChildAtOffset();
4369 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", 4369); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!child1->IsShadowRoot()" ")"); do { MOZ_CrashSequence
(__null, 4369); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
4370 const nsIContent* const child2 = aBoundary2.GetChildAtOffset();
4371 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", 4371); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!child2->IsShadowRoot()" ")"); do { MOZ_CrashSequence
(__null, 4371); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
4372 // But aBoundary1 and aBoundary2 may be not updated for the latest DOM.
4373 // In such case, we need to return Nothing.
4374 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", 4375)
4375 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", 4375)
||
4376 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", 4377)
4377 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", 4377)
) [[unlikely]] {
4378 return Nothing{};
4379 }
4380 return CompareClosestCommonAncestorChildren<
4381 TreeKindToCompareChildren<aKind>()>(*aBoundary1.GetContainer(), child1,
4382 child2, aIndexCache);
4383 }
4384
4385 // Otherwise, we need to compare the common ancestor children which is the
4386 // most distant different inclusive ancestors of the containers. So, the
4387 // following implementation is similar to ComparePointsWithIndices(), but we
4388 // don't have offset, so, we cannot use offset when we compare the boundaries
4389 // whose one is a descendant of the other.
4390 const CommonAncestors<GetParentNodeForComparison<aKind>> commonAncestors(
4391 *aBoundary1.GetContainer(), *aBoundary2.GetContainer());
4392
4393 const nsINode* const closestCommonAncestor =
4394 commonAncestors.GetClosestCommonAncestor();
4395 if (MOZ_UNLIKELY(!closestCommonAncestor)(__builtin_expect(!!(!closestCommonAncestor), 0))) {
4396 return Nothing();
4397 }
4398 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", 4398); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "commonAncestors.GetClosestCommonAncestor()"
")"); do { MOZ_CrashSequence(__null, 4398); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4399
4400 const nsIContent* closestCommonAncestorChild1 = nsIContent::FromNodeOrNull(
4401 commonAncestors.GetClosestCommonAncestorChild1());
4402 const nsIContent* closestCommonAncestorChild2 = nsIContent::FromNodeOrNull(
4403 commonAncestors.GetClosestCommonAncestorChild2());
4404 commonAncestors
4405 .template WarnIfClosestCommonAncestorChildrenAreNotInChildList<aKind>();
4406 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", 4406); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1 != closestCommonAncestorChild2"
")"); do { MOZ_CrashSequence(__null, 4406); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4407 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"
, 4408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 4408); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4408 !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"
, 4408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild1()"
")"); do { MOZ_CrashSequence(__null, 4408); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4409 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"
, 4410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 4410); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4410 !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"
, 4410); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!commonAncestors.GetClosestCommonAncestorChild2()"
")"); do { MOZ_CrashSequence(__null, 4410); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4411 if (closestCommonAncestorChild1 && closestCommonAncestorChild2) {
4412 return CompareClosestCommonAncestorChildren<
4413 TreeKindToCompareChildren<aKind>()>(
4414 *closestCommonAncestor, closestCommonAncestorChild1,
4415 closestCommonAncestorChild2, aIndexCache);
4416 }
4417
4418 if (closestCommonAncestorChild2) {
4419 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", 4420); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aBoundary1.GetContainer()"
")"); do { MOZ_CrashSequence(__null, 4420); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4420 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", 4420); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild2) == aBoundary1.GetContainer()"
")"); do { MOZ_CrashSequence(__null, 4420); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4421 // FIXME: bug 1946003 and bug 1946008.
4422 if (MOZ_UNLIKELY(closestCommonAncestorChild2->IsDocumentFragment())(__builtin_expect(!!(closestCommonAncestorChild2->IsDocumentFragment
()), 0))
) {
4423 // XXX Keep the odd traditional behavior for now.
4424 return Some(1);
4425 }
4426 // If the common ancestor is a shadow host, closestCommonAncestorChild2 must
4427 // be a child node of the host and we shouldn't handle the flattened tree.
4428 // Therefore, we can compare closestCommonAncestorChild2 and the child at
4429 // aBoundary1 can be compared within TreeKind::DOM tree.
4430 // NOTE: When aKind is TreeKind::FlatForSelection,
4431 // GetParentNodeForComparison returns the shadow host as the parent node
4432 // of a child node even if it's not assigned to any <slot>. Therefore, even
4433 // when we should return Nothing, we may return Some value for now.
4434 // Therefore, we need to relax this assertion for TreeKind::FlatForSelection
4435 // until fixing bug 2014622. And it's okay to compare the child nodes not a
4436 // part of flattened tree as in the DOM since anyway we return wrong value.
4437 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", 4440); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4440); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4438 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", 4440); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4440); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4439 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", 4440); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4440); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4440 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", 4440); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild2->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4440); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4441 const Maybe<int32_t> comp = nsContentUtils::CompareChildNodes<
4442 TreeKindToCompareChildren<TreeKindToCompareChildren<aKind>()>()>(
4443 *closestCommonAncestor, aBoundary1.GetChildAtOffset(),
4444 closestCommonAncestorChild2, aIndexCache);
4445 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", 4447); MOZ_PretendNoReturn
(); } } while (0)
4446 "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", 4447); MOZ_PretendNoReturn
(); } } while (0)
4447 "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", 4447); MOZ_PretendNoReturn
(); } } while (0)
;
4448 if (NS_WARN_IF(comp.isNothing())NS_warn_if_impl(comp.isNothing(), "comp.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4448)
) {
4449 // XXX Keep the odd traditional behavior for now.
4450 return Some(1);
4451 }
4452 // If the child of the closest common ancestor is at aBoundary1, it means
4453 // that aBoundary2 refers a descendant of the child. So, aBoundary2 refers a
4454 // descendant of aBoundary1.
4455 if (!*comp) {
4456 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", 4461); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4461); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4457 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", 4461); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4461); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4458 *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", 4461); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4461); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4459 ->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", 4461); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4461); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4460 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", 4461); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4461); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4461 *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", 4461); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) == *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4461); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4462 return Some(-1);
4463 }
4464 // ComputeIndexInParentNode() is the index in the regular child list, which
4465 // native anonymous content is not part of. CompareChildNodes already
4466 // ordered NAC via GetIndexInParent, so skip the regular-index sanity checks
4467 // for it.
4468 const DebugOnly<bool> child2IsNAC =
4469 closestCommonAncestorChild2->IsRootOfNativeAnonymousSubtree();
4470 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", 4475); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
")"); do { MOZ_CrashSequence(__null, 4475); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4471 !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", 4475); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
")"); do { MOZ_CrashSequence(__null, 4475); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4472 *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", 4475); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
")"); do { MOZ_CrashSequence(__null, 4475); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4473 *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", 4475); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
")"); do { MOZ_CrashSequence(__null, 4475); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4474 ->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", 4475); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
")"); do { MOZ_CrashSequence(__null, 4475); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4475 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", 4475); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary1.Offset(kValidOrInvalidOffsets1) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2)"
")"); do { MOZ_CrashSequence(__null, 4475); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4476 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", 4481); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4481); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4477 !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", 4481); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4481); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4478 *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", 4481); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4481); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4479 ->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", 4481); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4481); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4480 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", 4481); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4481); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4481 *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", 4481); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild2) < *aBoundary1.Offset(kValidOrInvalidOffsets1)"
")"); do { MOZ_CrashSequence(__null, 4481); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4482 return comp;
4483 }
4484
4485 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", 4485); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1" ")"); do { MOZ_CrashSequence
(__null, 4485); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4486 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", 4487); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aBoundary2.GetContainer()"
")"); do { MOZ_CrashSequence(__null, 4487); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4487 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", 4487); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "GetParentNodeForComparison<aKind>::Get( closestCommonAncestorChild1) == aBoundary2.GetContainer()"
")"); do { MOZ_CrashSequence(__null, 4487); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4488 // FIXME: bug 1946003 and bug 1946008.
4489 if (MOZ_UNLIKELY(closestCommonAncestorChild1->IsDocumentFragment())(__builtin_expect(!!(closestCommonAncestorChild1->IsDocumentFragment
()), 0))
) {
4490 // XXX Keep the odd traditional behavior for now.
4491 return Some(-1);
4492 }
4493 // If the common ancestor is a shadow host, closestCommonAncestorChild1 must
4494 // be a child node of the host and we shouldn't handle the flattened tree.
4495 // Therefore, we can compare closestCommonAncestorChild1 and the child at
4496 // aBoundary2 can be compared within TreeKind::DOM tree.
4497 // NOTE: When aKind is TreeKind::FlatForSelection,
4498 // GetParentNodeForComparison returns the shadow host as the parent node
4499 // of a child node even if it's not assigned to any <slot>. Therefore, even
4500 // when we should return Nothing, we may return Some value for now.
4501 // Therefore, we need to relax this assertion for TreeKind::FlatForSelection
4502 // until fixing bug 2014622. And it's okay to compare the child nodes not a
4503 // part of flattened tree as in the DOM since anyway we return wrong value.
4504 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", 4507); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4507); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4505 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", 4507); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4507); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4506 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", 4507); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4507); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4507 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", 4507); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "closestCommonAncestorChild1->GetParentNode() == closestCommonAncestor"
")"); do { MOZ_CrashSequence(__null, 4507); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4508 const Maybe<int32_t> comp =
4509 nsContentUtils::CompareChildNodes<TreeKindToCompareChildren<aKind>()>(
4510 *closestCommonAncestor, closestCommonAncestorChild1,
4511 aBoundary2.GetChildAtOffset(), aIndexCache);
4512 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", 4514); MOZ_PretendNoReturn
(); } } while (0)
4513 "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", 4514); MOZ_PretendNoReturn
(); } } while (0)
4514 "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", 4514); MOZ_PretendNoReturn
(); } } while (0)
;
4515 if (NS_WARN_IF(comp.isNothing())NS_warn_if_impl(comp.isNothing(), "comp.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 4515)
) {
4516 // XXX Keep the odd traditional behavior for now.
4517 return Some(-1);
4518 }
4519 // If the child of the closet common ancestor is at aBoundary2, it means that
4520 // aBoundary1 refers a descendant of the child. So, aBoundary1 refers a
4521 // descendant of aBoundary2.
4522 if (!*comp) {
4523 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", 4527); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4527); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4524 *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", 4527); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4527); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4525 ->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", 4527); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4527); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4526 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", 4527); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4527); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4527 *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", 4527); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) == *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4527); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4528 return Some(1);
4529 }
4530 // ComputeIndexInParentNode() is the index in the regular child list, which
4531 // native anonymous content is not part of. CompareChildNodes already ordered
4532 // NAC via GetIndexInParent, so skip the regular-index sanity checks for it.
4533 const DebugOnly<bool> child1IsNAC =
4534 closestCommonAncestorChild1->IsRootOfNativeAnonymousSubtree();
4535 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", 4540); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4540); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4536 !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", 4540); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4540); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4537 *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", 4540); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4540); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4538 ->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", 4540); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4540); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4539 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", 4540); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4540); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4540 *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", 4540); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1) < *aBoundary2.Offset(kValidOrInvalidOffsets2)"
")"); do { MOZ_CrashSequence(__null, 4540); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4541 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", 4546); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
")"); do { MOZ_CrashSequence(__null, 4546); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4542 !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", 4546); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
")"); do { MOZ_CrashSequence(__null, 4546); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4543 *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", 4546); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
")"); do { MOZ_CrashSequence(__null, 4546); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4544 *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", 4546); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
")"); do { MOZ_CrashSequence(__null, 4546); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4545 ->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", 4546); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
")"); do { MOZ_CrashSequence(__null, 4546); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
4546 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", 4546); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "*aBoundary2.Offset(kValidOrInvalidOffsets2) < *closestCommonAncestor ->ComputeIndexOf<TreeKindToCompareChildren<aKind>()>( closestCommonAncestorChild1)"
")"); do { MOZ_CrashSequence(__null, 4546); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4547 return comp;
4548}
4549
4550inline bool IsCharInSet(const char* aSet, const char16_t aChar) {
4551 char16_t ch;
4552 while ((ch = *aSet)) {
4553 if (aChar == char16_t(ch)) {
4554 return true;
4555 }
4556 ++aSet;
4557 }
4558 return false;
4559}
4560
4561/**
4562 * This method strips leading/trailing chars, in given set, from string.
4563 */
4564
4565// static
4566const nsDependentSubstring nsContentUtils::TrimCharsInSet(
4567 const char* aSet, const nsAString& aValue) {
4568 nsAString::const_iterator valueCurrent, valueEnd;
4569
4570 aValue.BeginReading(valueCurrent);
4571 aValue.EndReading(valueEnd);
4572
4573 // Skip characters in the beginning
4574 while (valueCurrent != valueEnd) {
4575 if (!IsCharInSet(aSet, *valueCurrent)) {
4576 break;
4577 }
4578 ++valueCurrent;
4579 }
4580
4581 if (valueCurrent != valueEnd) {
4582 for (;;) {
4583 --valueEnd;
4584 if (!IsCharInSet(aSet, *valueEnd)) {
4585 break;
4586 }
4587 }
4588 ++valueEnd; // Step beyond the last character we want in the value.
4589 }
4590
4591 // valueEnd should point to the char after the last to copy
4592 return Substring(valueCurrent, valueEnd);
4593}
4594
4595/**
4596 * This method strips leading and trailing whitespace from a string.
4597 */
4598
4599// static
4600template <bool IsWhitespace(char16_t)>
4601const nsDependentSubstring nsContentUtils::TrimWhitespace(const nsAString& aStr,
4602 bool aTrimTrailing) {
4603 nsAString::const_iterator start, end;
4604
4605 aStr.BeginReading(start);
4606 aStr.EndReading(end);
4607
4608 // Skip whitespace characters in the beginning
4609 while (start != end && IsWhitespace(*start)) {
4610 ++start;
4611 }
4612
4613 if (aTrimTrailing) {
4614 // Skip whitespace characters in the end.
4615 while (end != start) {
4616 --end;
4617
4618 if (!IsWhitespace(*end)) {
4619 // Step back to the last non-whitespace character.
4620 ++end;
4621
4622 break;
4623 }
4624 }
4625 }
4626
4627 // Return a substring for the string w/o leading and/or trailing
4628 // whitespace
4629
4630 return Substring(start, end);
4631}
4632
4633// Declaring the templates we are going to use avoid linking issues without
4634// inlining the method. Considering there is not so much spaces checking
4635// methods we can consider this to be better than inlining.
4636template const nsDependentSubstring
4637nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(const nsAString&, bool);
4638template const nsDependentSubstring nsContentUtils::TrimWhitespace<
4639 nsContentUtils::IsHTMLWhitespace>(const nsAString&, bool);
4640template const nsDependentSubstring nsContentUtils::TrimWhitespace<
4641 nsContentUtils::IsHTMLWhitespaceOrNBSP>(const nsAString&, bool);
4642
4643static inline void KeyAppendSep(nsACString& aKey) {
4644 if (!aKey.IsEmpty()) {
4645 aKey.Append('>');
4646 }
4647}
4648
4649static inline void KeyAppendString(const nsAString& aString, nsACString& aKey) {
4650 KeyAppendSep(aKey);
4651
4652 // Could escape separator here if collisions happen. > is not a legal char
4653 // for a name or type attribute, so we should be safe avoiding that extra
4654 // work.
4655
4656 AppendUTF16toUTF8(aString, aKey);
4657}
4658
4659static inline void KeyAppendString(const nsACString& aString,
4660 nsACString& aKey) {
4661 KeyAppendSep(aKey);
4662
4663 // Could escape separator here if collisions happen. > is not a legal char
4664 // for a name or type attribute, so we should be safe avoiding that extra
4665 // work.
4666
4667 aKey.Append(aString);
4668}
4669
4670static inline void KeyAppendInt(int32_t aInt, nsACString& aKey) {
4671 KeyAppendSep(aKey);
4672
4673 aKey.AppendInt(aInt);
4674}
4675
4676static inline bool IsAutocompleteOff(const nsIContent* aContent) {
4677 return aContent->IsElement() &&
4678 aContent->AsElement()->AttrValueIs(kNameSpaceID_None,
4679 nsGkAtoms::autocomplete, u"off"_ns,
4680 eIgnoreCase);
4681}
4682
4683/*static*/
4684void nsContentUtils::GenerateStateKey(nsIContent* aContent, Document* aDocument,
4685 nsACString& aKey) {
4686 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"
, 4686); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { MOZ_CrashSequence(__null, 4686); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4687
4688 aKey.Truncate();
4689
4690 uint32_t partID = aDocument ? aDocument->GetPartID() : 0;
4691
4692 // Don't capture state for anonymous content
4693 if (aContent->IsInNativeAnonymousSubtree()) {
4694 return;
4695 }
4696
4697 if (IsAutocompleteOff(aContent)) {
4698 return;
4699 }
4700
4701 RefPtr<Document> doc = aContent->GetUncomposedDoc();
4702
4703 KeyAppendInt(partID, aKey); // first append a partID
4704 bool generatedUniqueKey = false;
4705
4706 if (doc && doc->IsHTMLOrXHTML()) {
4707 nsHTMLDocument* htmlDoc = doc->AsHTMLDocument();
4708
4709 // If we have a form control and can calculate form information, use that
4710 // as the key - it is more reliable than just recording position in the
4711 // DOM.
4712 // XXXbz Is it, really? We have bugs on this, I think...
4713 // Important to have a unique key, and tag/type/name may not be.
4714 //
4715 // The format of the key depends on whether the control has a form,
4716 // and whether the element was parser inserted:
4717 //
4718 // [Has Form, Parser Inserted]:
4719 // fp>type>FormNum>IndOfControlInForm>FormName>name
4720 //
4721 // [No Form, Parser Inserted]:
4722 // dp>type>ControlNum>name
4723 //
4724 // [Has Form, Not Parser Inserted]:
4725 // fn>type>IndOfFormInDoc>IndOfControlInForm>FormName>name
4726 //
4727 // [No Form, Not Parser Inserted]:
4728 // dn>type>IndOfControlInDoc>name
4729 //
4730 // XXX We don't need to use index if name is there
4731 // XXXbz We don't? Why not? I don't follow.
4732 //
4733 if (const auto* control = nsIFormControl::FromNode(aContent)) {
4734 // Get the control number if this was a parser inserted element from the
4735 // network.
4736 int32_t controlNumber =
4737 control->GetParserInsertedControlNumberForStateKey();
4738 bool parserInserted = controlNumber != -1;
4739
4740 RefPtr<ContentList> htmlForms;
4741 RefPtr<ContentList> htmlFormControls;
4742 if (!parserInserted) {
4743 // Getting these lists is expensive, as we need to keep them up to date
4744 // as the document loads, so we avoid it if we don't need them.
4745 htmlDoc->GetFormsAndFormControls(getter_AddRefs(htmlForms),
4746 getter_AddRefs(htmlFormControls));
4747 }
4748
4749 // Append the control type
4750 KeyAppendInt(int32_t(control->ControlType()), aKey);
4751
4752 // If in a form, add form name / index of form / index in form
4753 HTMLFormElement* formElement = control->GetFormInternal();
4754 if (formElement) {
4755 if (IsAutocompleteOff(formElement)) {
4756 aKey.Truncate();
4757 return;
4758 }
4759
4760 // Append the form number, if this is a parser inserted control, or
4761 // the index of the form in the document otherwise.
4762 bool appendedForm = false;
4763 if (parserInserted) {
4764 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", 4766
); 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, 4766); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4765 "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", 4766
); 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, 4766); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4766 "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", 4766
); 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, 4766); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4767 KeyAppendString("fp"_ns, aKey);
4768 KeyAppendInt(formElement->GetFormNumberForStateKey(), aKey);
4769 appendedForm = true;
4770 } else {
4771 KeyAppendString("fn"_ns, aKey);
4772 int32_t index = htmlForms->IndexOf(formElement, false);
4773 if (index <= -1) {
4774 //
4775 // XXX HACK this uses some state that was dumped into the document
4776 // specifically to fix bug 138892. What we are trying to do is
4777 // *guess* which form this control's state is found in, with the
4778 // highly likely guess that the highest form parsed so far is the
4779 // one. This code should not be on trunk, only branch.
4780 //
4781 index = htmlDoc->GetNumFormsSynchronous() - 1;
4782 }
4783 if (index > -1) {
4784 KeyAppendInt(index, aKey);
4785 appendedForm = true;
4786 }
4787 }
4788
4789 if (appendedForm) {
4790 // Append the index of the control in the form
4791 int32_t index = formElement->IndexOfContent(aContent);
4792
4793 if (index > -1) {
4794 KeyAppendInt(index, aKey);
4795 generatedUniqueKey = true;
4796 }
4797 }
4798
4799 // Append the form name
4800 nsAutoString formName;
4801 formElement->GetAttr(nsGkAtoms::name, formName);
4802 KeyAppendString(formName, aKey);
4803 } else {
4804 // Not in a form. Append the control number, if this is a parser
4805 // inserted control, or the index of the control in the document
4806 // otherwise.
4807 if (parserInserted) {
4808 KeyAppendString("dp"_ns, aKey);
4809 KeyAppendInt(control->GetParserInsertedControlNumberForStateKey(),
4810 aKey);
4811 generatedUniqueKey = true;
4812 } else {
4813 KeyAppendString("dn"_ns, aKey);
4814 int32_t index = htmlFormControls->IndexOf(aContent, true);
4815 if (index > -1) {
4816 KeyAppendInt(index, aKey);
4817 generatedUniqueKey = true;
4818 }
4819 }
4820
4821 // Append the control name
4822 nsAutoString name;
4823 aContent->AsElement()->GetAttr(nsGkAtoms::name, name);
4824 KeyAppendString(name, aKey);
4825 }
4826 }
4827 }
4828
4829 if (!generatedUniqueKey) {
4830 // Either we didn't have a form control or we aren't in an HTML document so
4831 // we can't figure out form info. Append the tag name if it's an element
4832 // to avoid restoring state for one type of element on another type.
4833 if (aContent->IsElement()) {
4834 KeyAppendString(nsDependentAtomString(aContent->NodeInfo()->NameAtom()),
4835 aKey);
4836 } else {
4837 // Append a character that is not "d" or "f" to disambiguate from
4838 // the case when we were a form control in an HTML document.
4839 KeyAppendString("o"_ns, aKey);
4840 }
4841
4842 // Now start at aContent and append the indices of it and all its ancestors
4843 // in their containers. That should at least pin down its position in the
4844 // DOM...
4845 nsINode* parent = aContent->GetParentNode();
4846 nsINode* content = aContent;
4847 while (parent) {
4848 if (content->IsShadowRoot()) {
4849 KeyAppendString("s"_ns, aKey);
4850 } else {
4851 KeyAppendInt(parent->ComputeIndexOf_Deprecated(content), aKey);
4852 }
4853 content = parent;
4854 parent = content->GetParentOrShadowHostNode();
4855 }
4856 }
4857}
4858
4859// static
4860nsIPrincipal* nsContentUtils::SubjectPrincipal(JSContext* aCx) {
4861 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", 4861); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 4861); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4862
4863 // As opposed to SubjectPrincipal(), we do in fact assume that
4864 // we're in a realm here; anyone who calls this function in
4865 // situations where that's not the case is doing it wrong.
4866 JS::Realm* realm = js::GetContextRealm(aCx);
4867 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"
, 4867); AnnotateMozCrashReason("MOZ_ASSERT" "(" "realm" ")")
; do { MOZ_CrashSequence(__null, 4867); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4868
4869 JSPrincipals* principals = JS::GetRealmPrincipals(realm);
4870 return nsJSPrincipals::get(principals);
4871}
4872
4873// static
4874nsIPrincipal* nsContentUtils::SubjectPrincipal() {
4875 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", 4875); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInitialized()" ")"); do { MOZ_CrashSequence
(__null, 4875); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4876 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", 4876); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 4876); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4877 JSContext* cx = GetCurrentJSContext();
4878 if (!cx) {
4879 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"
, 4881); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden" ")"); do { MOZ_CrashSequence(__null, 4881); __attribute__
((nomerge)) ::abort(); } while (false); } while (false)
4880 "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"
, 4881); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden" ")"); do { MOZ_CrashSequence(__null, 4881); __attribute__
((nomerge)) ::abort(); } while (false); } while (false)
4881 "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"
, 4881); AnnotateMozCrashReason("MOZ_CRASH(" "Accessing the Subject Principal without an AutoJSAPI on the stack is "
"forbidden" ")"); do { MOZ_CrashSequence(__null, 4881); __attribute__
((nomerge)) ::abort(); } while (false); } while (false)
;
4882 }
4883
4884 JS::Realm* realm = js::GetContextRealm(cx);
4885
4886 // When an AutoJSAPI is instantiated, we are in a null realm until the
4887 // first JSAutoRealm, which is kind of a purgatory as far as permissions
4888 // go. It would be nice to just hard-abort if somebody does a security check
4889 // in this purgatory zone, but that would be too fragile, since it could be
4890 // triggered by random IsCallerChrome() checks 20-levels deep.
4891 //
4892 // So we want to return _something_ here - and definitely not the System
4893 // Principal, since that would make an AutoJSAPI a very dangerous thing to
4894 // instantiate.
4895 //
4896 // The natural thing to return is a null principal. Ideally, we'd return a
4897 // different null principal each time, to avoid any unexpected interactions
4898 // when the principal accidentally gets inherited somewhere. But
4899 // SubjectPrincipal doesn't return strong references, so there's no way to
4900 // sanely manage the lifetime of multiple null principals.
4901 //
4902 // So we use a singleton null principal. To avoid it being accidentally
4903 // inherited and becoming a "real" subject or object principal, we do a
4904 // release-mode assert during realm creation against using this principal on
4905 // an actual global.
4906 if (!realm) {
4907 return sNullSubjectPrincipal;
4908 }
4909
4910 return SubjectPrincipal(cx);
4911}
4912
4913// static
4914nsIPrincipal* nsContentUtils::ObjectPrincipal(JSObject* aObj) {
4915#ifdef DEBUG1
4916 JS::AssertObjectBelongsToCurrentThread(aObj);
4917#endif
4918
4919 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"
, 4919); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!js::IsCrossCompartmentWrapper(aObj)"
")"); do { MOZ_CrashSequence(__null, 4919); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4920
4921 JS::Realm* realm = js::GetNonCCWObjectRealm(aObj);
4922 JSPrincipals* principals = JS::GetRealmPrincipals(realm);
4923 return nsJSPrincipals::get(principals);
4924}
4925
4926// static
4927nsresult nsContentUtils::NewURIWithDocumentCharset(nsIURI** aResult,
4928 const nsAString& aSpec,
4929 Document* aDocument,
4930 nsIURI* aBaseURI) {
4931 if (aDocument) {
4932 return NS_NewURI(aResult, aSpec, aDocument->GetDocumentCharacterSet(),
4933 aBaseURI);
4934 }
4935 return NS_NewURI(aResult, aSpec, nullptr, aBaseURI);
4936}
4937
4938// static
4939bool nsContentUtils::ContainsChar(nsAtom* aAtom, char aChar) {
4940 const uint32_t len = aAtom->GetLength();
4941 if (!len) {
4942 return false;
4943 }
4944 const char16_t* name = aAtom->GetUTF16String();
4945 uint32_t i = 0;
4946 while (i < len) {
4947 if (name[i] == aChar) {
4948 return true;
4949 }
4950 i++;
4951 }
4952 return false;
4953}
4954
4955// static
4956bool nsContentUtils::IsNameWithDash(nsAtom* aName) {
4957 // A valid custom element name is a sequence of characters name which
4958 // must match the PotentialCustomElementName production:
4959 // PotentialCustomElementName ::= [a-z] (PCENChar)* '-' (PCENChar)*
4960 const char16_t* name = aName->GetUTF16String();
4961 uint32_t len = aName->GetLength();
4962 bool hasDash = false;
4963
4964 // A string name is a valid custom element name if all of the following are
4965 // true:
4966
4967 // name's 0th code point is an ASCII lower alpha;
4968 if (!len || name[0] < 'a' || name[0] > 'z') {
4969 return false;
4970 }
4971
4972 uint32_t i = 1;
4973 while (i < len) {
4974 // name does not contain any ASCII upper alphas
4975 if (name[i] >= 'A' && name[i] <= 'Z') {
4976 return false;
4977 }
4978
4979 // name is a valid element local name;
4980 //
4981 // // https://dom.spec.whatwg.org/#valid-element-local-name
4982 // Step 2.1.
4983 // If name contains ASCII whitespace, U+0000 NULL, U+002F (/), or U+003E
4984 // (>), then return false.
4985 //
4986 // ASCII whitespace is U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, or
4987 // U+0020 SPACE.
4988 if (name[i] == 0x0000 || // null
4989 name[i] == 0x0009 || // tab
4990 name[i] == 0x000A || // newline
4991 name[i] == 0x000C || // form feed
4992 name[i] == 0x000D || // carriage return
4993 name[i] == 0x0020 || // space
4994 name[i] == 0x002F || // /
4995 name[i] == 0x003E) { // >
4996 return false;
4997 }
4998
4999 if (name[i] == '-') {
5000 hasDash = true;
5001 }
5002
5003 i++;
5004 }
5005 return hasDash;
5006}
5007
5008// static
5009bool nsContentUtils::IsCustomElementName(nsAtom* aName, uint32_t aNameSpaceID) {
5010 // Allow non-dashed names in XUL for XBL to Custom Element migrations.
5011 if (aNameSpaceID == kNameSpaceID_XUL8) {
5012 return true;
5013 }
5014
5015 bool hasDash = IsNameWithDash(aName);
5016 if (!hasDash) {
5017 return false;
5018 }
5019
5020 // The custom element name must not be one of the following values:
5021 // annotation-xml
5022 // color-profile
5023 // font-face
5024 // font-face-src
5025 // font-face-uri
5026 // font-face-format
5027 // font-face-name
5028 // missing-glyph
5029 return aName != nsGkAtoms::annotation_xml &&
5030 aName != nsGkAtoms::color_profile && aName != nsGkAtoms::font_face &&
5031 aName != nsGkAtoms::font_face_src &&
5032 aName != nsGkAtoms::font_face_uri &&
5033 aName != nsGkAtoms::font_face_format &&
5034 aName != nsGkAtoms::font_face_name && aName != nsGkAtoms::missingGlyph;
5035}
5036
5037bool nsContentUtils::IsValidShadowHostName(nsAtom* aName,
5038 uint32_t aNameSpaceID) {
5039 return IsCustomElementName(aName, aNameSpaceID) ||
5040 aName == nsGkAtoms::article || aName == nsGkAtoms::aside ||
5041 aName == nsGkAtoms::blockquote || aName == nsGkAtoms::body ||
5042 aName == nsGkAtoms::div || aName == nsGkAtoms::footer ||
5043 aName == nsGkAtoms::h1 || aName == nsGkAtoms::h2 ||
5044 aName == nsGkAtoms::h3 || aName == nsGkAtoms::h4 ||
5045 aName == nsGkAtoms::h5 || aName == nsGkAtoms::h6 ||
5046 aName == nsGkAtoms::header || aName == nsGkAtoms::main ||
5047 aName == nsGkAtoms::nav || aName == nsGkAtoms::p ||
5048 aName == nsGkAtoms::section || aName == nsGkAtoms::span;
5049}
5050
5051// static
5052nsresult nsContentUtils::CheckQName(const nsAString& aQualifiedName,
5053 bool aNamespaceAware,
5054 const char16_t** aColon) {
5055 const char* colon = nullptr;
5056 const char16_t* begin = aQualifiedName.BeginReading();
5057 const char16_t* end = aQualifiedName.EndReading();
5058
5059 int result = MOZ_XMLCheckQName(reinterpret_cast<const char*>(begin),
5060 reinterpret_cast<const char*>(end),
5061 aNamespaceAware, &colon);
5062
5063 if (!result) {
5064 if (aColon) {
5065 *aColon = reinterpret_cast<const char16_t*>(colon);
5066 }
5067
5068 return NS_OK;
5069 }
5070
5071 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5072}
5073
5074static inline bool IsValidRestrictedContinuation(char16_t c) {
5075 return mozilla::IsAsciiAlpha(c) || mozilla::IsAsciiDigit(c) || c == '-' ||
5076 c == '.' || c == ':' || c == '_' || c >= 0x80;
5077}
5078
5079// static
5080// https://dom.spec.whatwg.org/#valid-element-local-name
5081// Two paths:
5082// 1. Starts with [A-Za-z]: continuation can be any char except
5083// null/whitespace/>/'/'
5084// 2. Starts with [:_>=0x80]: continuation must be [A-Za-z0-9-.:_>=0x80]
5085bool nsContentUtils::IsValidElementLocalName(const nsAString& aName) {
5086 if (aName.IsEmpty()) {
5087 return false;
5088 }
5089
5090 const char16_t* ptr = aName.BeginReading();
5091 const char16_t* end = aName.EndReading();
5092 char16_t first = *ptr;
5093
5094 if (mozilla::IsAsciiAlpha(first)) {
5095 // Path 1: ASCII alpha start - any continuation except forbidden chars.
5096 for (++ptr; ptr < end; ++ptr) {
5097 char16_t c = *ptr;
5098 if (c == 0 || IsHTMLWhitespace(c) || c == '/' || c == '>') {
5099 return false;
5100 }
5101 }
5102 return true;
5103 }
5104
5105 if (first == ':' || first == '_' || first >= 0x80) {
5106 // Path 2: Colon, underscore, or non-ASCII start - restricted continuation.
5107 for (++ptr; ptr < end; ++ptr) {
5108 if (!IsValidRestrictedContinuation(*ptr)) {
5109 return false;
5110 }
5111 }
5112 return true;
5113 }
5114
5115 // Starting with anything else (e.g., digits, other ASCII) is invalid.
5116 return false;
5117}
5118
5119// static
5120// https://dom.spec.whatwg.org/#valid-attribute-local-name
5121bool nsContentUtils::IsValidAttributeLocalName(const nsAString& aName) {
5122 if (aName.IsEmpty()) {
5123 return false;
5124 }
5125 for (const char16_t* ptr = aName.BeginReading(); ptr < aName.EndReading();
5126 ptr++) {
5127 char16_t c = *ptr;
5128 if (c == 0 || IsHTMLWhitespace(c) || c == '>' || c == '/' || c == '=') {
5129 return false;
5130 }
5131 }
5132 return true;
5133}
5134
5135// static
5136// https://dom.spec.whatwg.org/#valid-namespace-prefix
5137bool nsContentUtils::IsValidNamespacePrefix(const nsAString& aPrefix) {
5138 // Empty prefix is valid (means no prefix).
5139 if (aPrefix.IsEmpty()) {
5140 return true;
5141 }
5142 for (const char16_t* ptr = aPrefix.BeginReading(); ptr < aPrefix.EndReading();
5143 ptr++) {
5144 char16_t c = *ptr;
5145 if (c == 0 || IsHTMLWhitespace(c) || c == '/' || c == '>') {
5146 return false;
5147 }
5148 }
5149 return true;
5150}
5151
5152// static
5153// https://dom.spec.whatwg.org/#valid-doctype-name
5154bool nsContentUtils::IsValidDoctypeName(const nsAString& aName) {
5155 // Empty doctype name is valid per spec (it just can't contain bad chars).
5156 for (const char16_t* ptr = aName.BeginReading(); ptr < aName.EndReading();
5157 ptr++) {
5158 char16_t c = *ptr;
5159 if (c == 0 || IsHTMLWhitespace(c) || c == '>') {
5160 return false;
5161 }
5162 }
5163 return true;
5164}
5165
5166// static
5167// https://dom.spec.whatwg.org/#validate-and-extract
5168// This implements only the validation and parsing portion of the algorithm.
5169// Namespace resolution (steps involving namespace lookups) is handled by
5170// callers.
5171nsresult nsContentUtils::ParseQualifiedNameRelaxed(
5172 const nsAString& aQualifiedName, uint16_t aNodeType,
5173 const char16_t** aColon, const char16_t** aLocalNameEnd) {
5174 if (aColon) {
5175 *aColon = nullptr;
5176 }
5177 if (aLocalNameEnd) {
5178 *aLocalNameEnd = nullptr;
5179 }
5180
5181 if (aQualifiedName.IsEmpty()) {
5182 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5183 }
5184
5185 const char16_t* begin = aQualifiedName.BeginReading();
5186 const char16_t* end = aQualifiedName.EndReading();
5187 const char16_t* firstColon = nullptr;
5188
5189 for (const char16_t* ptr = begin; ptr < end; ptr++) {
5190 if (*ptr == ':') {
5191 firstColon = ptr;
5192 break;
5193 }
5194 }
5195
5196 if (firstColon) {
5197 nsDependentSubstring prefix(begin, firstColon);
5198
5199 if (prefix.IsEmpty()) {
5200 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5201 }
5202
5203 if (!IsValidNamespacePrefix(prefix)) {
5204 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5205 }
5206
5207 // Local name is everything after the first colon.
5208 nsDependentSubstring localName(firstColon + 1, end);
5209
5210 // Local name must not be empty.
5211 if (localName.IsEmpty()) {
5212 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5213 }
5214
5215 // Validate local name based on node type.
5216 if (aNodeType == nsINode::ATTRIBUTE_NODE) {
5217 if (!IsValidAttributeLocalName(localName)) {
5218 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5219 }
5220 } else {
5221 if (!IsValidElementLocalName(localName)) {
5222 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5223 }
5224 }
5225
5226 if (aColon) {
5227 *aColon = firstColon;
5228 }
5229 if (aLocalNameEnd) {
5230 *aLocalNameEnd = end;
5231 }
5232 } else {
5233 // No colon, the whole string is the local name.
5234 if (aNodeType == nsINode::ATTRIBUTE_NODE) {
5235 if (!IsValidAttributeLocalName(aQualifiedName)) {
5236 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5237 }
5238 } else {
5239 if (!IsValidElementLocalName(aQualifiedName)) {
5240 return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
5241 }
5242 }
5243 }
5244
5245 return NS_OK;
5246}
5247
5248// static
5249nsresult nsContentUtils::SplitQName(const nsIContent* aNamespaceResolver,
5250 const nsString& aQName, int32_t* aNamespace,
5251 nsAtom** aLocalName) {
5252 const char16_t* colon;
5253 nsresult rv = nsContentUtils::CheckQName(aQName, true, &colon);
5254 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"
, 5254); return rv; } } while (false)
;
5255
5256 if (colon) {
5257 const char16_t* end;
5258 aQName.EndReading(end);
5259 nsAutoString nameSpace;
5260 rv = aNamespaceResolver->LookupNamespaceURIInternal(
5261 Substring(aQName.get(), colon), nameSpace);
5262 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"
, 5262); return rv; } } while (false)
;
5263
5264 *aNamespace = nsNameSpaceManager::GetInstance()->GetNameSpaceID(
5265 nameSpace, nsContentUtils::IsChromeDoc(aNamespaceResolver->OwnerDoc()));
5266 if (*aNamespace == kNameSpaceID_Unknown-1) return NS_ERROR_FAILURE;
5267
5268 *aLocalName = NS_AtomizeMainThread(Substring(colon + 1, end)).take();
5269 } else {
5270 *aNamespace = kNameSpaceID_None;
5271 *aLocalName = NS_AtomizeMainThread(aQName).take();
5272 }
5273 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", 5273
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
5274 return NS_OK;
5275}
5276
5277// static
5278nsresult nsContentUtils::GetNodeInfoFromQName(
5279 const nsAString& aNamespaceURI, const nsAString& aQualifiedName,
5280 nsNodeInfoManager* aNodeInfoManager, uint16_t aNodeType,
5281 mozilla::dom::NodeInfo** aNodeInfo) {
5282 const nsString& qName = PromiseFlatStringTPromiseFlatString<char16_t>(aQualifiedName);
5283 const char16_t* colon;
5284 const char16_t* localNameEnd;
5285 nsresult rv = nsContentUtils::ParseQualifiedNameRelaxed(
5286 qName, aNodeType, &colon, &localNameEnd);
5287 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5287); return rv; } } while (false)
;
5288
5289 int32_t nsID;
5290 nsNameSpaceManager::GetInstance()->RegisterNameSpace(aNamespaceURI, nsID);
5291 if (colon) {
5292 RefPtr<nsAtom> prefix = NS_AtomizeMainThread(Substring(qName.get(), colon));
5293
5294 rv = aNodeInfoManager->GetNodeInfo(Substring(colon + 1, localNameEnd),
5295 prefix, nsID, aNodeType, aNodeInfo);
5296 } else {
5297 rv = aNodeInfoManager->GetNodeInfo(aQualifiedName, nullptr, nsID, aNodeType,
5298 aNodeInfo);
5299 }
5300 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"
, 5300); return rv; } } while (false)
;
5301
5302 return nsContentUtils::IsValidNodeName((*aNodeInfo)->NameAtom(),
5303 (*aNodeInfo)->GetPrefixAtom(),
5304 (*aNodeInfo)->NamespaceID())
5305 ? NS_OK
5306 : NS_ERROR_DOM_NAMESPACE_ERR;
5307}
5308
5309// static
5310void nsContentUtils::SplitExpatName(const char16_t* aExpatName,
5311 nsAtom** aPrefix, nsAtom** aLocalName,
5312 int32_t* aNameSpaceID) {
5313 /**
5314 * Expat can send the following:
5315 * localName
5316 * namespaceURI<separator>localName
5317 * namespaceURI<separator>localName<separator>prefix
5318 *
5319 * and we use 0xFFFF for the <separator>.
5320 *
5321 */
5322
5323 const char16_t* uriEnd = nullptr;
5324 const char16_t* nameEnd = nullptr;
5325 const char16_t* pos;
5326 for (pos = aExpatName; *pos; ++pos) {
5327 if (*pos == 0xFFFF) {
5328 if (uriEnd) {
5329 nameEnd = pos;
5330 } else {
5331 uriEnd = pos;
5332 }
5333 }
5334 }
5335
5336 const char16_t* nameStart;
5337 if (uriEnd) {
5338 nsNameSpaceManager::GetInstance()->RegisterNameSpace(
5339 nsDependentSubstring(aExpatName, uriEnd), *aNameSpaceID);
5340
5341 nameStart = (uriEnd + 1);
5342 if (nameEnd) {
5343 const char16_t* prefixStart = nameEnd + 1;
5344 *aPrefix = NS_AtomizeMainThread(Substring(prefixStart, pos)).take();
5345 } else {
5346 nameEnd = pos;
5347 *aPrefix = nullptr;
5348 }
5349 } else {
5350 *aNameSpaceID = kNameSpaceID_None;
5351 nameStart = aExpatName;
5352 nameEnd = pos;
5353 *aPrefix = nullptr;
5354 }
5355 *aLocalName = NS_AtomizeMainThread(Substring(nameStart, nameEnd)).take();
5356}
5357
5358// static
5359PresShell* nsContentUtils::GetPresShellForContent(const nsIContent* aContent) {
5360 Document* doc = aContent->GetComposedDoc();
5361 if (!doc) {
5362 return nullptr;
5363 }
5364 return doc->GetPresShell();
5365}
5366
5367// static
5368nsPresContext* nsContentUtils::GetContextForContent(
5369 const nsIContent* aContent) {
5370 PresShell* presShell = GetPresShellForContent(aContent);
5371 if (!presShell) {
5372 return nullptr;
5373 }
5374 return presShell->GetPresContext();
5375}
5376
5377// static
5378bool nsContentUtils::IsInPrivateBrowsing(nsILoadGroup* aLoadGroup) {
5379 if (!aLoadGroup) {
5380 return false;
5381 }
5382 // See duplicated code in Document::Reset/ResetToURI
5383 bool isPrivate = false;
5384 nsCOMPtr<nsIInterfaceRequestor> callbacks;
5385 aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
5386 if (callbacks) {
5387 nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
5388 isPrivate = loadContext && loadContext->UsePrivateBrowsing();
5389 }
5390 return isPrivate;
5391}
5392
5393// FIXME(emilio): This is (effectively) almost but not quite the same as
5394// Document::ShouldLoadImages(), which one is right?
5395bool nsContentUtils::DocumentInactiveForImageLoads(Document* aDocument) {
5396 if (!aDocument) {
5397 return false;
5398 }
5399 if (IsChromeDoc(aDocument) || aDocument->IsResourceDoc() ||
5400 aDocument->IsStaticDocument()) {
5401 return false;
5402 }
5403 nsCOMPtr<nsPIDOMWindowInner> win =
5404 do_QueryInterface(aDocument->GetScopeObject());
5405 return !win || !win->GetDocShell();
5406}
5407
5408imgLoader* nsContentUtils::GetImgLoaderForDocument(Document* aDoc) {
5409 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"
, 5409); return nullptr; } } while (false)
;
5410
5411 if (!aDoc) {
5412 return imgLoader::NormalLoader();
5413 }
5414 const bool isPrivate = aDoc->IsInPrivateBrowsing();
5415 return isPrivate ? imgLoader::PrivateBrowsingLoader()
5416 : imgLoader::NormalLoader();
5417}
5418
5419// static
5420imgLoader* nsContentUtils::GetImgLoaderForChannel(nsIChannel* aChannel,
5421 Document* aContext) {
5422 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", 5422); return
nullptr; } } while (false)
;
5423
5424 if (!aChannel) {
5425 return imgLoader::NormalLoader();
5426 }
5427 return NS_UsePrivateBrowsing(aChannel) ? imgLoader::PrivateBrowsingLoader()
5428 : imgLoader::NormalLoader();
5429}
5430
5431// static
5432int32_t nsContentUtils::CORSModeToLoadImageFlags(mozilla::CORSMode aMode) {
5433 switch (aMode) {
5434 case CORS_ANONYMOUS:
5435 return imgILoader::LOAD_CORS_ANONYMOUS;
5436 case CORS_USE_CREDENTIALS:
5437 return imgILoader::LOAD_CORS_USE_CREDENTIALS;
5438 default:
5439 return 0;
5440 }
5441}
5442
5443// static
5444nsresult nsContentUtils::LoadImage(
5445 nsIURI* aURI, nsINode* aContext, Document* aLoadingDocument,
5446 nsIPrincipal* aLoadingPrincipal, uint64_t aRequestContextID,
5447 nsIReferrerInfo* aReferrerInfo, imgINotificationObserver* aObserver,
5448 int32_t aLoadFlags, const nsAString& initiatorType,
5449 imgRequestProxy** aRequest, nsContentPolicyType aContentPolicyType,
5450 bool aUseUrgentStartForChannel, bool aLinkPreload,
5451 uint64_t aEarlyHintPreloaderId,
5452 mozilla::dom::FetchPriority aFetchPriority) {
5453 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", 5453); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aURI" ") (" "Must have a URI" ")"); do { MOZ_CrashSequence
(__null, 5453); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5454 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", 5454
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContext" ") (" "Must have a context"
")"); do { MOZ_CrashSequence(__null, 5454); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5455 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"
, 5455); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingDocument"
") (" "Must have a document" ")"); do { MOZ_CrashSequence(__null
, 5455); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
5456 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"
, 5456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Must have a principal" ")"); do { MOZ_CrashSequence(__null
, 5456); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
5457 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", 5457
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRequest" ") (" "Null out param"
")"); do { MOZ_CrashSequence(__null, 5457); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5458
5459 imgLoader* imgLoader = GetImgLoaderForDocument(aLoadingDocument);
5460 if (!imgLoader) {
5461 // nothing we can do here
5462 return NS_ERROR_FAILURE;
5463 }
5464
5465 nsCOMPtr<nsILoadGroup> loadGroup = aLoadingDocument->GetDocumentLoadGroup();
5466
5467 nsIURI* documentURI = aLoadingDocument->GetDocumentURI();
5468
5469 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"
, 5470); MOZ_PretendNoReturn(); } } while (0)
5470 "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"
, 5470); MOZ_PretendNoReturn(); } } while (0)
;
5471
5472 // XXXbz using "documentURI" for the initialDocumentURI is not quite
5473 // right, but the best we can do here...
5474 return imgLoader->LoadImage(aURI, /* uri to load */
5475 documentURI, /* initialDocumentURI */
5476 aReferrerInfo, /* referrerInfo */
5477 aLoadingPrincipal, /* loading principal */
5478 aRequestContextID, /* request context ID */
5479 loadGroup, /* loadgroup */
5480 aObserver, /* imgINotificationObserver */
5481 aContext, /* loading context */
5482 aLoadingDocument, /* uniquification key */
5483 aLoadFlags, /* load flags */
5484 nullptr, /* cache key */
5485 aContentPolicyType, /* content policy type */
5486 initiatorType, /* the load initiator */
5487 aUseUrgentStartForChannel, /* urgent-start flag */
5488 aLinkPreload, /* <link preload> initiator */
5489 aEarlyHintPreloaderId, aFetchPriority, aRequest);
5490}
5491
5492// static
5493already_AddRefed<imgIContainer> nsContentUtils::GetImageFromContent(
5494 nsIImageLoadingContent* aContent, imgIRequest** aRequest) {
5495 if (aRequest) {
5496 *aRequest = nullptr;
5497 }
5498
5499 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", 5499); return
nullptr; } } while (false)
;
5500
5501 nsCOMPtr<imgIRequest> imgRequest;
5502 aContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
5503 getter_AddRefs(imgRequest));
5504 if (!imgRequest) {
5505 return nullptr;
5506 }
5507
5508 nsCOMPtr<imgIContainer> imgContainer;
5509 imgRequest->GetImage(getter_AddRefs(imgContainer));
5510
5511 if (!imgContainer) {
5512 return nullptr;
5513 }
5514
5515 if (aRequest) {
5516 // If the consumer wants the request, verify it has actually loaded
5517 // successfully.
5518 uint32_t imgStatus;
5519 imgRequest->GetImageStatus(&imgStatus);
5520 if (imgStatus & imgIRequest::STATUS_FRAME_COMPLETE &&
5521 !(imgStatus & imgIRequest::STATUS_ERROR)) {
5522 imgRequest.swap(*aRequest);
5523 }
5524 }
5525
5526 return imgContainer.forget();
5527}
5528
5529static bool IsLinkWithURI(const nsIContent& aContent) {
5530 const auto* element = Element::FromNode(aContent);
5531 if (!element || !element->IsLink()) {
5532 return false;
5533 }
5534 nsCOMPtr<nsIURI> absURI = element->GetHrefURI();
5535 return !!absURI;
5536}
5537
5538static bool HasImageRequest(nsIContent& aContent) {
5539 nsCOMPtr<nsIImageLoadingContent> imageContent(do_QueryInterface(&aContent));
5540 if (!imageContent) {
5541 return false;
5542 }
5543
5544 nsCOMPtr<imgIRequest> imgRequest;
5545 imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
5546 getter_AddRefs(imgRequest));
5547
5548 // XXXbz It may be draggable even if the request resulted in an error. Why?
5549 // Not sure; that's what the old nsContentAreaDragDrop/nsFrame code did.
5550 return !!imgRequest;
5551}
5552
5553static Maybe<bool> DraggableOverride(const nsIContent& aContent) {
5554 if (auto* el = nsGenericHTMLElement::FromNode(aContent)) {
5555 if (el->Draggable()) {
5556 return Some(true);
5557 }
5558
5559 if (el->AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable,
5560 nsGkAtoms::_false, eIgnoreCase)) {
5561 return Some(false);
5562 }
5563 }
5564 if (aContent.IsSVGElement()) {
5565 return Some(false);
5566 }
5567 return Nothing();
5568}
5569
5570// static
5571bool nsContentUtils::ContentIsDraggable(nsIContent* aContent) {
5572 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"
, 5572); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { MOZ_CrashSequence(__null, 5572); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5573
5574 if (auto draggable = DraggableOverride(*aContent)) {
5575 return *draggable;
5576 }
5577
5578 // special handling for content area image and link dragging
5579 return HasImageRequest(*aContent) || IsLinkWithURI(*aContent);
5580}
5581
5582// static
5583bool nsContentUtils::IsDraggableImage(nsIContent* aContent) {
5584 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"
, 5584); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { MOZ_CrashSequence(__null, 5584); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5585 return HasImageRequest(*aContent) &&
5586 DraggableOverride(*aContent).valueOr(true);
5587}
5588
5589// static
5590bool nsContentUtils::IsDraggableLink(const nsIContent* aContent) {
5591 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"
, 5591); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aContent" ")"
); do { MOZ_CrashSequence(__null, 5591); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5592 return IsLinkWithURI(*aContent) && DraggableOverride(*aContent).valueOr(true);
5593}
5594
5595// static
5596nsresult nsContentUtils::QNameChanged(mozilla::dom::NodeInfo* aNodeInfo,
5597 nsAtom* aName,
5598 mozilla::dom::NodeInfo** aResult) {
5599 nsNodeInfoManager* niMgr = aNodeInfo->NodeInfoManager();
5600
5601 *aResult = niMgr
5602 ->GetNodeInfo(aName, nullptr, aNodeInfo->NamespaceID(),
5603 aNodeInfo->NodeType(), aNodeInfo->GetExtraName())
5604 .take();
5605 return NS_OK;
5606}
5607
5608static bool TestSitePerm(nsIPrincipal* aPrincipal, const nsACString& aType,
5609 uint32_t aPerm, bool aExactHostMatch) {
5610 if (!aPrincipal) {
5611 // We always deny (i.e. don't allow) the permission if we don't have a
5612 // principal.
5613 return aPerm != nsIPermissionManager::ALLOW_ACTION;
5614 }
5615
5616 nsCOMPtr<nsIPermissionManager> permMgr =
5617 components::PermissionManager::Service();
5618 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", 5618); return
false; } } while (false)
;
5619
5620 uint32_t perm;
5621 nsresult rv;
5622 if (aExactHostMatch) {
5623 rv = permMgr->TestExactPermissionFromPrincipal(aPrincipal, aType, &perm);
5624 } else {
5625 rv = permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &perm);
5626 }
5627 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"
, 5627); return false; } } while (false)
;
5628
5629 return perm == aPerm;
5630}
5631
5632bool nsContentUtils::IsSitePermAllow(nsIPrincipal* aPrincipal,
5633 const nsACString& aType) {
5634 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION,
5635 false);
5636}
5637
5638bool nsContentUtils::IsSitePermDeny(nsIPrincipal* aPrincipal,
5639 const nsACString& aType) {
5640 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION,
5641 false);
5642}
5643
5644bool nsContentUtils::IsExactSitePermAllow(nsIPrincipal* aPrincipal,
5645 const nsACString& aType) {
5646 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::ALLOW_ACTION,
5647 true);
5648}
5649
5650bool nsContentUtils::IsExactSitePermDeny(nsIPrincipal* aPrincipal,
5651 const nsACString& aType) {
5652 return TestSitePerm(aPrincipal, aType, nsIPermissionManager::DENY_ACTION,
5653 true);
5654}
5655
5656bool nsContentUtils::HasSitePerm(nsIPrincipal* aPrincipal,
5657 const nsACString& aType) {
5658 if (!aPrincipal) {
5659 return false;
5660 }
5661
5662 nsCOMPtr<nsIPermissionManager> permMgr =
5663 components::PermissionManager::Service();
5664 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", 5664); return
false; } } while (false)
;
5665
5666 uint32_t perm;
5667 nsresult rv = permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &perm);
5668 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"
, 5668); return false; } } while (false)
;
5669
5670 return perm != nsIPermissionManager::UNKNOWN_ACTION;
5671}
5672
5673static const char* gEventNames[] = {"event"};
5674static const char* gSVGEventNames[] = {"evt"};
5675// for b/w compat, the first name to onerror is still 'event', even though it
5676// is actually the error message
5677static const char* gOnErrorNames[] = {"event", "source", "lineno", "colno",
5678 "error"};
5679
5680// static
5681void nsContentUtils::GetEventArgNames(int32_t aNameSpaceID, nsAtom* aEventName,
5682 bool aIsForWindow, uint32_t* aArgCount,
5683 const char*** aArgArray) {
5684#define SET_EVENT_ARG_NAMES(names)*aArgCount = sizeof(names) / sizeof(names[0]); *aArgArray = names
;
\
5685 *aArgCount = sizeof(names) / sizeof(names[0]); \
5686 *aArgArray = names;
5687
5688 // JSEventHandler is what does the arg magic for onerror, and it does
5689 // not seem to take the namespace into account. So we let onerror in all
5690 // namespaces get the 3 arg names.
5691 if (aEventName == nsGkAtoms::onerror && aIsForWindow) {
5692 SET_EVENT_ARG_NAMES(gOnErrorNames)*aArgCount = sizeof(gOnErrorNames) / sizeof(gOnErrorNames[0])
; *aArgArray = gOnErrorNames;
;
5693 } else if (aNameSpaceID == kNameSpaceID_SVG9) {
5694 SET_EVENT_ARG_NAMES(gSVGEventNames)*aArgCount = sizeof(gSVGEventNames) / sizeof(gSVGEventNames[0
]); *aArgArray = gSVGEventNames;
;
5695 } else {
5696 SET_EVENT_ARG_NAMES(gEventNames)*aArgCount = sizeof(gEventNames) / sizeof(gEventNames[0]); *aArgArray
= gEventNames;
;
5697 }
5698}
5699
5700// Note: The list of content bundles in nsStringBundle.cpp should be updated
5701// whenever entries are added or removed from this list.
5702static const char* gPropertiesFiles[kPropertiesFileCount] = {
5703 // Must line up with the enum values in |PropertiesFile| enum.
5704 "chrome://global/locale/css.properties",
5705 "chrome://global/locale/xul.properties",
5706 "chrome://global/locale/layout_errors.properties",
5707 "chrome://global/locale/layout/HtmlForm.properties",
5708 "chrome://global/locale/printing.properties",
5709 "chrome://global/locale/dom/dom.properties",
5710 "chrome://global/locale/layout/htmlparser.properties",
5711 "chrome://global/locale/svg/svg.properties",
5712 "chrome://branding/locale/brand.properties",
5713 "chrome://global/locale/commonDialogs.properties",
5714 "chrome://global/locale/mathml/mathml.properties",
5715 "chrome://global/locale/security/security.properties",
5716 "chrome://necko/locale/necko.properties",
5717 "resource://gre/res/locale/layout/HtmlForm.properties",
5718 "resource://gre/res/locale/dom/dom.properties",
5719 "resource://gre/res/locale/necko/necko.properties",
5720};
5721
5722/* static */
5723nsresult nsContentUtils::EnsureStringBundle(PropertiesFile aFile) {
5724 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"
, 5725); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "NS_IsMainThread()"
") (" "Should not create bundles off main thread." ")"); do {
MOZ_CrashSequence(__null, 5725); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
5725 "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"
, 5725); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "NS_IsMainThread()"
") (" "Should not create bundles off main thread." ")"); do {
MOZ_CrashSequence(__null, 5725); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
5726 if (!sStringBundles[size_t(aFile)]) {
5727 if (!sStringBundleService) {
5728 nsresult rv =
5729 CallGetService(NS_STRINGBUNDLE_CONTRACTID"@mozilla.org/intl/stringbundle;1", &sStringBundleService);
5730 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"
, 5730); return rv; } } while (false)
;
5731 }
5732 RefPtr<nsIStringBundle> bundle;
5733 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(); })
5734 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(); })
;
5735 sStringBundles[size_t(aFile)] = bundle.forget();
5736 }
5737 return NS_OK;
5738}
5739
5740/* static */
5741void nsContentUtils::AsyncPrecreateStringBundles() {
5742 // We only ever want to pre-create bundles in the parent process.
5743 //
5744 // All nsContentUtils bundles are shared between the parent and child
5745 // precesses, and the shared memory regions that back them *must* be created
5746 // in the parent, and then sent to all children.
5747 //
5748 // If we attempt to create a bundle in the child before its memory region is
5749 // available, we need to create a temporary non-shared bundle, and later
5750 // replace that with the shared memory copy. So attempting to pre-load in the
5751 // child is wasteful and unnecessary.
5752 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", 5752); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "XRE_IsParentProcess()" ")"); do { MOZ_CrashSequence
(__null, 5752); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5753
5754 for (size_t bundleIndex = 0; bundleIndex < kPropertiesFileCount;
5755 ++bundleIndex) {
5756 nsresult rv = NS_DispatchToCurrentThreadQueue(
5757 NS_NewRunnableFunction("AsyncPrecreateStringBundles",
5758 [bundleIndex]() {
5759 PropertiesFile file =
5760 static_cast<PropertiesFile>(bundleIndex);
5761 EnsureStringBundle(file);
5762 nsIStringBundle* bundle =
5763 sStringBundles[size_t(file)];
5764 bundle->AsyncPreload();
5765 }),
5766 EventQueuePriority::Idle);
5767 (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"
, 5767)
;
5768 }
5769}
5770
5771static PropertiesFile GetMaybeSpoofedPropertiesFile(PropertiesFile aFile,
5772 const char* aKey,
5773 const Document* aDocument) {
5774 // When we spoof English, use en-US properties in strings that are accessible
5775 // by content.
5776 bool spoofLocale = nsContentUtils::ShouldResistFingerprinting(
5777 aDocument, RFPTarget::JSLocale);
5778 if (spoofLocale) {
5779 switch (aFile) {
5780 case PropertiesFile::FORMS_PROPERTIES:
5781 return PropertiesFile::FORMS_PROPERTIES_en_US;
5782 case PropertiesFile::DOM_PROPERTIES:
5783 return PropertiesFile::DOM_PROPERTIES_en_US;
5784 default:
5785 break;
5786 }
5787 }
5788 return aFile;
5789}
5790
5791/* static */
5792nsresult nsContentUtils::GetMaybeLocalizedString(PropertiesFile aFile,
5793 const char* aKey,
5794 const Document* aDocument,
5795 nsAString& aResult) {
5796 return GetLocalizedString(
5797 GetMaybeSpoofedPropertiesFile(aFile, aKey, aDocument), aKey, aResult);
5798}
5799
5800/* static */
5801nsresult nsContentUtils::GetLocalizedString(PropertiesFile aFile,
5802 const char* aKey,
5803 nsAString& aResult) {
5804 return FormatLocalizedString(aFile, aKey, {}, aResult);
5805}
5806
5807/* static */
5808nsresult nsContentUtils::FormatMaybeLocalizedString(
5809 PropertiesFile aFile, const char* aKey, Document* aDocument,
5810 const nsTArray<nsString>& aParams, nsAString& aResult) {
5811 return FormatLocalizedString(
5812 GetMaybeSpoofedPropertiesFile(aFile, aKey, aDocument), aKey, aParams,
5813 aResult);
5814}
5815
5816class FormatLocalizedStringRunnable final : public WorkerMainThreadRunnable {
5817 public:
5818 FormatLocalizedStringRunnable(WorkerPrivate* aWorkerPrivate,
5819 PropertiesFile aFile, const char* aKey,
5820 const nsTArray<nsString>& aParams,
5821 nsAString& aLocalizedString)
5822 : WorkerMainThreadRunnable(aWorkerPrivate,
5823 "FormatLocalizedStringRunnable"_ns),
5824 mFile(aFile),
5825 mKey(aKey),
5826 mParams(aParams),
5827 mLocalizedString(aLocalizedString) {
5828 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", 5828); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aWorkerPrivate" ")"); do { MOZ_CrashSequence
(__null, 5828); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5829 aWorkerPrivate->AssertIsOnWorkerThread();
5830 }
5831
5832 bool MainThreadRun() override {
5833 AssertIsOnMainThread();
5834
5835 mResult = nsContentUtils::FormatLocalizedString(mFile, mKey, mParams,
5836 mLocalizedString);
5837 (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"
, 5837)
;
5838 return true;
5839 }
5840
5841 nsresult GetResult() const { return mResult; }
5842
5843 private:
5844 const PropertiesFile mFile;
5845 const char* mKey;
5846 const nsTArray<nsString>& mParams;
5847 nsresult mResult = NS_ERROR_FAILURE;
5848 nsAString& mLocalizedString;
5849};
5850
5851/* static */
5852nsresult nsContentUtils::FormatLocalizedString(
5853 PropertiesFile aFile, const char* aKey, const nsTArray<nsString>& aParams,
5854 nsAString& aResult) {
5855 if (!NS_IsMainThread()) {
5856 // nsIStringBundle is thread-safe but its creation is not, and in particular
5857 // we don't create and store nsIStringBundle objects in a thread-safe way.
5858 //
5859 // TODO(emilio): Maybe if we already have the right bundle created we could
5860 // just call into it, but we should make sure that Shutdown() doesn't get
5861 // called on the main thread when that happens which is a bit tricky to
5862 // prove?
5863 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
5864 if (NS_WARN_IF(!workerPrivate)NS_warn_if_impl(!workerPrivate, "!workerPrivate", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 5864)
) {
5865 return NS_ERROR_UNEXPECTED;
5866 }
5867
5868 auto runnable = MakeRefPtr<FormatLocalizedStringRunnable>(
5869 workerPrivate, aFile, aKey, aParams, aResult);
5870
5871 runnable->Dispatch(workerPrivate, Canceling, IgnoreErrors());
5872 return runnable->GetResult();
5873 }
5874
5875 MOZ_TRY(EnsureStringBundle(aFile))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(EnsureStringBundle(aFile)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
;
5876 nsIStringBundle* bundle = sStringBundles[size_t(aFile)];
5877 if (aParams.IsEmpty()) {
5878 return bundle->GetStringFromName(aKey, aResult);
5879 }
5880 return bundle->FormatStringFromName(aKey, aParams, aResult);
5881}
5882
5883/* static */
5884void nsContentUtils::LogSimpleConsoleError(const nsAString& aErrorText,
5885 const nsACString& aCategory,
5886 bool aFromPrivateWindow,
5887 bool aFromChromeContext,
5888 uint32_t aErrorFlags) {
5889 nsCOMPtr<nsIScriptError> scriptError =
5890 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1");
5891 if (scriptError) {
5892 nsCOMPtr<nsIConsoleService> console =
5893 do_GetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1");
5894 if (console && NS_SUCCEEDED(scriptError->Init(((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init
( aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow
, aFromChromeContext))), 1)))
5895 aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory,((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init
( aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow
, aFromChromeContext))), 1)))
5896 aFromPrivateWindow, aFromChromeContext))((bool)(__builtin_expect(!!(!NS_FAILED_impl(scriptError->Init
( aErrorText, ""_ns, 0, 0, aErrorFlags, aCategory, aFromPrivateWindow
, aFromChromeContext))), 1)))
) {
5897 console->LogMessage(scriptError);
5898 }
5899 }
5900}
5901
5902/* static */
5903nsresult nsContentUtils::ReportToConsole(
5904 uint32_t aErrorFlags, const nsACString& aCategory,
5905 const Document* aDocument, PropertiesFile aFile, const char* aMessageName,
5906 const nsTArray<nsString>& aParams, const SourceLocation& aLoc) {
5907 nsresult rv;
5908 nsAutoString errorText;
5909 if (!aParams.IsEmpty()) {
5910 rv = FormatLocalizedString(aFile, aMessageName, aParams, errorText);
5911 } else {
5912 rv = GetLocalizedString(aFile, aMessageName, errorText);
5913 }
5914 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"
, 5914); return rv; } } while (false)
;
5915 return ReportToConsoleNonLocalized(errorText, aErrorFlags, aCategory,
5916 aDocument, aLoc);
5917}
5918
5919/* static */
5920void nsContentUtils::ReportEmptyGetElementByIdArg(const Document* aDoc) {
5921 ReportToConsole(nsIScriptError::warningFlag, "DOM"_ns, aDoc,
5922 PropertiesFile::DOM_PROPERTIES, "EmptyGetElementByIdParam");
5923}
5924
5925/* static */
5926nsresult nsContentUtils::ReportToConsoleNonLocalized(
5927 const nsAString& aErrorText, uint32_t aErrorFlags,
5928 const nsACString& aCategory, const Document* aDocument,
5929 const SourceLocation& aLoc) {
5930 uint64_t innerWindowID = aDocument ? aDocument->InnerWindowID() : 0;
5931 if (aLoc || !aDocument || !aDocument->GetDocumentURI()) {
5932 return ReportToConsoleByWindowID(aErrorText, aErrorFlags, aCategory,
5933 innerWindowID, aLoc);
5934 }
5935 return ReportToConsoleByWindowID(aErrorText, aErrorFlags, aCategory,
5936 innerWindowID,
5937 SourceLocation(aDocument->GetDocumentURI()));
5938}
5939
5940/* static */
5941nsresult nsContentUtils::ReportToConsoleByWindowID(
5942 const nsAString& aErrorText, uint32_t aErrorFlags,
5943 const nsACString& aCategory, uint64_t aInnerWindowID,
5944 const SourceLocation& aLocation) {
5945 nsresult rv;
5946 if (!sConsoleService) { // only need to bother null-checking here
5947 rv = CallGetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1", &sConsoleService);
5948 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"
, 5948); return rv; } } while (false)
;
5949 }
5950
5951 nsCOMPtr<nsIScriptError> errorObject =
5952 do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1", &rv);
5953 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"
, 5953); return rv; } } while (false)
;
5954
5955 if (aLocation.mResource.is<nsCOMPtr<nsIURI>>()) {
5956 nsIURI* uri = aLocation.mResource.as<nsCOMPtr<nsIURI>>();
5957 rv = errorObject->InitWithSourceURI(aErrorText, uri, aLocation.mLine,
5958 aLocation.mColumn, aErrorFlags,
5959 aCategory, aInnerWindowID);
5960 } else {
5961 rv = errorObject->InitWithWindowID(
5962 aErrorText, aLocation.mResource.as<nsCString>(), aLocation.mLine,
5963 aLocation.mColumn, aErrorFlags, aCategory, aInnerWindowID);
5964 }
5965 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"
, 5965); return rv; } } while (false)
;
5966
5967 return sConsoleService->LogMessage(errorObject);
5968}
5969
5970namespace {
5971
5972#define DEPRECATED_OPERATION(_op) #_op,
5973static const char* kDeprecatedOperations[] = {
5974#include "nsDeprecatedOperationList.inc"
5975 nullptr};
5976#undef DEPRECATED_OPERATION
5977
5978} // anonymous namespace
5979
5980/* static */
5981void nsContentUtils::ReportDeprecation(
5982 nsIGlobalObject* aGlobal, const Document* aDoc, nsIURI* aURI,
5983 DeprecatedOperations aOperation,
5984 const mozilla::JSCallingLocation& aLocation) {
5985 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"
, 5985); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aGlobal" ")"
); do { MOZ_CrashSequence(__null, 5985); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5986 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"
, 5986); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ")");
do { MOZ_CrashSequence(__null, 5986); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5987
5988 nsAutoCString url;
5989 ReportingUtils::StripURL(aURI, url);
5990
5991 const char* operation =
5992 kDeprecatedOperations[static_cast<size_t>(aOperation)];
5993 nsAutoString type;
5994 type.AppendASCII(operation);
5995
5996 nsAutoCString key;
5997 key.AssignLiteral(operation, strlen(operation));
5998 key.AppendLiteral("Warning");
5999
6000 // XXX do we really want the localized string for deprecation report?
6001 nsAutoString msg;
6002 nsresult rv = nsContentUtils::GetMaybeLocalizedString(
6003 PropertiesFile::DOM_PROPERTIES, key.get(), aDoc, msg);
6004 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"
, 6004)
) {
6005 return;
6006 }
6007
6008 Nullable<uint32_t> lineNumber;
6009 Nullable<uint32_t> columnNumber;
6010 nsAutoCString sourceFile;
6011 if (aLocation) {
6012 lineNumber.SetValue(aLocation.mLine);
6013 columnNumber.SetValue(aLocation.mColumn);
6014 ReportingUtils::StripLocationFileName(aLocation, sourceFile);
6015 }
6016
6017 RefPtr<DeprecationReportBody> body =
6018 new DeprecationReportBody(aGlobal, type, nullptr /* date */, msg,
6019 sourceFile, lineNumber, columnNumber);
6020
6021 ReportingUtils::Report(aGlobal, nsGkAtoms::deprecation, u"default"_ns,
6022 NS_ConvertUTF8toUTF16(url), body);
6023}
6024
6025void nsContentUtils::LogMessageToConsole(const char* aMsg) {
6026 if (!sConsoleService) { // only need to bother null-checking here
6027 CallGetService(NS_CONSOLESERVICE_CONTRACTID"@mozilla.org/consoleservice;1", &sConsoleService);
6028 if (!sConsoleService) {
6029 return;
6030 }
6031 }
6032 sConsoleService->LogStringMessage(NS_ConvertUTF8toUTF16(aMsg).get());
6033}
6034
6035bool nsContentUtils::IsChromeDoc(const Document* aDocument) {
6036 return aDocument && aDocument->NodePrincipal() == sSystemPrincipal;
6037}
6038
6039bool nsContentUtils::IsAddonDoc(const Document* aDocument) {
6040 return aDocument &&
6041 aDocument->NodePrincipal()->GetIsAddonOrExpandedAddonPrincipal();
6042}
6043
6044bool nsContentUtils::IsChildOfSameType(Document* aDoc) {
6045 if (BrowsingContext* bc = aDoc->GetBrowsingContext()) {
6046 return bc->GetParent();
6047 }
6048 return false;
6049}
6050
6051static bool IsJSONType(const nsACString& aContentType) {
6052 return aContentType.EqualsLiteral(TEXT_JSON"text/json") ||
6053 aContentType.EqualsLiteral(APPLICATION_JSON"application/json");
6054}
6055
6056static bool IsNonPlainTextType(const nsACString& aContentType) {
6057 // MIME type suffixes which should not be plain text.
6058 static constexpr std::string_view kNonPlainTextTypes[] = {
6059 "html",
6060 "xml",
6061 "xsl",
6062 "calendar",
6063 "x-calendar",
6064 "x-vcalendar",
6065 "vcalendar",
6066 "vcard",
6067 "x-vcard",
6068 "directory",
6069 "ldif",
6070 "qif",
6071 "x-qif",
6072 "x-csv",
6073 "x-vcf",
6074 "rtf",
6075 "comma-separated-values",
6076 "csv",
6077 "tab-separated-values",
6078 "tsv",
6079 "ofx",
6080 "vnd.sun.j2me.app-descriptor",
6081 "x-ms-iqy",
6082 "x-ms-odc",
6083 "x-ms-rqy",
6084 "x-ms-contact"};
6085
6086 // Trim off the "text/" prefix for comparison.
6087 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", 6087); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "StringBeginsWith(aContentType, \"text/\"_ns)"
")"); do { MOZ_CrashSequence(__null, 6087); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6088 std::string_view suffix = aContentType;
6089 suffix.remove_prefix(5);
6090
6091 for (std::string_view type : kNonPlainTextTypes) {
6092 if (type == suffix) {
6093 return true;
6094 }
6095 }
6096 return false;
6097}
6098
6099bool nsContentUtils::IsPlainTextType(const nsACString& aContentType) {
6100 // All `text/*`, any JSON type and any JavaScript type are considered "plain
6101 // text" types for the purposes of how to render them as a document.
6102 return (StringBeginsWith(aContentType, "text/"_ns) &&
6103 !IsNonPlainTextType(aContentType)) ||
6104 IsJSONType(aContentType) || IsJavascriptMIMEType(aContentType);
6105}
6106
6107bool nsContentUtils::IsUtf8OnlyPlainTextType(const nsACString& aContentType) {
6108 // NOTE: This must be a subset of the list in IsPlainTextType().
6109 return IsJSONType(aContentType) ||
6110 aContentType.EqualsLiteral(TEXT_CACHE_MANIFEST"text/cache-manifest") ||
6111 aContentType.EqualsLiteral(TEXT_VTT"text/vtt");
6112}
6113
6114bool nsContentUtils::IsInChromeDocshell(const Document* aDocument) {
6115 return aDocument && aDocument->IsInChromeDocShell();
6116}
6117
6118// static
6119nsIContentPolicy* nsContentUtils::GetContentPolicy() {
6120 if (!sTriedToGetContentPolicy) {
6121 CallGetService(NS_CONTENTPOLICY_CONTRACTID"@mozilla.org/layout/content-policy;1", &sContentPolicyService);
6122 // It's OK to not have a content policy service
6123 sTriedToGetContentPolicy = true;
6124 }
6125
6126 return sContentPolicyService;
6127}
6128
6129// static
6130bool nsContentUtils::IsEventAttributeName(nsAtom* aName, int32_t aType) {
6131 const char16_t* name = aName->GetUTF16String();
6132 if (name[0] != 'o' || name[1] != 'n') {
6133 return false;
6134 }
6135
6136 EventNameMapping mapping;
6137 return (sAtomEventTable->Get(aName, &mapping) && mapping.mType & aType);
6138}
6139
6140// static
6141EventMessage nsContentUtils::GetEventMessage(nsAtom* aName) {
6142 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"
, 6142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "sAtomEventTable is not threadsafe" ")"); do { MOZ_CrashSequence
(__null, 6142); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6143 if (aName) {
6144 EventNameMapping mapping;
6145 if (sAtomEventTable->Get(aName, &mapping)) {
6146 return mapping.mMessage;
6147 }
6148 }
6149
6150 return eUnidentifiedEvent;
6151}
6152
6153// static
6154void nsContentUtils::ForEachEventAttributeName(
6155 int32_t aType, const FunctionRef<void(nsAtom*)> aFunc) {
6156 for (auto iter = sAtomEventTable->ConstIter(); !iter.Done(); iter.Next()) {
6157 if (iter.Data().mType & aType) {
6158 aFunc(iter.Key());
6159 }
6160 }
6161}
6162
6163// static
6164mozilla::EventClassID nsContentUtils::GetEventClassID(const nsAString& aName) {
6165 EventNameMapping mapping;
6166 if (sStringEventTable->Get(aName, &mapping)) return mapping.mEventClassID;
6167
6168 return eBasicEventClass;
6169}
6170
6171nsAtom* nsContentUtils::GetEventMessageAndAtom(
6172 const nsAString& aName, mozilla::EventClassID aEventClassID,
6173 EventMessage* aEventMessage) {
6174 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"
, 6174); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Our hashtables are not threadsafe" ")"); do { MOZ_CrashSequence
(__null, 6174); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6175 EventNameMapping mapping;
6176 if (sStringEventTable->Get(aName, &mapping)) {
6177 *aEventMessage = mapping.mEventClassID == aEventClassID
6178 ? mapping.mMessage
6179 : eUnidentifiedEvent;
6180 return mapping.mAtom;
6181 }
6182
6183 // If we have cached lots of user defined event names, clear some of them.
6184 if (sUserDefinedEvents->Length() > 127) {
6185 while (sUserDefinedEvents->Length() > 64) {
6186 nsAtom* first = sUserDefinedEvents->ElementAt(0);
6187 sStringEventTable->Remove(Substring(nsDependentAtomString(first), 2));
6188 sUserDefinedEvents->RemoveElementAt(0);
6189 }
6190 }
6191
6192 *aEventMessage = eUnidentifiedEvent;
6193 RefPtr<nsAtom> atom = NS_AtomizeMainThread(u"on"_ns + aName);
6194 sUserDefinedEvents->AppendElement(atom);
6195 mapping.mAtom = atom;
6196 mapping.mMessage = eUnidentifiedEvent;
6197 mapping.mType = EventNameType_None;
6198 mapping.mEventClassID = eBasicEventClass;
6199 sStringEventTable->InsertOrUpdate(aName, mapping);
6200 return mapping.mAtom;
6201}
6202
6203// static
6204EventMessage nsContentUtils::GetEventMessageAndAtomForListener(
6205 const nsAString& aName, nsAtom** aOnName) {
6206 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"
, 6206); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Our hashtables are not threadsafe" ")"); do { MOZ_CrashSequence
(__null, 6206); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6207
6208 // Check sStringEventTable for a matching entry. This will only fail for
6209 // user-defined event types.
6210 EventNameMapping mapping;
6211 if (sStringEventTable->Get(aName, &mapping)) {
6212 RefPtr<nsAtom> atom = mapping.mAtom;
6213 atom.forget(aOnName);
6214 return mapping.mMessage;
6215 }
6216
6217 // sStringEventTable did not contain an entry for this event type string.
6218 // Call GetEventMessageAndAtom, which will create an event type atom and
6219 // cache it in sStringEventTable for future calls.
6220 EventMessage msg = eUnidentifiedEvent;
6221 RefPtr<nsAtom> atom = GetEventMessageAndAtom(aName, eBasicEventClass, &msg);
6222 atom.forget(aOnName);
6223 return msg;
6224}
6225
6226static already_AddRefed<Event> GetEventWithTarget(
6227 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
6228 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
6229 Trusted aTrusted, ErrorResult& aErrorResult) {
6230 RefPtr<Event> event =
6231 aDoc->CreateEvent(u"Events"_ns, CallerType::System, aErrorResult);
6232 if (aErrorResult.Failed()) {
6233 return nullptr;
6234 }
6235
6236 event->InitEvent(aEventName, aCanBubble, aCancelable, aComposed);
6237 event->SetTrusted(aTrusted == Trusted::eYes);
6238
6239 event->SetTarget(aTarget);
6240
6241 return event.forget();
6242}
6243
6244// static
6245nsIContent* nsContentUtils::GetEventTargetContent(
6246 nsIContent* aExplicitEventTargetContent, const WidgetEvent* aEvent) {
6247 if (!aExplicitEventTargetContent ||
6248 aExplicitEventTargetContent->IsElement() || !aEvent ||
6249 !IsForbiddenDispatchingToNonElementContent(aEvent->mMessage)) {
6250 return aExplicitEventTargetContent;
6251 }
6252 Element* const ancestorElement =
6253 aExplicitEventTargetContent->GetInclusiveFlattenedTreeAncestorElement();
6254 return ancestorElement ? ancestorElement : aExplicitEventTargetContent;
6255}
6256
6257// static
6258nsresult nsContentUtils::DispatchTrustedEvent(
6259 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
6260 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
6261 bool* aDefaultAction, SystemGroupOnly aSystemGroupOnly) {
6262 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"
, 6264); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
") (" "Use DispatchInputEvent() instead" ")"); do { MOZ_CrashSequence
(__null, 6264); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6263 !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"
, 6264); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
") (" "Use DispatchInputEvent() instead" ")"); do { MOZ_CrashSequence
(__null, 6264); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6264 "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"
, 6264); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventName.EqualsLiteral(\"input\") && !aEventName.EqualsLiteral(\"beforeinput\")"
") (" "Use DispatchInputEvent() instead" ")"); do { MOZ_CrashSequence
(__null, 6264); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6265 return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
6266 aComposed, Trusted::eYes, aDefaultAction,
6267 ChromeOnlyDispatch::eNo, aSystemGroupOnly);
6268}
6269
6270// static
6271nsresult nsContentUtils::DispatchUntrustedEvent(
6272 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
6273 CanBubble aCanBubble, Cancelable aCancelable, bool* aDefaultAction) {
6274 return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
6275 Composed::eDefault, Trusted::eNo, aDefaultAction);
6276}
6277
6278// static
6279nsresult nsContentUtils::DispatchEvent(
6280 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
6281 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
6282 Trusted aTrusted, bool* aDefaultAction,
6283 ChromeOnlyDispatch aOnlyChromeDispatch, SystemGroupOnly aSystemGroupOnly) {
6284 if (!aDoc || !aTarget) {
6285 return NS_ERROR_INVALID_ARG;
6286 }
6287
6288 ErrorResult err;
6289 RefPtr<Event> event =
6290 GetEventWithTarget(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
6291 aComposed, aTrusted, err);
6292 if (err.Failed()) {
6293 return err.StealNSResult();
6294 }
6295 event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch =
6296 aOnlyChromeDispatch == ChromeOnlyDispatch::eYes;
6297 event->WidgetEventPtr()->mFlags.mOnlySystemGroupDispatch =
6298 aSystemGroupOnly == SystemGroupOnly::eYes;
6299
6300 // For the performance reason, aDoc may be set to a raw pointer because it's
6301 // used only before dispatching the event. Therefore, we should not use aDoc
6302 // anymore.
6303 aDoc = nullptr;
6304 bool doDefault = aTarget->DispatchEvent(*event, CallerType::System, err);
6305 if (aDefaultAction) {
6306 *aDefaultAction = doDefault;
6307 }
6308 return err.StealNSResult();
6309}
6310
6311// static
6312nsresult nsContentUtils::DispatchEvent(
6313 EventTarget* aTarget, WidgetEvent& aEvent, EventMessage aEventMessage,
6314 CanBubble aCanBubble, Cancelable aCancelable, Trusted aTrusted,
6315 bool* aDefaultAction, ChromeOnlyDispatch aOnlyChromeDispatch) {
6316 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", 6317); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aTrusted == Trusted::eYes" ")"); do { MOZ_CrashSequence
(__null, 6317); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
6317 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", 6317); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aTrusted == Trusted::eYes" ")"); do { MOZ_CrashSequence
(__null, 6317); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
6318
6319 aEvent.mSpecifiedEventType = GetEventTypeFromMessage(aEventMessage);
6320 aEvent.SetDefaultComposed();
6321 aEvent.SetDefaultComposedInNativeAnonymousContent();
6322
6323 aEvent.mFlags.mBubbles = aCanBubble == CanBubble::eYes;
6324 aEvent.mFlags.mCancelable = aCancelable == Cancelable::eYes;
6325 aEvent.mFlags.mOnlyChromeDispatch =
6326 aOnlyChromeDispatch == ChromeOnlyDispatch::eYes;
6327
6328 aEvent.mTarget = aTarget;
6329
6330 nsEventStatus status = nsEventStatus_eIgnore;
6331 nsresult rv = EventDispatcher::DispatchDOMEvent(aTarget, &aEvent, nullptr,
6332 nullptr, &status);
6333 if (aDefaultAction) {
6334 *aDefaultAction = (status != nsEventStatus_eConsumeNoDefault);
6335 }
6336 return rv;
6337}
6338
6339// static
6340nsresult nsContentUtils::DispatchInputEvent(Element* aEventTarget) {
6341 return DispatchInputEvent(aEventTarget, mozilla::eEditorInput,
6342 mozilla::EditorInputType::eUnknown, nullptr,
6343 InputEventOptions());
6344}
6345
6346// static
6347nsresult nsContentUtils::DispatchInputEvent(
6348 Element* aEventTargetElement, EventMessage aEventMessage,
6349 EditorInputType aEditorInputType, EditorBase* aEditorBase,
6350 InputEventOptions&& aOptions, nsEventStatus* aEventStatus /* = nullptr */) {
6351 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", 6352); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput"
")"); do { MOZ_CrashSequence(__null, 6352); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6352 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", 6352); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aEventMessage == eEditorInput || aEventMessage == eEditorBeforeInput"
")"); do { MOZ_CrashSequence(__null, 6352); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6353
6354 if (NS_WARN_IF(!aEventTargetElement)NS_warn_if_impl(!aEventTargetElement, "!aEventTargetElement",
"/root/firefox-clang/dom/base/nsContentUtils.cpp", 6354)
) {
6355 return NS_ERROR_INVALID_ARG;
6356 }
6357
6358 // If this is called from editor, the instance should be set to aEditorBase.
6359 // Otherwise, we need to look for an editor for aEventTargetElement.
6360 // However, we don't need to do it for HTMLEditor since nobody shouldn't
6361 // dispatch "beforeinput" nor "input" event for HTMLEditor except HTMLEditor
6362 // itself.
6363 bool useInputEvent = false;
6364 if (aEditorBase) {
6365 useInputEvent = true;
6366 } else if (const HTMLTextAreaElement* const textAreaElement =
6367 HTMLTextAreaElement::FromNode(aEventTargetElement)) {
6368 aEditorBase = textAreaElement->GetExtantTextEditor();
6369 useInputEvent = true;
6370 } else if (const HTMLInputElement* const inputElement =
6371 HTMLInputElement::FromNode(aEventTargetElement)) {
6372 if (inputElement->IsInputEventTarget()) {
6373 aEditorBase = inputElement->GetExtantTextEditor();
6374 useInputEvent = true;
6375 }
6376 }
6377#ifdef DEBUG1
6378 else {
6379 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", 6380
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventTargetElement->IsTextControlElement()"
") (" "The event target may have editor, but we've not known it yet."
")"); do { MOZ_CrashSequence(__null, 6380); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6380 "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", 6380
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aEventTargetElement->IsTextControlElement()"
") (" "The event target may have editor, but we've not known it yet."
")"); do { MOZ_CrashSequence(__null, 6380); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6381 }
6382#endif // #ifdef DEBUG
6383
6384 if (!useInputEvent) {
6385 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"
, 6385); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEventMessage == eEditorInput"
")"); do { MOZ_CrashSequence(__null, 6385); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6386 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", 6386); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eUnknown"
")"); do { MOZ_CrashSequence(__null, 6386); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6387 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", 6387); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable" ")"); do { MOZ_CrashSequence
(__null, 6387); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6388 // Dispatch "input" event with Event instance.
6389 WidgetEvent widgetEvent(true, eUnidentifiedEvent);
6390 widgetEvent.mSpecifiedEventType = nsGkAtoms::oninput;
6391 widgetEvent.mFlags.mCancelable = false;
6392 widgetEvent.mFlags.mComposed = true;
6393 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)
6394 ("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)
6395 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)
6396 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)
6397 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)
;
6398 return AsyncEventDispatcher::RunDOMEventWhenSafe(*aEventTargetElement,
6399 widgetEvent, aEventStatus);
6400 }
6401
6402 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", 6403); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable" ")"); do { MOZ_CrashSequence
(__null, 6403); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
6403 !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", 6403); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aOptions.mNeverCancelable" ")"); do { MOZ_CrashSequence
(__null, 6403); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false); } } while (false)
;
6404 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", 6406); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText"
")"); do { MOZ_CrashSequence(__null, 6406); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
6405 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", 6406); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText"
")"); do { MOZ_CrashSequence(__null, 6406); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
6406 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", 6406); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aEditorInputType == EditorInputType::eInsertReplacementText"
")"); do { MOZ_CrashSequence(__null, 6406); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6407
6408 nsCOMPtr<nsIWidget> widget;
6409 if (aEditorBase) {
6410 widget = aEditorBase->GetWidget();
6411 if (NS_WARN_IF(!widget)NS_warn_if_impl(!widget, "!widget", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6411)
) {
6412 return NS_ERROR_FAILURE;
6413 }
6414 } else {
6415 Document* document = aEventTargetElement->OwnerDoc();
6416 if (NS_WARN_IF(!document)NS_warn_if_impl(!document, "!document", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6416)
) {
6417 return NS_ERROR_FAILURE;
6418 }
6419 // If we're running xpcshell tests, we fail to get presShell here.
6420 // Even in such case, we need to dispatch "input" event without widget.
6421 PresShell* presShell = document->GetPresShell();
6422 if (presShell) {
6423 nsPresContext* presContext = presShell->GetPresContext();
6424 if (NS_WARN_IF(!presContext)NS_warn_if_impl(!presContext, "!presContext", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6424)
) {
6425 return NS_ERROR_FAILURE;
6426 }
6427 widget = presContext->GetRootWidget();
6428 if (NS_WARN_IF(!widget)NS_warn_if_impl(!widget, "!widget", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 6428)
) {
6429 return NS_ERROR_FAILURE;
6430 }
6431 }
6432 }
6433
6434 // Dispatch "input" event with InputEvent instance.
6435 InternalEditorInputEvent inputEvent(true, aEventMessage, widget);
6436
6437 inputEvent.mFlags.mCancelable =
6438 !aOptions.mNeverCancelable && aEventMessage == eEditorBeforeInput &&
6439 IsCancelableBeforeInputEvent(aEditorInputType);
6440 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", 6440); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!inputEvent.mFlags.mCancelable || aEventStatus"
")"); do { MOZ_CrashSequence(__null, 6440); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6441
6442 // If there is an editor, set isComposing to true when it has composition.
6443 // Note that EditorBase::IsIMEComposing() may return false even when we
6444 // need to set it to true.
6445 // Otherwise, i.e., editor hasn't been created for the element yet,
6446 // we should set isComposing to false since the element can never has
6447 // composition without editor.
6448 inputEvent.mIsComposing = aEditorBase && aEditorBase->GetComposition();
6449
6450 if (!aEditorBase || aEditorBase->IsTextEditor()) {
6451 if (IsDataAvailableOnTextEditor(aEditorInputType)) {
6452 inputEvent.mData = std::move(aOptions.mData);
6453 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"
, 6454); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { MOZ_CrashSequence
(__null, 6454); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6454 "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"
, 6454); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { MOZ_CrashSequence
(__null, 6454); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6455 }
6456#ifdef DEBUG1
6457 else {
6458 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"
, 6458); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mData.IsVoid()"
") (" "inputEvent.mData should be void" ")"); do { MOZ_CrashSequence
(__null, 6458); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6459 }
6460#endif // #ifdef DEBUG
6461 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", 6463
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges for <input> and <textarea> should always be empty"
")"); do { MOZ_CrashSequence(__null, 6463); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6462 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", 6463
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges for <input> and <textarea> should always be empty"
")"); do { MOZ_CrashSequence(__null, 6463); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6463 "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", 6463
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges for <input> and <textarea> should always be empty"
")"); do { MOZ_CrashSequence(__null, 6463); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6464 } else {
6465 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"
, 6465); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aEditorBase->IsHTMLEditor()"
")"); do { MOZ_CrashSequence(__null, 6465); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6466 if (IsDataAvailableOnHTMLEditor(aEditorInputType)) {
6467 inputEvent.mData = std::move(aOptions.mData);
6468 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"
, 6469); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { MOZ_CrashSequence
(__null, 6469); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
6469 "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"
, 6469); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mData.IsVoid()"
") (" "inputEvent.mData shouldn't be void" ")"); do { MOZ_CrashSequence
(__null, 6469); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6470 } else {
6471 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"
, 6471); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mData.IsVoid()"
") (" "inputEvent.mData should be void" ")"); do { MOZ_CrashSequence
(__null, 6471); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6472 if (IsDataTransferAvailableOnHTMLEditor(aEditorInputType)) {
6473 inputEvent.mDataTransfer = std::move(aOptions.mDataTransfer);
6474 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"
, 6475); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer shouldn't be nullptr" ")"); do
{ MOZ_CrashSequence(__null, 6475); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6475 "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"
, 6475); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer shouldn't be nullptr" ")"); do
{ MOZ_CrashSequence(__null, 6475); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6476 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"
, 6477); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer->IsReadOnly()"
") (" "inputEvent.mDataTransfer should be read only" ")"); do
{ MOZ_CrashSequence(__null, 6477); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6477 "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"
, 6477); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputEvent.mDataTransfer->IsReadOnly()"
") (" "inputEvent.mDataTransfer should be read only" ")"); do
{ MOZ_CrashSequence(__null, 6477); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6478 }
6479#ifdef DEBUG1
6480 else {
6481 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"
, 6482); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer should be nullptr" ")"); do {
MOZ_CrashSequence(__null, 6482); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
6482 "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"
, 6482); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!inputEvent.mDataTransfer"
") (" "inputEvent.mDataTransfer should be nullptr" ")"); do {
MOZ_CrashSequence(__null, 6482); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6483 }
6484#endif // #ifdef DEBUG
6485 }
6486 if (aEventMessage == eEditorBeforeInput &&
6487 MayHaveTargetRangesOnHTMLEditor(aEditorInputType)) {
6488 inputEvent.mTargetRanges = std::move(aOptions.mTargetRanges);
6489 }
6490#ifdef DEBUG1
6491 else {
6492 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", 6493
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges shouldn't be set for the dispatching event"
")"); do { MOZ_CrashSequence(__null, 6493); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6493 "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", 6493
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOptions.mTargetRanges.IsEmpty()"
") (" "Target ranges shouldn't be set for the dispatching event"
")"); do { MOZ_CrashSequence(__null, 6493); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6494 }
6495#endif // #ifdef DEBUG
6496 }
6497
6498 inputEvent.mInputType = aEditorInputType;
6499
6500 // If we cannot dispatch an event right now, we cannot make it cancelable.
6501 if (!nsContentUtils::IsSafeToRunScript()) {
6502 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"
, 6504); MOZ_PretendNoReturn(); } } while (0)
6503 !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"
, 6504); MOZ_PretendNoReturn(); } } while (0)
6504 "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"
, 6504); MOZ_PretendNoReturn(); } } while (0)
;
6505 inputEvent.mFlags.mCancelable = false;
6506 }
6507 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)
6508 ("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)
6509 "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)
6510 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)
6511 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)
6512 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)
6513 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)
;
6514 return AsyncEventDispatcher::RunDOMEventWhenSafe(*aEventTargetElement,
6515 inputEvent, aEventStatus);
6516}
6517
6518nsresult nsContentUtils::DispatchChromeEvent(
6519 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
6520 CanBubble aCanBubble, Cancelable aCancelable, bool* aDefaultAction) {
6521 if (!aDoc || !aTarget) {
6522 return NS_ERROR_INVALID_ARG;
6523 }
6524
6525 if (!aDoc->GetWindow()) {
6526 return NS_ERROR_INVALID_ARG;
6527 }
6528
6529 EventTarget* piTarget = aDoc->GetWindow()->GetParentTarget();
6530 if (!piTarget) {
6531 return NS_ERROR_INVALID_ARG;
6532 }
6533
6534 ErrorResult err;
6535 RefPtr<Event> event =
6536 GetEventWithTarget(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
6537 Composed::eDefault, Trusted::eYes, err);
6538 if (err.Failed()) {
6539 return err.StealNSResult();
6540 }
6541
6542 bool defaultActionEnabled =
6543 piTarget->DispatchEvent(*event, CallerType::System, err);
6544 if (aDefaultAction) {
6545 *aDefaultAction = defaultActionEnabled;
6546 }
6547 return err.StealNSResult();
6548}
6549
6550void nsContentUtils::RequestFrameFocus(Element& aFrameElement, bool aCanRaise,
6551 CallerType aCallerType) {
6552 RefPtr<Element> target = &aFrameElement;
6553 bool defaultAction = true;
6554 if (aCanRaise) {
6555 RefPtr<Document> doc = target->OwnerDoc();
6556 DispatchEventOnlyToChrome(doc, target, u"framefocusrequested"_ns,
6557 CanBubble::eYes, Cancelable::eYes,
6558 &defaultAction);
6559 }
6560 if (!defaultAction) {
6561 return;
6562 }
6563
6564 RefPtr<nsFocusManager> fm = nsFocusManager::GetFocusManager();
6565 if (!fm) {
6566 return;
6567 }
6568
6569 uint32_t flags = nsIFocusManager::FLAG_NOSCROLL;
6570 if (aCanRaise) {
6571 flags |= nsIFocusManager::FLAG_RAISE;
6572 }
6573
6574 if (aCallerType == CallerType::NonSystem) {
6575 flags |= nsIFocusManager::FLAG_NONSYSTEMCALLER;
6576 }
6577
6578 fm->SetFocus(target, flags);
6579}
6580
6581nsresult nsContentUtils::DispatchEventOnlyToChrome(
6582 Document* aDoc, EventTarget* aTarget, const nsAString& aEventName,
6583 CanBubble aCanBubble, Cancelable aCancelable, Composed aComposed,
6584 bool* aDefaultAction) {
6585 return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
6586 aComposed, Trusted::eYes, aDefaultAction,
6587 ChromeOnlyDispatch::eYes);
6588}
6589
6590/* static */
6591Element* nsContentUtils::MatchElementId(nsIContent* aContent,
6592 const nsAtom* aId) {
6593 for (nsIContent* cur = aContent; cur; cur = cur->GetNextNode(aContent)) {
6594 if (aId == cur->GetID()) {
6595 return cur->AsElement();
6596 }
6597 }
6598
6599 return nullptr;
6600}
6601
6602/* static */
6603Element* nsContentUtils::MatchElementId(nsIContent* aContent,
6604 const nsAString& aId) {
6605 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"
, 6605); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aId.IsEmpty()"
") (" "Will match random elements" ")"); do { MOZ_CrashSequence
(__null, 6605); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6606
6607 // ID attrs are generally stored as atoms, so just atomize this up front
6608 RefPtr<nsAtom> id(NS_Atomize(aId));
6609 if (!id) {
6610 // OOM, so just bail
6611 return nullptr;
6612 }
6613
6614 return MatchElementId(aContent, id);
6615}
6616
6617/* static */
6618void nsContentUtils::RegisterShutdownObserver(nsIObserver* aObserver) {
6619 nsCOMPtr<nsIObserverService> observerService =
6620 mozilla::services::GetObserverService();
6621 if (observerService) {
6622 observerService->AddObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown",
6623 false);
6624 }
6625}
6626
6627/* static */
6628void nsContentUtils::UnregisterShutdownObserver(nsIObserver* aObserver) {
6629 nsCOMPtr<nsIObserverService> observerService =
6630 mozilla::services::GetObserverService();
6631 if (observerService) {
6632 observerService->RemoveObserver(aObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID"xpcom-shutdown");
6633 }
6634}
6635
6636/* static */
6637bool nsContentUtils::HasNonEmptyAttr(const nsIContent* aContent,
6638 int32_t aNameSpaceID, nsAtom* aName) {
6639 static AttrArray::AttrValuesArray strings[] = {nsGkAtoms::_empty, nullptr};
6640 return aContent->IsElement() &&
6641 aContent->AsElement()->FindAttrValueIn(aNameSpaceID, aName, strings,
6642 eCaseMatters) ==
6643 AttrArray::ATTR_VALUE_NO_MATCH;
6644}
6645
6646void nsContentUtils::NotifyDevToolsOfNodeRemoval(nsINode& aRemovingNode) {
6647 // Having an explicit check here since it's an easy mistake to fall into,
6648 // and there might be existing code with problems. We'd rather be safe
6649 // than fire a chrome only event in all corner cases. We also rely on it for
6650 // nsAutoScriptBlockerSuppressNodeRemoved.
6651 if (!IsSafeToRunScript()) {
6652 // This checks that IsSafeToRunScript is true since we don't want to fire
6653 // events when that is false. We can't rely on EventDispatcher to assert
6654 // this in this situation since most of the time DevTools is not observing
6655 // the mutations, in which case we won't even attempt to dispatch events.
6656 // However this also allows for two exceptions. First off, we don't assert
6657 // if the mutation happens to native anonymous content since we never fire
6658 // mutation events on such content anyway.
6659 // Second, we don't assert if sDOMNodeRemovedSuppressCount is true since
6660 // that is a know case when we'd normally fire a mutation event, but can't
6661 // make that safe and so we suppress it at this time. Ideally this should
6662 // go away eventually.
6663 if (!aRemovingNode.IsInNativeAnonymousSubtree() &&
6664 !sDOMNodeRemovedSuppressCount) {
6665 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",
6666); MOZ_PretendNoReturn(); } while (0)
6666 "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",
6666); MOZ_PretendNoReturn(); } while (0)
;
6667 WarnScriptWasIgnored(aRemovingNode.OwnerDoc());
6668 }
6669 return;
6670 }
6671
6672 if (MOZ_UNLIKELY(aRemovingNode.DevToolsShouldBeNotifiedOfThisRemoval())(__builtin_expect(!!(aRemovingNode.DevToolsShouldBeNotifiedOfThisRemoval
()), 0))
) {
6673 const RefPtr<Document> doc = aRemovingNode.OwnerDoc();
6674 DispatchChromeEvent(doc, &aRemovingNode, u"devtoolschildremoved"_ns,
6675 CanBubble::eNo, Cancelable::eNo);
6676 }
6677}
6678
6679void nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments() {
6680 for (EventListenerManager& mgr : sNodeEventListenerManagers) {
6681 nsINode* n = static_cast<nsINode*>(mgr.GetTarget());
6682 if (n && n->IsInComposedDoc() &&
6683 nsCCUncollectableMarker::InGeneration(
6684 n->OwnerDoc()->GetMarkedCCGeneration())) {
6685 mgr.MarkForCC();
6686 }
6687 }
6688}
6689
6690/* static */
6691void nsContentUtils::AddNodeListenerManager(EventListenerManager* aManager) {
6692 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", 6692); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 6692); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6693 sNodeEventListenerManagers.pushBack(aManager);
6694}
6695
6696/* static */
6697void nsContentUtils::RemoveNodeListenerManager(EventListenerManager* aManager) {
6698 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", 6698); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 6698); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6699 // ~EventListenerManager passes here managers which are not in the list.
6700 if (sNodeEventListenerManagers.ElementProbablyInList(aManager)) {
6701 sNodeEventListenerManagers.remove(aManager);
6702 }
6703}
6704
6705void nsContentUtils::AddEntryToDOMArenaTable(nsINode* aNode,
6706 DOMArena* aDOMArena) {
6707 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"
, 6707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sDOMArenaHashtable->Contains(aNode)"
")"); do { MOZ_CrashSequence(__null, 6707); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6708 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", 6708); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aNode->HasFlag(NODE_KEEPS_DOMARENA)" ")"
); do { MOZ_CrashSequence(__null, 6708); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6709 if (!sDOMArenaHashtable) {
6710 sDOMArenaHashtable =
6711 new nsRefPtrHashtable<nsPtrHashKey<const nsINode>, dom::DOMArena>();
6712 }
6713 aNode->SetFlags(NODE_KEEPS_DOMARENA);
6714 sDOMArenaHashtable->InsertOrUpdate(aNode, RefPtr<DOMArena>(aDOMArena));
6715}
6716
6717DOMArena* nsContentUtils::GetEntryFromDOMArenaTable(const nsINode* aNode) {
6718 if (!sDOMArenaHashtable) {
6719 return nullptr;
6720 }
6721 return sDOMArenaHashtable->MaybeGet(aNode).valueOr(nullptr);
6722}
6723
6724already_AddRefed<DOMArena> nsContentUtils::TakeEntryFromDOMArenaTable(
6725 const nsINode* aNode) {
6726 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", 6726); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "sDOMArenaHashtable->Contains(aNode)" ")"
); do { MOZ_CrashSequence(__null, 6726); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6727 RefPtr<DOMArena> arena;
6728 sDOMArenaHashtable->Remove(aNode, getter_AddRefs(arena));
6729 return arena.forget();
6730}
6731
6732/* static */
6733bool nsContentUtils::IsValidNodeName(nsAtom* aLocalName, nsAtom* aPrefix,
6734 int32_t aNamespaceID) {
6735 if (aNamespaceID == kNameSpaceID_Unknown-1) {
6736 return false;
6737 }
6738
6739 if (!aPrefix) {
6740 // If the prefix is null, then either the QName must be xmlns or the
6741 // namespace must not be XMLNS.
6742 return (aLocalName == nsGkAtoms::xmlns) ==
6743 (aNamespaceID == kNameSpaceID_XMLNS1);
6744 }
6745
6746 // If the prefix is non-null then the namespace must not be null.
6747 if (aNamespaceID == kNameSpaceID_None) {
6748 return false;
6749 }
6750
6751 // If the namespace is the XMLNS namespace then the prefix must be xmlns,
6752 // but the localname must not be xmlns.
6753 if (aNamespaceID == kNameSpaceID_XMLNS1) {
6754 return aPrefix == nsGkAtoms::xmlns && aLocalName != nsGkAtoms::xmlns;
6755 }
6756
6757 // If the namespace is not the XMLNS namespace then the prefix must not be
6758 // xmlns.
6759 // If the namespace is the XML namespace then the prefix can be anything.
6760 // If the namespace is not the XML namespace then the prefix must not be xml.
6761 return aPrefix != nsGkAtoms::xmlns &&
6762 (aNamespaceID == kNameSpaceID_XML2 || aPrefix != nsGkAtoms::xml);
6763}
6764
6765already_AddRefed<DocumentFragment> nsContentUtils::CreateContextualFragment(
6766 nsINode* aContextNode, const nsAString& aFragment,
6767 bool aPreventScriptExecution,
6768 Maybe<RefPtr<CustomElementRegistry>> aCustomElementRegistry,
6769 ErrorResult& aRv) {
6770 if (!aContextNode) {
6771 aRv.Throw(NS_ERROR_INVALID_ARG);
6772 return nullptr;
6773 }
6774
6775 // If we don't have a document here, we can't get the right security context
6776 // for compiling event handlers... so just bail out.
6777 RefPtr<Document> document = aContextNode->OwnerDoc();
6778 bool isHTML = document->IsHTMLDocument();
6779
6780 if (isHTML) {
6781 RefPtr<DocumentFragment> frag = new (document->NodeInfoManager())
6782 DocumentFragment(document->NodeInfoManager());
6783
6784 Element* element = aContextNode->GetAsElementOrParentElement();
6785 if (element && !element->IsHTMLElement(nsGkAtoms::html)) {
6786 aRv = ParseFragmentHTML(
6787 aFragment, frag, element->NodeInfo()->NameAtom(),
6788 element->GetNameSpaceID(),
6789 (document->GetCompatibilityMode() == eCompatibility_NavQuirks),
6790 aPreventScriptExecution, kParseFragmentPrivilegedDefaultSanitization,
6791 std::move(aCustomElementRegistry));
6792 } else {
6793 aRv = ParseFragmentHTML(
6794 aFragment, frag, nsGkAtoms::body, kNameSpaceID_XHTML3,
6795 (document->GetCompatibilityMode() == eCompatibility_NavQuirks),
6796 aPreventScriptExecution, kParseFragmentPrivilegedDefaultSanitization,
6797 std::move(aCustomElementRegistry));
6798 }
6799
6800 return frag.forget();
6801 }
6802
6803 AutoTArray<nsString, 32> tagStack;
6804 nsAutoString uriStr, nameStr;
6805 for (Element* element : aContextNode->InclusiveAncestorsOfType<Element>()) {
6806 nsString& tagName = *tagStack.AppendElement();
6807 // It mostly doesn't actually matter what tag name we use here: XML doesn't
6808 // have parsing that depends on the open tag stack, apart from namespace
6809 // declarations. So this whole tagStack bit is just there to get the right
6810 // namespace declarations to the XML parser. That said, the parser _is_
6811 // going to create elements with the tag names we provide here, so we need
6812 // to make sure they are not names that can trigger custom element
6813 // constructors. Just make up a name that is never going to be a valid
6814 // custom element name.
6815 //
6816 // The principled way to do this would probably be to add a new FromParser
6817 // value and make sure we use it when creating the context elements, then
6818 // make sure we teach all FromParser consumers (and in particular the custom
6819 // element code) about it as needed. But right now the XML parser never
6820 // actually uses FromParser values other than NOT_FROM_PARSER, and changing
6821 // that is pretty complicated.
6822 tagName.AssignLiteral("notacustomelement");
6823
6824 // see if we need to add xmlns declarations
6825 uint32_t count = element->GetAttrCount();
6826 bool setDefaultNamespace = false;
6827 if (count > 0) {
6828 uint32_t index;
6829
6830 for (index = 0; index < count; index++) {
6831 const BorrowedAttrInfo info = element->GetAttrInfoAt(index);
6832 const nsAttrName* name = info.mName;
6833 if (name->NamespaceEquals(kNameSpaceID_XMLNS1)) {
6834 info.mValue->ToString(uriStr);
6835
6836 // really want something like nsXMLContentSerializer::SerializeAttr
6837 tagName.AppendLiteral(" xmlns"); // space important
6838 if (name->GetPrefix()) {
6839 tagName.Append(char16_t(':'));
6840 name->LocalName()->ToString(nameStr);
6841 tagName.Append(nameStr);
6842 } else {
6843 setDefaultNamespace = true;
6844 }
6845 tagName.AppendLiteral(R"(=")");
6846 tagName.Append(uriStr);
6847 tagName.Append('"');
6848 }
6849 }
6850 }
6851
6852 if (!setDefaultNamespace) {
6853 mozilla::dom::NodeInfo* info = element->NodeInfo();
6854 if (!info->GetPrefixAtom() && info->NamespaceID() != kNameSpaceID_None) {
6855 // We have no namespace prefix, but have a namespace ID. Push
6856 // default namespace attr in, so that our kids will be in our
6857 // namespace.
6858 info->GetNamespaceURI(uriStr);
6859 tagName.AppendLiteral(R"( xmlns=")");
6860 tagName.Append(uriStr);
6861 tagName.Append('"');
6862 }
6863 }
6864 }
6865
6866 RefPtr<DocumentFragment> frag;
6867 aRv = ParseFragmentXML(aFragment, document, tagStack, aPreventScriptExecution,
6868 kParseFragmentPrivilegedDefaultSanitization,
6869 getter_AddRefs(frag));
6870 return frag.forget();
6871}
6872
6873/* static */
6874void nsContentUtils::DropFragmentParsers() {
6875 NS_IF_RELEASE(sHTMLFragmentParser)do { if (sHTMLFragmentParser) { (sHTMLFragmentParser)->Release
(); (sHTMLFragmentParser) = 0; } } while (0)
;
6876 NS_IF_RELEASE(sXMLFragmentParser)do { if (sXMLFragmentParser) { (sXMLFragmentParser)->Release
(); (sXMLFragmentParser) = 0; } } while (0)
;
6877 NS_IF_RELEASE(sXMLFragmentSink)do { if (sXMLFragmentSink) { (sXMLFragmentSink)->Release()
; (sXMLFragmentSink) = 0; } } while (0)
;
6878}
6879
6880/* static */
6881void nsContentUtils::XPCOMShutdown() { nsContentUtils::DropFragmentParsers(); }
6882
6883// https://wicg.github.io/sanitizer-api/#set-and-filter-html
6884static void SetAndFilterHTML(
6885 FragmentOrElement* aTarget, Element* aContext, const nsAString& aHTML,
6886 const OwningSanitizerOrSanitizerConfigOrSanitizerPresets& aSanitizerOptions,
6887 const bool aSafe, ErrorResult& aError) {
6888 const RefPtr<Document> doc = aTarget->OwnerDoc();
6889
6890 // Step 1. If safe and contextElement’s local name is "script" and
6891 // contextElement’s namespace is the HTML namespace or the SVG namespace, then
6892 // return.
6893 if (aSafe && (aContext->IsHTMLElement(nsGkAtoms::script) ||
6894 aContext->IsSVGElement(nsGkAtoms::script))) {
6895 nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "DOM"_ns, doc,
6896 PropertiesFile::DOM_PROPERTIES,
6897 "SetHTMLScript");
6898 return;
6899 }
6900
6901 // Step 2. Let sanitizer be the result of calling get a sanitizer instance
6902 // from options with options and safe.
6903 nsCOMPtr<nsIGlobalObject> global = aTarget->GetRelevantGlobal();
6904 if (!global) {
6905 aError.ThrowInvalidStateError("Missing owner global.");
6906 return;
6907 }
6908 RefPtr<Sanitizer> sanitizer =
6909 Sanitizer::GetInstance(global, aSanitizerOptions, aSafe, aError);
6910 if (aError.Failed()) {
6911 return;
6912 }
6913
6914 aTarget->NotifyDevToolsOfRemovalsOfChildren();
6915
6916 // Needed when innerHTML is used in combination with contenteditable
6917 mozAutoDocUpdate updateBatch(doc, true);
6918
6919 // Remove childnodes.
6920 nsAutoMutationBatch mb(aTarget, true, false);
6921 aTarget->RemoveAllChildren(true);
6922 mb.RemovalDone();
6923
6924 nsAutoScriptLoaderDisabler sld(doc);
6925
6926 // Step 3. Let newChildren be the result of the HTML fragment parsing
6927 // algorithm steps given contextElement, html, and true.
6928 // Step 4. Let fragment be a new DocumentFragment whose node document is
6929 // contextElement’s node document.
6930 // Step 5. For each node in newChildren, append node to fragment.
6931
6932 // We MUST NOT cause any requests during parsing, so we'll
6933 // create an inert Document and parse into a new DocumentFragment.
6934
6935 RefPtr<Document> inertDoc = nsContentUtils::CreateInertHTMLDocument(doc);
6936 if (!inertDoc) {
6937 aError = NS_ERROR_FAILURE;
6938 return;
6939 }
6940
6941 RefPtr<DocumentFragment> fragment = new (inertDoc->NodeInfoManager())
6942 DocumentFragment(inertDoc->NodeInfoManager());
6943
6944 nsAtom* contextLocalName = aContext->NodeInfo()->NameAtom();
6945 int32_t contextNameSpaceID = aContext->GetNameSpaceID();
6946 int32_t flags =
6947 aSafe ? nsContentUtils::kParseFragmentNoSanitization
6948 : nsContentUtils::kParseFragmentPrivilegedDefaultSanitization;
6949 aError = nsContentUtils::ParseFragmentHTML(
6950 aHTML, fragment, contextLocalName, contextNameSpaceID,
6951 /* aQuirks */ false, /* aPreventScriptExecution */ true, flags,
6952 mozilla::Nothing());
6953 if (aError.Failed()) {
6954 return;
6955 }
6956
6957 // Suppress assertion about node removal mutation events that can't have
6958 // listeners anyway, because no one has had the chance to register
6959 // mutation listeners on the fragment that comes from the parser.
6960 nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
6961
6962 // Step 6. Run sanitize on fragment using sanitizer and safe.
6963 sanitizer->Sanitize(fragment, aSafe, aError);
6964 if (aError.Failed()) {
6965 return;
6966 }
6967
6968 // Step 7. Replace all with fragment within target.
6969 aTarget->AppendChild(*fragment, aError);
6970 if (aError.Failed()) {
6971 return;
6972 }
6973
6974 mb.NodesAdded();
6975}
6976
6977/* static */
6978void nsContentUtils::SetHTML(FragmentOrElement* aTarget, Element* aContext,
6979 const nsAString& aHTML,
6980 const SetHTMLOptions& aOptions,
6981 ErrorResult& aError) {
6982 SetAndFilterHTML(aTarget, aContext, aHTML, aOptions.mSanitizer,
6983 /* aSafe */ true, aError);
6984}
6985
6986/* https://html.spec.whatwg.org/#unsafely-set-html */
6987/* https://html.spec.whatwg.org/#dom-shadowroot-sethtmlunsafe */
6988/* https://html.spec.whatwg.org/#dom-element-sethtmlunsafe */
6989/* static */
6990void nsContentUtils::SetHTMLUnsafe(
6991 FragmentOrElement* aTarget, Element* aContext,
6992 const TrustedHTMLOrString& aSource, const SetHTMLUnsafeOptions& aOptions,
6993 bool aIsShadowRoot, nsIPrincipal* aSubjectPrincipal, ErrorResult& aError) {
6994 // Element's setHTMLUnsafe() step 1 / ShadowRoot's setHTMLUnsafe() step 1.
6995 // "Let compliantHTML be the result of invoking the get trusted type compliant
6996 // string algorithm with TrustedHTML, this's relevant global object, html,
6997 // «Element setHTMLUnsafe» or «ShadowRoot setHTMLUnsafe», and «script»."
6998 constexpr nsLiteralString elementSink = u"Element setHTMLUnsafe"_ns;
6999 constexpr nsLiteralString shadowRootSink = u"ShadowRoot setHTMLUnsafe"_ns;
7000 Maybe<nsAutoString> compliantStringHolder;
7001 const nsAString* compliantString =
7002 TrustedTypeUtils::GetTrustedTypesCompliantString(
7003 aSource, aIsShadowRoot ? shadowRootSink : elementSink,
7004 kTrustedTypesOnlySinkGroup, *aContext, aSubjectPrincipal,
7005 compliantStringHolder, aError);
7006 if (aError.Failed()) {
7007 return;
7008 }
7009
7010 // Fallback to the more optimized code below without a sanitizer.
7011 if (aOptions.mSanitizer.WasPassed()) {
7012 return SetAndFilterHTML(aTarget, aContext, *compliantString,
7013 aOptions.mSanitizer.Value(), /* aSafe */ false,
7014 aError);
7015 }
7016
7017 RefPtr<DocumentFragment> fragment;
7018 {
7019 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"
, 7020); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sFragmentParsingActive"
") (" "Re-entrant fragment parsing attempted." ")"); do { MOZ_CrashSequence
(__null, 7020); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
7020 "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"
, 7020); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!sFragmentParsingActive"
") (" "Re-entrant fragment parsing attempted." ")"); do { MOZ_CrashSequence
(__null, 7020); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7021 mozilla::AutoRestore<bool> guard(sFragmentParsingActive);
7022 sFragmentParsingActive = true;
7023 if (!sHTMLFragmentParser) {
7024 NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef(
)
;
7025 // Now sHTMLFragmentParser owns the object
7026 }
7027
7028 nsAtom* contextLocalName = aContext->NodeInfo()->NameAtom();
7029 int32_t contextNameSpaceID = aContext->GetNameSpaceID();
7030
7031 // https://html.spec.whatwg.org/#html-fragment-parsing-algorithm
7032 // 11. Let root be the result of creating an element given document,
7033 // 'html', the HTML namespace, null, null, false, and context's
7034 // custom element registry.
7035 Maybe<RefPtr<CustomElementRegistry>> customElementRegistry;
7036 if (StaticPrefs::dom_scoped_custom_element_registries_enabled()) {
7037 customElementRegistry.emplace(aContext->GetCustomElementRegistry());
7038 }
7039
7040 RefPtr<Document> doc = aTarget->OwnerDoc();
7041 fragment = doc->CreateDocumentFragment();
7042
7043 // XXX: Steps 1-3 are performed together by ParseFragment, which parses
7044 // directly into the DocumentFragment.
7045 nsresult rv = sHTMLFragmentParser->ParseFragment(
7046 *compliantString, fragment, contextLocalName, contextNameSpaceID,
7047 fragment->OwnerDoc()->GetCompatibilityMode() ==
7048 eCompatibility_NavQuirks,
7049 true, true, std::move(customElementRegistry));
7050 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7051 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",
7051)
;
7052 }
7053 }
7054
7055 // Step 4. "Replace all with fragment within target."
7056 aTarget->ReplaceChildren(fragment, IgnoreErrors());
7057}
7058
7059// We sanitize if the fragment occurs in a system privileged
7060// context, an about: page, or if there are explicit sanitization flags.
7061// Please note that about:blank and about:srcdoc inherit the security
7062// context from the embedding context and hence are not loaded using
7063// an about: scheme principal.
7064bool ShouldSanitize(nsIPrincipal* aPrincipal, int32_t aFlags) {
7065 // We don't need to sanitize for setHTML(), which uses
7066 // kParseFragmentNoSanitization.
7067 if (aFlags == nsContentUtils::kParseFragmentNoSanitization) {
7068 return false;
7069 }
7070
7071 if (aFlags >= 0) {
7072 return true;
7073 }
7074
7075 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", 7076); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization"
")"); do { MOZ_CrashSequence(__null, 7076); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7076 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", 7076); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization"
")"); do { MOZ_CrashSequence(__null, 7076); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7077 return aPrincipal->IsSystemPrincipal() || aPrincipal->SchemeIs("about");
7078}
7079
7080// Helper function to compuate Sanitization Flags for ParseFramentHTML/XML
7081uint32_t ComputeSanitizationFlags(nsIPrincipal* aPrincipal, int32_t aFlags) {
7082 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", 7084); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0"
")"); do { MOZ_CrashSequence(__null, 7084); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7083 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", 7084); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0"
")"); do { MOZ_CrashSequence(__null, 7084); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7084 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", 7084); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization || aFlags >= 0"
")"); do { MOZ_CrashSequence(__null, 7084); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7085
7086 if (aPrincipal->IsSystemPrincipal() || aPrincipal->SchemeIs("about")) {
7087 if (aFlags == nsContentUtils::kParseFragmentPrivilegedDefaultSanitization) {
7088 // If this is a chrome-privileged document and no explicit flags
7089 // were passed, then use these sanitization flags.
7090 return nsIParserUtils::SanitizerAllowStyle |
7091 nsIParserUtils::SanitizerAllowComments |
7092 // Don't drop forms in about: to avoid breaking existing users
7093 (aPrincipal->IsSystemPrincipal()
7094 ? nsIParserUtils::SanitizerDropForms
7095 : 0) |
7096 nsIParserUtils::SanitizerLogRemovals;
7097 }
7098
7099 // If the caller explicitly passes flags, then we use those
7100 // flags but additionally drop forms.
7101 return aFlags | nsIParserUtils::SanitizerDropForms;
7102 }
7103
7104 if (aFlags >= 0) {
7105 // aFlags by default is -1 and is only ever non equal to -1 if the
7106 // caller of ParseFragmentHTML/ParseFragmentXML is
7107 // ParserUtils::ParseFragment(). Only in that case we should use
7108 // the sanitization flags passed within aFlags.
7109 return aFlags;
7110 }
7111
7112 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"
, 7112); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "We should have explicit flags" ")"
); do { MOZ_CrashSequence(__null, 7112); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7113 return 0;
7114}
7115
7116/* https://html.spec.whatwg.org/#html-fragment-parsing-algorithm */
7117/* static */
7118nsresult nsContentUtils::ParseFragmentHTML(
7119 const nsAString& aSourceBuffer, nsIContent* aTargetNode,
7120 nsAtom* aContextLocalName, int32_t aContextNamespace, bool aQuirks,
7121 bool aPreventScriptExecution, int32_t aFlags,
7122 mozilla::Maybe<RefPtr<mozilla::dom::CustomElementRegistry>>
7123 aCustomElementRegistry) {
7124 if (nsContentUtils::sFragmentParsingActive) {
7125 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"
, 7125); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted."
")"); do { MOZ_CrashSequence(__null, 7125); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7126 return NS_ERROR_DOM_INVALID_STATE_ERR;
7127 }
7128 mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
7129 nsContentUtils::sFragmentParsingActive = true;
7130 if (!sHTMLFragmentParser) {
7131 NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef(
)
;
7132 // Now sHTMLFragmentParser owns the object
7133 }
7134
7135 nsCOMPtr<nsIPrincipal> nodePrincipal = aTargetNode->NodePrincipal();
7136
7137#ifdef DEBUG1
7138 // aFlags should always be kParseFragmentPrivilegedDefaultSanitization unless
7139 // the caller of ParseFragmentHTML is ParserUtils::ParseFragment() which is
7140 // the only caller that intends sanitization. For all other callers we need to
7141 // ensure to call AuditParsingOfHTMLXMLFragments.
7142 //
7143 // For SetHTML the flag is kParseFragmentNoSanitization, because that function
7144 // already sanitizes.
7145 if (aFlags == kParseFragmentPrivilegedDefaultSanitization) {
7146 DOMSecurityMonitor::AuditParsingOfHTMLXMLFragments(nodePrincipal,
7147 aSourceBuffer);
7148 }
7149#endif
7150
7151 nsIContent* target = aTargetNode;
7152
7153 RefPtr<Document> doc = aTargetNode->OwnerDoc();
7154 RefPtr<DocumentFragment> fragment;
7155
7156 if (ShouldSanitize(nodePrincipal, aFlags)) {
7157 if (!doc->IsLoadedAsData()) {
7158 doc = nsContentUtils::CreateInertHTMLDocument(doc);
7159 if (!doc) {
7160 return NS_ERROR_FAILURE;
7161 }
7162 }
7163 fragment =
7164 new (doc->NodeInfoManager()) DocumentFragment(doc->NodeInfoManager());
7165 target = fragment;
7166 }
7167
7168 nsresult rv = sHTMLFragmentParser->ParseFragment(
7169 aSourceBuffer, target, aContextLocalName, aContextNamespace, aQuirks,
7170 aPreventScriptExecution, false, std::move(aCustomElementRegistry));
7171 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"
, 7171); return rv; } } while (false)
;
7172
7173 if (fragment) {
7174 uint32_t sanitizationFlags =
7175 ComputeSanitizationFlags(nodePrincipal, aFlags);
7176 // Don't fire mutation events for nodes removed by the sanitizer.
7177 nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
7178 nsTreeSanitizer sanitizer(sanitizationFlags);
7179 sanitizer.Sanitize(fragment);
7180
7181 ErrorResult error;
7182 aTargetNode->AppendChild(*fragment, error);
7183 rv = error.StealNSResult();
7184 }
7185
7186 return rv;
7187}
7188
7189/* static */
7190nsresult nsContentUtils::ParseDocumentHTML(
7191 const nsAString& aSourceBuffer, Document* aTargetDocument,
7192 bool aScriptingEnabledForNoscriptParsing) {
7193 if (nsContentUtils::sFragmentParsingActive) {
7194 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"
, 7194); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted."
")"); do { MOZ_CrashSequence(__null, 7194); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7195 return NS_ERROR_DOM_INVALID_STATE_ERR;
7196 }
7197 mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
7198 nsContentUtils::sFragmentParsingActive = true;
7199 if (!sHTMLFragmentParser) {
7200 NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser())(sHTMLFragmentParser = new nsHtml5StringParser())->AddRef(
)
;
7201 // Now sHTMLFragmentParser owns the object
7202 }
7203 nsresult rv = sHTMLFragmentParser->ParseDocument(
7204 aSourceBuffer, aTargetDocument, aScriptingEnabledForNoscriptParsing);
7205 return rv;
7206}
7207
7208/* static */
7209nsresult nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer,
7210 Document* aDocument,
7211 nsTArray<nsString>& aTagStack,
7212 bool aPreventScriptExecution,
7213 int32_t aFlags,
7214 DocumentFragment** aReturn) {
7215 if (nsContentUtils::sFragmentParsingActive) {
7216 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"
, 7216); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Re-entrant fragment parsing attempted."
")"); do { MOZ_CrashSequence(__null, 7216); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7217 return NS_ERROR_DOM_INVALID_STATE_ERR;
7218 }
7219 mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
7220 nsContentUtils::sFragmentParsingActive = true;
7221 if (!sXMLFragmentParser) {
7222 RefPtr<nsParser> parser = new nsParser();
7223 parser.forget(&sXMLFragmentParser);
7224 // sXMLFragmentParser now owns the parser
7225 }
7226 if (!sXMLFragmentSink) {
7227 NS_NewXMLFragmentContentSink(&sXMLFragmentSink);
7228 // sXMLFragmentSink now owns the sink
7229 }
7230 nsCOMPtr<nsIContentSink> contentsink = do_QueryInterface(sXMLFragmentSink);
7231 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"
, 7231); AnnotateMozCrashReason("MOZ_ASSERT" "(" "contentsink"
") (" "Sink doesn't QI to nsIContentSink!" ")"); do { MOZ_CrashSequence
(__null, 7231); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7232 sXMLFragmentParser->SetContentSink(contentsink);
7233
7234 RefPtr<Document> doc;
7235 nsCOMPtr<nsIPrincipal> nodePrincipal = aDocument->NodePrincipal();
7236
7237#ifdef DEBUG1
7238 // aFlags should always be kParseFragmentPrivilegedDefaultSanitization unless
7239 // the caller of ParseFragmentXML is ParserUtils::ParseFragment() which is the
7240 // only caller that intends sanitization. For all other callers we need to
7241 // ensure to call AuditParsingOfHTMLXMLFragments.
7242 if (aFlags == kParseFragmentPrivilegedDefaultSanitization) {
7243 DOMSecurityMonitor::AuditParsingOfHTMLXMLFragments(nodePrincipal,
7244 aSourceBuffer);
7245 }
7246#endif
7247
7248 bool shouldSanitize = ShouldSanitize(nodePrincipal, aFlags);
7249 if (shouldSanitize && !aDocument->IsLoadedAsData()) {
7250 doc = nsContentUtils::CreateInertXMLDocument(aDocument);
7251 } else {
7252 doc = aDocument;
7253 }
7254
7255 sXMLFragmentSink->SetTargetDocument(doc);
7256 sXMLFragmentSink->SetPreventScriptExecution(aPreventScriptExecution);
7257
7258 nsresult rv = sXMLFragmentParser->ParseFragment(aSourceBuffer, aTagStack);
7259 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7260 // Drop the fragment parser and sink that might be in an inconsistent state
7261 NS_IF_RELEASE(sXMLFragmentParser)do { if (sXMLFragmentParser) { (sXMLFragmentParser)->Release
(); (sXMLFragmentParser) = 0; } } while (0)
;
7262 NS_IF_RELEASE(sXMLFragmentSink)do { if (sXMLFragmentSink) { (sXMLFragmentSink)->Release()
; (sXMLFragmentSink) = 0; } } while (0)
;
7263 return rv;
7264 }
7265
7266 rv = sXMLFragmentSink->FinishFragmentParsing(aReturn);
7267
7268 sXMLFragmentParser->Reset();
7269 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"
, 7269); return rv; } } while (false)
;
7270
7271 if (shouldSanitize) {
7272 uint32_t sanitizationFlags =
7273 ComputeSanitizationFlags(nodePrincipal, aFlags);
7274 // Don't fire mutation events for nodes removed by the sanitizer.
7275 nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
7276 nsTreeSanitizer sanitizer(sanitizationFlags);
7277 sanitizer.Sanitize(*aReturn);
7278 }
7279
7280 return rv;
7281}
7282
7283/* static */
7284nsresult nsContentUtils::ConvertToPlainText(const nsAString& aSourceBuffer,
7285 nsAString& aResultBuffer,
7286 uint32_t aFlags,
7287 uint32_t aWrapCol) {
7288 RefPtr<Document> document = nsContentUtils::CreateInertHTMLDocument(nullptr);
7289 if (!document) {
7290 return NS_ERROR_FAILURE;
7291 }
7292
7293 nsresult rv = nsContentUtils::ParseDocumentHTML(
7294 aSourceBuffer, document,
7295 !(aFlags & nsIDocumentEncoder::OutputNoScriptContent));
7296 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"
, 7296); return rv; } } while (false)
;
7297
7298 nsCOMPtr<nsIDocumentEncoder> encoder = do_createDocumentEncoder("text/plain");
7299
7300 rv = encoder->Init(document, u"text/plain"_ns, aFlags);
7301 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"
, 7301); return rv; } } while (false)
;
7302
7303 encoder->SetWrapColumn(aWrapCol);
7304
7305 return encoder->EncodeToString(aResultBuffer);
7306}
7307
7308static already_AddRefed<Document> CreateInertDocument(const Document* aTemplate,
7309 DocumentFlavor aFlavor) {
7310 if (aTemplate) {
7311 bool hasHad = true;
7312 nsIScriptGlobalObject* sgo = aTemplate->GetScriptHandlingObject(hasHad);
7313 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",
7313); return nullptr; } } while (false)
;
7314
7315 nsCOMPtr<Document> doc;
7316 nsresult rv = NS_NewDOMDocument(
7317 getter_AddRefs(doc), u""_ns, u""_ns, nullptr,
7318 aTemplate->GetDocumentURI(), aTemplate->GetDocBaseURI(),
7319 aTemplate->NodePrincipal(), LoadedAsData::AsData, sgo, aFlavor);
7320 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7321 return nullptr;
7322 }
7323 return doc.forget();
7324 }
7325 nsCOMPtr<nsIURI> uri;
7326 NS_NewURI(getter_AddRefs(uri), "about:blank"_ns);
7327 if (!uri) {
7328 return nullptr;
7329 }
7330
7331 RefPtr<NullPrincipal> nullPrincipal =
7332 NullPrincipal::CreateWithoutOriginAttributes();
7333 if (!nullPrincipal) {
7334 return nullptr;
7335 }
7336
7337 nsCOMPtr<Document> doc;
7338 nsresult rv =
7339 NS_NewDOMDocument(getter_AddRefs(doc), u""_ns, u""_ns, nullptr, uri, uri,
7340 nullPrincipal, LoadedAsData::AsData, nullptr, aFlavor);
7341 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7342 return nullptr;
7343 }
7344 return doc.forget();
7345}
7346
7347/* static */
7348already_AddRefed<Document> nsContentUtils::CreateInertXMLDocument(
7349 const Document* aTemplate) {
7350 return CreateInertDocument(aTemplate, DocumentFlavor::XML);
7351}
7352
7353/* static */
7354already_AddRefed<Document> nsContentUtils::CreateInertHTMLDocument(
7355 const Document* aTemplate) {
7356 return CreateInertDocument(aTemplate, DocumentFlavor::HTML);
7357}
7358
7359/* static */
7360nsresult nsContentUtils::SetNodeTextContent(
7361 nsIContent* aContent, const nsAString& aValue, bool aTryReuse,
7362 MutationEffectOnScript aMutationEffectOnScript) {
7363 // Optimize the common case of there being no observers
7364 if (MOZ_UNLIKELY((__builtin_expect(!!(aContent->MaybeNeedsToNotifyDevToolsOfNodeRemovalsInOwnerDoc
()), 0))
7365 aContent->MaybeNeedsToNotifyDevToolsOfNodeRemovalsInOwnerDoc())(__builtin_expect(!!(aContent->MaybeNeedsToNotifyDevToolsOfNodeRemovalsInOwnerDoc
()), 0))
) {
7366 if (aTryReuse) {
7367 bool skipFirstText = true;
7368 for (nsCOMPtr<nsINode> child = aContent->GetFirstChild();
7369 child && child->GetParentNode() == aContent;
7370 child = child->GetNextSibling()) {
7371 if (skipFirstText && child->IsText()) {
7372 skipFirstText = false;
7373 continue;
7374 }
7375 nsContentUtils::NotifyDevToolsOfNodeRemoval(*child);
7376 }
7377 } else {
7378 aContent->NotifyDevToolsOfRemovalsOfChildren();
7379 }
7380 }
7381
7382 // Might as well stick a batch around this since we're performing several
7383 // mutations.
7384 mozAutoDocUpdate updateBatch(aContent->GetComposedDoc(), true);
7385 nsAutoMutationBatch mb;
7386
7387 if (aTryReuse && !aValue.IsEmpty()) {
7388 // Let's remove nodes until we find a eTEXT.
7389 while (aContent->HasChildren()) {
7390 nsIContent* child = aContent->GetFirstChild();
7391 if (child->IsText()) {
7392 break;
7393 }
7394 aContent->RemoveChildNode(child, true, nullptr, nullptr,
7395 aMutationEffectOnScript);
7396 }
7397
7398 // If we have a node, it must be a eTEXT and we reuse it.
7399 if (aContent->HasChildren()) {
7400 nsIContent* child = aContent->GetFirstChild();
7401 nsresult rv = child->AsText()->SetText(aValue, true);
7402 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"
, 7402); return rv; } } while (false)
;
7403
7404 // All the following nodes, if they exist, must be deleted.
7405 while (nsIContent* lastChild = aContent->GetLastChild()) {
7406 if (lastChild == child) {
7407 break;
7408 }
7409 aContent->RemoveChildNode(lastChild, true, nullptr, nullptr,
7410 aMutationEffectOnScript);
7411 }
7412 }
7413
7414 if (aContent->HasChildren()) {
7415 return NS_OK;
7416 }
7417 } else {
7418 mb.Init(aContent, true, false);
7419 aContent->RemoveAllChildren(true);
7420 }
7421 mb.RemovalDone();
7422
7423 if (aValue.IsEmpty()) {
7424 return NS_OK;
7425 }
7426
7427 RefPtr<nsTextNode> textContent = new (aContent->NodeInfo()->NodeInfoManager())
7428 nsTextNode(aContent->NodeInfo()->NodeInfoManager());
7429
7430 textContent->SetText(aValue, true);
7431
7432 ErrorResult rv;
7433 aContent->AppendChildTo(textContent, true, rv, aMutationEffectOnScript);
7434 mb.NodesAdded();
7435 return rv.StealNSResult();
7436}
7437
7438template <typename CharT>
7439static bool AppendNodeTextContentsRecurse(const nsINode* aNode,
7440 nsTSubstring<CharT>& aResult,
7441 const fallible_t& aFallible) {
7442 for (nsIContent* child = aNode->GetFirstChild(); child;
7443 child = child->GetNextSibling()) {
7444 if (child->IsElement()) {
7445 if (!AppendNodeTextContentsRecurse(child, aResult, aFallible)) {
7446 return false;
7447 }
7448 } else if (Text* text = child->GetAsText()) {
7449 if (!text->AppendTextTo(aResult, aFallible)) {
7450 return false;
7451 }
7452 }
7453 }
7454 return true;
7455}
7456
7457template <typename CharT>
7458static bool AppendNodeTextContent(const nsINode* aNode, bool aDeep,
7459 nsTSubstring<CharT>& aResult,
7460 const fallible_t& aFallible) {
7461 if (const Text* text = aNode->GetAsText()) {
7462 return text->AppendTextTo(aResult, aFallible);
7463 }
7464 if (aDeep) {
7465 return AppendNodeTextContentsRecurse(aNode, aResult, aFallible);
7466 }
7467 for (nsIContent* child = aNode->GetFirstChild(); child;
7468 child = child->GetNextSibling()) {
7469 if (Text* text = child->GetAsText()) {
7470 bool ok = text->AppendTextTo(aResult, fallible);
7471 if (!ok) {
7472 return false;
7473 }
7474 }
7475 }
7476 return true;
7477}
7478
7479/* static */
7480bool nsContentUtils::AppendNodeTextContent(const nsINode* aNode, bool aDeep,
7481 nsAString& aResult,
7482 const fallible_t& aFallible) {
7483 return ::AppendNodeTextContent(aNode, aDeep, aResult, aFallible);
7484}
7485
7486bool nsContentUtils::AppendNodeTextContent(const nsINode* aNode, bool aDeep,
7487 nsACString& aResult,
7488 const fallible_t& aFallible) {
7489 return ::AppendNodeTextContent(aNode, aDeep, aResult, aFallible);
7490}
7491
7492bool nsContentUtils::HasNonEmptyTextContent(
7493 nsINode* aNode, TextContentDiscoverMode aDiscoverMode) {
7494 for (nsIContent* child = aNode->GetFirstChild(); child;
7495 child = child->GetNextSibling()) {
7496 if (child->IsText() && child->TextLength() > 0) {
7497 return true;
7498 }
7499
7500 if (aDiscoverMode == eRecurseIntoChildren &&
7501 HasNonEmptyTextContent(child, aDiscoverMode)) {
7502 return true;
7503 }
7504 }
7505
7506 return false;
7507}
7508
7509/* static */
7510bool nsContentUtils::IsInSameAnonymousTree(const nsINode* aNode,
7511 const nsINode* aOtherNode) {
7512 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", 7512
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode" ") (" "Must have a node to work with"
")"); do { MOZ_CrashSequence(__null, 7512); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7513 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", 7513
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOtherNode" ") ("
"Must have a content to work with" ")"); do { MOZ_CrashSequence
(__null, 7513); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7514
7515 const bool anon = aNode->IsInNativeAnonymousSubtree();
7516 if (anon != aOtherNode->IsInNativeAnonymousSubtree()) {
7517 return false;
7518 }
7519
7520 if (anon) {
7521 return aOtherNode->GetClosestNativeAnonymousSubtreeRoot() ==
7522 aNode->GetClosestNativeAnonymousSubtreeRoot();
7523 }
7524
7525 // FIXME: This doesn't deal with disconnected nodes whatsoever, but it didn't
7526 // use to either. Maybe that's fine.
7527 return aNode->GetContainingShadow() == aOtherNode->GetContainingShadow();
7528}
7529
7530/* static */
7531bool nsContentUtils::IsInInteractiveHTMLContent(const Element* aElement,
7532 const Element* aStop) {
7533 const Element* element = aElement;
7534 while (element && element != aStop) {
7535 if (element->IsInteractiveHTMLContent()) {
7536 return true;
7537 }
7538 element = element->GetFlattenedTreeParentElement();
7539 }
7540 return false;
7541}
7542
7543/* static */
7544void nsContentUtils::NotifyInstalledMenuKeyboardListener(bool aInstalling) {
7545 IMEStateManager::OnInstalledMenuKeyboardListener(aInstalling);
7546}
7547
7548/* static */
7549bool nsContentUtils::SchemeIs(nsIURI* aURI, const char* aScheme) {
7550 nsCOMPtr<nsIURI> baseURI = NS_GetInnermostURI(aURI);
7551 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", 7551); return
false; } } while (false)
;
7552 return baseURI->SchemeIs(aScheme);
7553}
7554
7555bool nsContentUtils::IsExpandedPrincipal(nsIPrincipal* aPrincipal) {
7556 return aPrincipal && aPrincipal->GetIsExpandedPrincipal();
7557}
7558
7559bool nsContentUtils::IsSystemOrExpandedPrincipal(nsIPrincipal* aPrincipal) {
7560 return (aPrincipal && aPrincipal->IsSystemPrincipal()) ||
7561 IsExpandedPrincipal(aPrincipal);
7562}
7563
7564nsIPrincipal* nsContentUtils::GetSystemPrincipal() {
7565 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", 7565); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInitialized()" ")"); do { MOZ_CrashSequence
(__null, 7565); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7566 return sSystemPrincipal;
7567}
7568
7569bool nsContentUtils::CombineResourcePrincipals(
7570 nsCOMPtr<nsIPrincipal>* aResourcePrincipal, nsIPrincipal* aExtraPrincipal) {
7571 if (!aExtraPrincipal) {
7572 return false;
7573 }
7574 if (!*aResourcePrincipal) {
7575 *aResourcePrincipal = aExtraPrincipal;
7576 return true;
7577 }
7578 if (*aResourcePrincipal == aExtraPrincipal) {
7579 return false;
7580 }
7581 bool subsumes;
7582 if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl((*aResourcePrincipal
)->Subsumes(aExtraPrincipal, &subsumes))), 1)))
7583 (*aResourcePrincipal)->Subsumes(aExtraPrincipal, &subsumes))((bool)(__builtin_expect(!!(!NS_FAILED_impl((*aResourcePrincipal
)->Subsumes(aExtraPrincipal, &subsumes))), 1)))
&&
7584 subsumes) {
7585 return false;
7586 }
7587 *aResourcePrincipal = sSystemPrincipal;
7588 return true;
7589}
7590
7591/* static */
7592void nsContentUtils::TriggerLinkClick(
7593 nsIContent* aContent, nsIURI* aLinkURI, const nsString& aTargetSpec,
7594 UserNavigationInvolvement aUserInvolvement) {
7595 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", 7595
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLinkURI" ") (" "No link URI"
")"); do { MOZ_CrashSequence(__null, 7595); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7596
7597 if (aContent->IsEditable() || !aContent->OwnerDoc()->LinkHandlingEnabled()) {
7598 return;
7599 }
7600
7601 RefPtr<nsDocShell> docShell =
7602 nsDocShell::Cast(aContent->OwnerDoc()->GetDocShell());
7603 if (!docShell) {
7604 return;
7605 }
7606
7607 // Check that this page is allowed to load this URI.
7608 nsresult proceed = NS_OK;
7609
7610 if (sSecurityManager) {
7611 uint32_t flag = static_cast<uint32_t>(nsIScriptSecurityManager::STANDARD);
7612 proceed = sSecurityManager->CheckLoadURIWithPrincipal(
7613 aContent->NodePrincipal(), aLinkURI, flag,
7614 aContent->OwnerDoc()->InnerWindowID());
7615 }
7616
7617 // Only pass off the click event if the script security manager says it's ok.
7618 // We need to rest aTargetSpec for forced downloads.
7619 if (NS_SUCCEEDED(proceed)((bool)(__builtin_expect(!!(!NS_FAILED_impl(proceed)), 1)))) {
7620 // A link/area element with a download attribute is allowed to set
7621 // a pseudo Content-Disposition header.
7622 // For security reasons we only allow websites to declare same-origin
7623 // resources as downloadable. If this check fails we will just do the normal
7624 // thing (i.e. navigate to the resource).
7625 nsAutoString fileName;
7626 if ((!aContent->IsHTMLElement(nsGkAtoms::a) &&
7627 !aContent->IsHTMLElement(nsGkAtoms::area) &&
7628 !aContent->IsSVGElement(nsGkAtoms::a)) ||
7629 !aContent->AsElement()->GetAttr(nsGkAtoms::download, fileName) ||
7630 NS_FAILED(aContent->NodePrincipal()->CheckMayLoad(aLinkURI, true))((bool)(__builtin_expect(!!(NS_FAILED_impl(aContent->NodePrincipal
()->CheckMayLoad(aLinkURI, true))), 0)))
) {
7631 fileName.SetIsVoid(true); // No actionable download attribute was found.
7632 }
7633
7634 nsCOMPtr<nsIPrincipal> triggeringPrincipal = aContent->NodePrincipal();
7635 nsCOMPtr<nsIPolicyContainer> policyContainer =
7636 aContent->GetPolicyContainer();
7637
7638 // Sanitize fileNames containing null characters by replacing them with
7639 // underscores.
7640 if (!fileName.IsVoid()) {
7641 fileName.ReplaceChar(char16_t(0), '_');
7642 }
7643
7644 docShell->OnLinkClick(
7645 aContent, aLinkURI, fileName.IsVoid() ? aTargetSpec : u""_ns, fileName,
7646 nullptr, nullptr, UserActivation::IsHandlingUserInput(),
7647 aUserInvolvement, triggeringPrincipal, policyContainer);
7648 }
7649}
7650
7651/* static */
7652void nsContentUtils::TriggerLinkMouseOver(nsIContent* aContent,
7653 nsIURI* aLinkURI,
7654 const nsString& aTargetSpec) {
7655 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", 7655
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLinkURI" ") (" "No link URI"
")"); do { MOZ_CrashSequence(__null, 7655); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7656
7657 if (aContent->IsEditable() || !aContent->OwnerDoc()->LinkHandlingEnabled()) {
7658 return;
7659 }
7660
7661 RefPtr<nsDocShell> docShell =
7662 nsDocShell::Cast(aContent->OwnerDoc()->GetDocShell());
7663 if (!docShell) {
7664 return;
7665 }
7666
7667 docShell->OnOverLink(aContent, aLinkURI, aTargetSpec);
7668
7669 if (nsPresContext* pc = aContent->OwnerDoc()->GetPresContext()) {
7670 pc->EventStateManager()->SetLinkOverFrame(aContent->GetPrimaryFrame());
7671 }
7672}
7673
7674/* static */
7675void nsContentUtils::GetLinkLocation(Element* aElement,
7676 nsString& aLocationString) {
7677 nsCOMPtr<nsIURI> hrefURI = aElement->GetHrefURI();
7678 if (hrefURI) {
7679 nsAutoCString specUTF8;
7680 nsresult rv = hrefURI->GetSpec(specUTF8);
7681 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) CopyUTF8toUTF16(specUTF8, aLocationString);
7682 }
7683}
7684
7685/* static */
7686nsIWidget* nsContentUtils::GetTopLevelWidget(nsIWidget* aWidget) {
7687 if (!aWidget) return nullptr;
7688
7689 return aWidget->GetTopLevelWidget();
7690}
7691
7692/* static */
7693const nsDependentString nsContentUtils::GetLocalizedEllipsis() {
7694 static char16_t sBuf[4] = {0, 0, 0, 0};
7695 if (!sBuf[0]) {
7696 if (!nsContentUtils::ShouldResistFingerprinting("No context",
7697 RFPTarget::JSLocale)) {
7698 nsAutoString tmp;
7699 intl::LocaleService::GetInstance()->GetEllipsis(tmp);
7700 uint32_t len =
7701 std::min(uint32_t(tmp.Length()), uint32_t(std::size(sBuf) - 1));
7702 CopyUnicodeTo(tmp, 0, sBuf, len);
7703 }
7704 if (!sBuf[0]) {
7705 sBuf[0] = char16_t(0x2026);
7706 }
7707 }
7708 return nsDependentString(sBuf);
7709}
7710
7711/* static */
7712void nsContentUtils::AddScriptBlocker() {
7713 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", 7713); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 7713); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7714 if (!sScriptBlockerCount) {
7715 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", 7716
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sRunnersCountAtFirstBlocker == 0"
") (" "Should not already have a count" ")"); do { MOZ_CrashSequence
(__null, 7716); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
7716 "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", 7716
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sRunnersCountAtFirstBlocker == 0"
") (" "Should not already have a count" ")"); do { MOZ_CrashSequence
(__null, 7716); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7717 sRunnersCountAtFirstBlocker =
7718 sBlockedScriptRunners ? sBlockedScriptRunners->Length() : 0;
7719 }
7720 ++sScriptBlockerCount;
7721}
7722
7723#ifdef DEBUG1
7724static bool sRemovingScriptBlockers = false;
7725#endif
7726
7727/* static */
7728void nsContentUtils::RemoveScriptBlocker() {
7729 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", 7729); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 7729); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7730 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", 7730); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!sRemovingScriptBlockers" ")"); do { MOZ_CrashSequence
(__null, 7730); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7731 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"
, 7731); MOZ_PretendNoReturn(); } } while (0)
;
7732 --sScriptBlockerCount;
7733 if (sScriptBlockerCount) {
7734 return;
7735 }
7736
7737 if (!sBlockedScriptRunners) {
7738 return;
7739 }
7740
7741 uint32_t firstBlocker = sRunnersCountAtFirstBlocker;
7742 uint32_t lastBlocker = sBlockedScriptRunners->Length();
7743 uint32_t originalFirstBlocker = firstBlocker;
7744 uint32_t blockersCount = lastBlocker - firstBlocker;
7745 sRunnersCountAtFirstBlocker = 0;
7746 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", 7746); MOZ_PretendNoReturn
(); } } while (0)
;
7747
7748 while (firstBlocker < lastBlocker) {
7749 nsCOMPtr<nsIRunnable> runnable;
7750 runnable.swap((*sBlockedScriptRunners)[firstBlocker]);
7751 ++firstBlocker;
7752
7753 // Calling the runnable can reenter us
7754 {
7755 AUTO_PROFILE_FOLLOWING_RUNNABLE(runnable)mozilla::Maybe<mozilla::AutoProfileRunnable> raiiRunnableMarker
; if (profiler_thread_is_profiling_runnables()) { raiiRunnableMarker
.emplace(runnable); }
;
7756 runnable->Run();
7757 }
7758 // So can dropping the reference to the runnable
7759 runnable = nullptr;
7760
7761 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", 7761); MOZ_PretendNoReturn
(); } } while (0)
;
7762 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"
, 7762); MOZ_PretendNoReturn(); } } while (0)
;
7763 }
7764#ifdef DEBUG1
7765 AutoRestore<bool> removingScriptBlockers(sRemovingScriptBlockers);
7766 sRemovingScriptBlockers = true;
7767#endif
7768 sBlockedScriptRunners->RemoveElementsAt(originalFirstBlocker, blockersCount);
7769}
7770
7771/* static */
7772already_AddRefed<nsPIDOMWindowOuter>
7773nsContentUtils::GetMostRecentNonPBWindow() {
7774 nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID"@mozilla.org/appshell/window-mediator;1");
7775
7776 nsCOMPtr<mozIDOMWindowProxy> window;
7777 wm->GetMostRecentNonPBWindow(u"navigator:browser", getter_AddRefs(window));
7778 nsCOMPtr<nsPIDOMWindowOuter> pwindow;
7779 pwindow = do_QueryInterface(window);
7780
7781 return pwindow.forget();
7782}
7783
7784/* static */
7785already_AddRefed<nsPIDOMWindowOuter> nsContentUtils::GetMostRecentWindowBy(
7786 WindowMediatorFilter aFilter) {
7787 nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID"@mozilla.org/appshell/window-mediator;1");
7788
7789 nsCOMPtr<mozIDOMWindowProxy> window;
7790 wm->GetMostRecentWindowBy(u"navigator:browser", static_cast<uint8_t>(aFilter),
7791 getter_AddRefs(window));
7792 nsCOMPtr<nsPIDOMWindowOuter> pwindow;
7793 pwindow = do_QueryInterface(window);
7794
7795 return pwindow.forget();
7796}
7797
7798/* static */
7799void nsContentUtils::WarnScriptWasIgnored(Document* aDocument) {
7800 nsAutoString msg;
7801 bool privateBrowsing = false;
7802 bool chromeContext = false;
7803
7804 if (aDocument) {
7805 nsCOMPtr<nsIURI> uri = aDocument->GetDocumentURI();
7806 if (uri) {
7807 msg.Append(NS_ConvertUTF8toUTF16(uri->GetSpecOrDefault()));
7808 msg.AppendLiteral(" : ");
7809 }
7810 privateBrowsing =
7811 aDocument->NodePrincipal()->OriginAttributesRef().IsPrivateBrowsing();
7812 chromeContext = aDocument->NodePrincipal()->IsSystemPrincipal();
7813 }
7814
7815 msg.AppendLiteral(
7816 "Unable to run script because scripts are blocked internally.");
7817 LogSimpleConsoleError(msg, "DOM"_ns, privateBrowsing, chromeContext);
7818}
7819
7820/* static */
7821void nsContentUtils::AddScriptRunner(already_AddRefed<nsIRunnable> aRunnable) {
7822 nsCOMPtr<nsIRunnable> runnable = aRunnable;
7823 if (!runnable) {
7824 return;
7825 }
7826
7827 if (sScriptBlockerCount) {
7828 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)
7829 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)
;
7830 sBlockedScriptRunners->AppendElement(runnable.forget());
7831 return;
7832 }
7833
7834 AUTO_PROFILE_FOLLOWING_RUNNABLE(runnable)mozilla::Maybe<mozilla::AutoProfileRunnable> raiiRunnableMarker
; if (profiler_thread_is_profiling_runnables()) { raiiRunnableMarker
.emplace(runnable); }
;
7835 runnable->Run();
7836}
7837
7838/* static */
7839void nsContentUtils::AddScriptRunner(nsIRunnable* aRunnable) {
7840 nsCOMPtr<nsIRunnable> runnable = aRunnable;
7841 AddScriptRunner(runnable.forget());
7842}
7843
7844/* static */ bool nsContentUtils::IsSafeToRunScript() {
7845 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", 7846
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "This static variable only makes sense on the main thread!"
")"); do { MOZ_CrashSequence(__null, 7846); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7846 "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", 7846
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "This static variable only makes sense on the main thread!"
")"); do { MOZ_CrashSequence(__null, 7846); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7847 return sScriptBlockerCount == 0;
7848}
7849
7850/* static */
7851void nsContentUtils::RunInStableState(already_AddRefed<nsIRunnable> aRunnable) {
7852 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", 7852
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()"
") (" "Must be on a script thread!" ")"); do { MOZ_CrashSequence
(__null, 7852); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7853 CycleCollectedJSContext::Get()->RunInStableState(std::move(aRunnable));
7854}
7855
7856/* static */
7857void nsContentUtils::AddPendingIDBTransaction(
7858 already_AddRefed<nsIRunnable> aTransaction) {
7859 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", 7859
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()"
") (" "Must be on a script thread!" ")"); do { MOZ_CrashSequence
(__null, 7859); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7860 CycleCollectedJSContext::Get()->AddPendingIDBTransaction(
7861 std::move(aTransaction));
7862}
7863
7864/* static */
7865bool nsContentUtils::IsInStableOrMetaStableState() {
7866 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", 7866
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "CycleCollectedJSContext::Get()"
") (" "Must be on a script thread!" ")"); do { MOZ_CrashSequence
(__null, 7866); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
7867 return CycleCollectedJSContext::Get()->IsInStableOrMetaStableState();
7868}
7869
7870/* static */
7871void nsContentUtils::HidePopupsInDocument(Document* aDocument) {
7872 RefPtr<nsXULPopupManager> pm = nsXULPopupManager::GetInstance();
7873 if (!pm || !aDocument) {
7874 return;
7875 }
7876 nsCOMPtr<nsIDocShellTreeItem> docShellToHide = aDocument->GetDocShell();
7877 if (docShellToHide) {
7878 pm->HidePopupsInDocShell(docShellToHide);
7879 }
7880}
7881
7882/* static */
7883already_AddRefed<nsIDragSession> nsContentUtils::GetDragSession(
7884 nsIWidget* aWidget) {
7885 nsCOMPtr<nsIDragSession> dragSession;
7886 nsCOMPtr<nsIDragService> dragService =
7887 do_GetService("@mozilla.org/widget/dragservice;1");
7888 if (dragService) {
7889 dragSession = dragService->GetCurrentSession(aWidget);
7890 }
7891 return dragSession.forget();
7892}
7893
7894/* static */
7895already_AddRefed<nsIDragSession> nsContentUtils::GetDragSession(
7896 nsPresContext* aPC) {
7897 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"
, 7897); return nullptr; } } while (false)
;
7898 auto* widget = aPC->GetRootWidget();
7899 if (!widget) {
7900 return nullptr;
7901 }
7902 return GetDragSession(widget);
7903}
7904
7905/* static */
7906nsresult nsContentUtils::SetDataTransferInEvent(WidgetDragEvent* aDragEvent) {
7907 if (aDragEvent->mDataTransfer || !aDragEvent->IsTrusted()) {
7908 return NS_OK;
7909 }
7910
7911 // For dragstart events, the data transfer object is
7912 // created before the event fires, so it should already be set. For other
7913 // drag events, get the object from the drag session.
7914 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"
, 7915); MOZ_PretendNoReturn(); } } while (0)
7915 "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"
, 7915); MOZ_PretendNoReturn(); } } while (0)
;
7916
7917 nsCOMPtr<nsIDragSession> dragSession = GetDragSession(aDragEvent->mWidget);
7918 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",
7918); return NS_OK; } } while (false)
; // no drag in progress
7919
7920 RefPtr<DataTransfer> initialDataTransfer = dragSession->GetDataTransfer();
7921 if (!initialDataTransfer) {
7922 // A dataTransfer won't exist when a drag was started by some other
7923 // means, for instance calling the drag service directly, or a drag
7924 // from another application. In either case, a new dataTransfer should
7925 // be created that reflects the data.
7926 initialDataTransfer = new DataTransfer(
7927 aDragEvent->mTarget, aDragEvent->mMessage, true, Nothing());
7928
7929 // now set it in the drag session so we don't need to create it again
7930 dragSession->SetDataTransfer(initialDataTransfer);
7931 }
7932
7933 bool isCrossDomainSubFrameDrop = false;
7934 if (aDragEvent->mMessage == eDrop) {
7935 isCrossDomainSubFrameDrop = CheckForSubFrameDrop(dragSession, aDragEvent);
7936 }
7937
7938 // each event should use a clone of the original dataTransfer.
7939 initialDataTransfer->Clone(
7940 aDragEvent->mTarget, aDragEvent->mMessage, aDragEvent->mUserCancelled,
7941 isCrossDomainSubFrameDrop, getter_AddRefs(aDragEvent->mDataTransfer));
7942 if (NS_WARN_IF(!aDragEvent->mDataTransfer)NS_warn_if_impl(!aDragEvent->mDataTransfer, "!aDragEvent->mDataTransfer"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 7942)
) {
7943 return NS_ERROR_OUT_OF_MEMORY;
7944 }
7945
7946 // for the dragenter and dragover events, initialize the drop effect
7947 // from the drop action, which platform specific widget code sets before
7948 // the event is fired based on the keyboard state.
7949 if (aDragEvent->mMessage == eDragEnter || aDragEvent->mMessage == eDragOver) {
7950 uint32_t action;
7951 dragSession->GetDragAction(&action);
7952 uint32_t effectAllowed = aDragEvent->mDataTransfer->EffectAllowedInt();
7953 aDragEvent->mDataTransfer->SetDropEffectInt(
7954 FilterDropEffect(action, effectAllowed));
7955 } else if (aDragEvent->mMessage == eDrop ||
7956 aDragEvent->mMessage == eDragEnd) {
7957 // For the drop and dragend events, set the drop effect based on the
7958 // last value that the dropEffect had. This will have been set in
7959 // EventStateManager::PostHandleEvent for the last dragenter or
7960 // dragover event.
7961 aDragEvent->mDataTransfer->SetDropEffectInt(
7962 initialDataTransfer->DropEffectInt());
7963 }
7964
7965 return NS_OK;
7966}
7967
7968/* static */
7969uint32_t nsContentUtils::FilterDropEffect(uint32_t aAction,
7970 uint32_t aEffectAllowed) {
7971 // It is possible for the drag action to include more than one action, but
7972 // the widget code which sets the action from the keyboard state should only
7973 // be including one. If multiple actions were set, we just consider them in
7974 // the following order:
7975 // copy, link, move
7976 if (aAction & nsIDragService::DRAGDROP_ACTION_COPY)
7977 aAction = nsIDragService::DRAGDROP_ACTION_COPY;
7978 else if (aAction & nsIDragService::DRAGDROP_ACTION_LINK)
7979 aAction = nsIDragService::DRAGDROP_ACTION_LINK;
7980 else if (aAction & nsIDragService::DRAGDROP_ACTION_MOVE)
7981 aAction = nsIDragService::DRAGDROP_ACTION_MOVE;
7982
7983 // Filter the action based on the effectAllowed. If the effectAllowed
7984 // doesn't include the action, then that action cannot be done, so adjust
7985 // the action to something that is allowed. For a copy, adjust to move or
7986 // link. For a move, adjust to copy or link. For a link, adjust to move or
7987 // link. Otherwise, use none.
7988 if (aAction & aEffectAllowed ||
7989 aEffectAllowed == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED)
7990 return aAction;
7991 if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_MOVE)
7992 return nsIDragService::DRAGDROP_ACTION_MOVE;
7993 if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_COPY)
7994 return nsIDragService::DRAGDROP_ACTION_COPY;
7995 if (aEffectAllowed & nsIDragService::DRAGDROP_ACTION_LINK)
7996 return nsIDragService::DRAGDROP_ACTION_LINK;
7997 return nsIDragService::DRAGDROP_ACTION_NONE;
7998}
7999
8000/* static */
8001bool nsContentUtils::CheckForSubFrameDrop(nsIDragSession* aDragSession,
8002 WidgetDragEvent* aDropEvent) {
8003 nsCOMPtr<nsIContent> target =
8004 nsIContent::FromEventTargetOrNull(aDropEvent->mOriginalTarget);
8005 if (!target) {
8006 return true;
8007 }
8008
8009 // Always allow dropping onto chrome shells.
8010 BrowsingContext* targetBC = target->OwnerDoc()->GetBrowsingContext();
8011 if (targetBC->IsChrome()) {
8012 return false;
8013 }
8014
8015 WindowContext* targetWC = target->OwnerDoc()->GetWindowContext();
8016
8017 // If there is no source browsing context, then this is a drag from another
8018 // application, which should be allowed.
8019 RefPtr<WindowContext> sourceWC;
8020 aDragSession->GetSourceWindowContext(getter_AddRefs(sourceWC));
8021 if (sourceWC) {
8022 // Get each successive parent of the source document and compare it to
8023 // the drop document. If they match, then this is a drag from a child frame.
8024 for (sourceWC = sourceWC->GetParentWindowContext(); sourceWC;
8025 sourceWC = sourceWC->GetParentWindowContext()) {
8026 // If the source and the target match, then the drag started in a
8027 // descendant frame. If the source is discarded, err on the side of
8028 // caution and treat it as a subframe drag.
8029 if (sourceWC == targetWC || sourceWC->IsDiscarded()) {
8030 return true;
8031 }
8032 }
8033 }
8034
8035 return false;
8036}
8037
8038/* static */
8039bool nsContentUtils::URIIsLocalFile(nsIURI* aURI) {
8040 bool isFile;
8041 nsCOMPtr<nsINetUtil> util = mozilla::components::IO::Service();
8042
8043 // Important: we do NOT test the entire URI chain here!
8044 return util &&
8045 NS_SUCCEEDED(util->ProtocolHasFlags(((bool)(__builtin_expect(!!(!NS_FAILED_impl(util->ProtocolHasFlags
( aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile)))
, 1)))
8046 aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile))((bool)(__builtin_expect(!!(!NS_FAILED_impl(util->ProtocolHasFlags
( aURI, nsIProtocolHandler::URI_IS_LOCAL_FILE, &isFile)))
, 1)))
&&
8047 isFile;
8048}
8049
8050/* static */
8051JSContext* nsContentUtils::GetCurrentJSContext() {
8052 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", 8052); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "IsInitialized()" ")"); do { MOZ_CrashSequence
(__null, 8052); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8053 if (!IsJSAPIActive()) {
8054 return nullptr;
8055 }
8056 return danger::GetJSContext();
8057}
8058
8059template <typename StringType, typename CharType>
8060void _ASCIIToLowerInSitu(StringType& aStr) {
8061 CharType* iter = aStr.BeginWriting();
8062 CharType* end = aStr.EndWriting();
8063 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", 8063); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "iter && end" ")"); do { MOZ_CrashSequence
(__null, 8063); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8064
8065 while (iter != end) {
8066 CharType c = *iter;
8067 if (c >= 'A' && c <= 'Z') {
8068 *iter = c + ('a' - 'A');
8069 }
8070 ++iter;
8071 }
8072}
8073
8074/* static */
8075void nsContentUtils::ASCIIToLower(nsAString& aStr) {
8076 return _ASCIIToLowerInSitu<nsAString, char16_t>(aStr);
8077}
8078
8079/* static */
8080void nsContentUtils::ASCIIToLower(nsACString& aStr) {
8081 return _ASCIIToLowerInSitu<nsACString, char>(aStr);
8082}
8083
8084template <typename StringType, typename CharType>
8085void _ASCIIToLowerCopy(const StringType& aSource, StringType& aDest) {
8086 uint32_t len = aSource.Length();
8087 aDest.SetLength(len);
8088 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", 8088); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aDest.Length() == len" ")"); do { MOZ_CrashSequence
(__null, 8088); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8089
8090 CharType* dest = aDest.BeginWriting();
8091 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"
, 8091); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dest" ")");
do { MOZ_CrashSequence(__null, 8091); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8092
8093 const CharType* iter = aSource.BeginReading();
8094 const CharType* end = aSource.EndReading();
8095 while (iter != end) {
8096 CharType c = *iter;
8097 *dest = (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
8098 ++iter;
8099 ++dest;
8100 }
8101}
8102
8103/* static */
8104void nsContentUtils::ASCIIToLower(const nsAString& aSource, nsAString& aDest) {
8105 return _ASCIIToLowerCopy<nsAString, char16_t>(aSource, aDest);
8106}
8107
8108/* static */
8109void nsContentUtils::ASCIIToLower(const nsACString& aSource,
8110 nsACString& aDest) {
8111 return _ASCIIToLowerCopy<nsACString, char>(aSource, aDest);
8112}
8113
8114template <typename StringType, typename CharType>
8115void _ASCIIToUpperInSitu(StringType& aStr) {
8116 CharType* iter = aStr.BeginWriting();
8117 CharType* end = aStr.EndWriting();
8118 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", 8118); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "iter && end" ")"); do { MOZ_CrashSequence
(__null, 8118); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8119
8120 while (iter != end) {
8121 CharType c = *iter;
8122 if (c >= 'a' && c <= 'z') {
8123 *iter = c + ('A' - 'a');
8124 }
8125 ++iter;
8126 }
8127}
8128
8129/* static */
8130void nsContentUtils::ASCIIToUpper(nsAString& aStr) {
8131 return _ASCIIToUpperInSitu<nsAString, char16_t>(aStr);
8132}
8133
8134/* static */
8135void nsContentUtils::ASCIIToUpper(nsACString& aStr) {
8136 return _ASCIIToUpperInSitu<nsACString, char>(aStr);
8137}
8138
8139template <typename StringType, typename CharType>
8140void _ASCIIToUpperCopy(const StringType& aSource, StringType& aDest) {
8141 uint32_t len = aSource.Length();
8142 aDest.SetLength(len);
8143 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", 8143); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aDest.Length() == len" ")"); do { MOZ_CrashSequence
(__null, 8143); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8144
8145 CharType* dest = aDest.BeginWriting();
8146 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"
, 8146); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dest" ")");
do { MOZ_CrashSequence(__null, 8146); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8147
8148 const CharType* iter = aSource.BeginReading();
8149 const CharType* end = aSource.EndReading();
8150 while (iter != end) {
8151 CharType c = *iter;
8152 *dest = (c >= 'a' && c <= 'z') ? c + ('A' - 'a') : c;
8153 ++iter;
8154 ++dest;
8155 }
8156}
8157
8158/* static */
8159void nsContentUtils::ASCIIToUpper(const nsAString& aSource, nsAString& aDest) {
8160 return _ASCIIToUpperCopy<nsAString, char16_t>(aSource, aDest);
8161}
8162
8163/* static */
8164void nsContentUtils::ASCIIToUpper(const nsACString& aSource,
8165 nsACString& aDest) {
8166 return _ASCIIToUpperCopy<nsACString, char>(aSource, aDest);
8167}
8168
8169/* static */
8170bool nsContentUtils::EqualsIgnoreASCIICase(nsAtom* aAtom1, nsAtom* aAtom2) {
8171 if (aAtom1 == aAtom2) {
8172 return true;
8173 }
8174
8175 // If both are ascii lowercase already, we know that the slow comparison
8176 // below is going to return false.
8177 if (aAtom1->IsAsciiLowercase() && aAtom2->IsAsciiLowercase()) {
8178 return false;
8179 }
8180
8181 return EqualsIgnoreASCIICase(nsDependentAtomString(aAtom1),
8182 nsDependentAtomString(aAtom2));
8183}
8184
8185/* static */
8186bool nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1,
8187 const nsAString& aStr2) {
8188 uint32_t len = aStr1.Length();
8189 if (len != aStr2.Length()) {
8190 return false;
8191 }
8192
8193 const char16_t* str1 = aStr1.BeginReading();
8194 const char16_t* str2 = aStr2.BeginReading();
8195 const char16_t* end = str1 + len;
8196
8197 while (str1 < end) {
8198 char16_t c1 = *str1++;
8199 char16_t c2 = *str2++;
8200
8201 // First check if any bits other than the 0x0020 differs
8202 if ((c1 ^ c2) & 0xffdf) {
8203 return false;
8204 }
8205
8206 // We know they can only differ in the 0x0020 bit.
8207 // Likely the two chars are the same, so check that first
8208 if (c1 != c2) {
8209 // They do differ, but since it's only in the 0x0020 bit, check if it's
8210 // the same ascii char, but just differing in case
8211 char16_t c1Upper = c1 & 0xffdf;
8212 if (!('A' <= c1Upper && c1Upper <= 'Z')) {
8213 return false;
8214 }
8215 }
8216 }
8217
8218 return true;
8219}
8220
8221/* static */
8222bool nsContentUtils::StringContainsASCIIUpper(const nsAString& aStr) {
8223 const char16_t* iter = aStr.BeginReading();
8224 const char16_t* end = aStr.EndReading();
8225 while (iter != end) {
8226 char16_t c = *iter;
8227 if (c >= 'A' && c <= 'Z') {
8228 return true;
8229 }
8230 ++iter;
8231 }
8232
8233 return false;
8234}
8235
8236/* static */
8237nsIInterfaceRequestor* nsContentUtils::SameOriginChecker() {
8238 if (!sSameOriginChecker) {
8239 sSameOriginChecker = new SameOriginCheckerImpl();
8240 NS_ADDREF(sSameOriginChecker)(sSameOriginChecker)->AddRef();
8241 }
8242 return sSameOriginChecker;
8243}
8244
8245/* static */
8246nsresult nsContentUtils::CheckSameOrigin(nsIChannel* aOldChannel,
8247 nsIChannel* aNewChannel) {
8248 if (!nsContentUtils::GetSecurityManager()) return NS_ERROR_NOT_AVAILABLE;
8249
8250 nsCOMPtr<nsIPrincipal> oldPrincipal;
8251 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
8252 aOldChannel, getter_AddRefs(oldPrincipal));
8253
8254 nsCOMPtr<nsIURI> newURI;
8255 aNewChannel->GetURI(getter_AddRefs(newURI));
8256 nsCOMPtr<nsIURI> newOriginalURI;
8257 aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
8258
8259 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"
, 8259); return NS_ERROR_UNEXPECTED; } } while (false)
;
8260
8261 nsresult rv = oldPrincipal->CheckMayLoad(newURI, false);
8262 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && newOriginalURI != newURI) {
8263 rv = oldPrincipal->CheckMayLoad(newOriginalURI, false);
8264 }
8265
8266 return rv;
8267}
8268
8269NS_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"
, 8270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 8270
); __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"
, 8270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 8270); __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", 8270
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 8270
); __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"
, 8270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 8270); __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"
, 8270); 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; }
8270 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"
, 8270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 8270
); __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"
, 8270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 8270); __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", 8270
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 8270
); __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"
, 8270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SameOriginCheckerImpl\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 8270); __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"
, 8270); 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; }
8271
8272NS_IMETHODIMPnsresult
8273SameOriginCheckerImpl::AsyncOnChannelRedirect(
8274 nsIChannel* aOldChannel, nsIChannel* aNewChannel, uint32_t aFlags,
8275 nsIAsyncVerifyRedirectCallback* cb) {
8276 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"
, 8276); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNewChannel"
") (" "Redirecting to null channel?" ")"); do { MOZ_CrashSequence
(__null, 8276); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8277
8278 nsresult rv = nsContentUtils::CheckSameOrigin(aOldChannel, aNewChannel);
8279 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
8280 cb->OnRedirectVerifyCallback(NS_OK);
8281 }
8282
8283 return rv;
8284}
8285
8286NS_IMETHODIMPnsresult
8287SameOriginCheckerImpl::GetInterface(const nsIID& aIID, void** aResult) {
8288 return QueryInterface(aIID, aResult);
8289}
8290
8291/* static */
8292nsresult nsContentUtils::GetWebExposedOriginSerialization(nsIURI* aURI,
8293 nsACString& aOrigin) {
8294 nsresult rv;
8295 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"
, 8295); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"missing uri" ")"); do { MOZ_CrashSequence(__null, 8295); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
8296
8297 // For Blob URI, the path is the URL of the owning page.
8298 if (aURI->SchemeIs(BLOBURI_SCHEME"blob")) {
8299 nsAutoCString path;
8300 rv = aURI->GetPathQueryRef(path);
8301 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"
, 8301); return rv; } } while (false)
;
8302
8303 nsCOMPtr<nsIURI> uri;
8304 rv = NS_NewURI(getter_AddRefs(uri), path);
8305 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8306 aOrigin.AssignLiteral("null");
8307 return NS_OK;
8308 }
8309
8310 if (
8311 // Schemes in spec. https://url.spec.whatwg.org/#origin
8312 !net::SchemeIsHttpOrHttps(uri) && !uri->SchemeIs("file") &&
8313 !uri->SchemeIs("resource") &&
8314 // Our own schemes.
8315 !uri->SchemeIs("moz-extension")) {
8316 aOrigin.AssignLiteral("null");
8317 return NS_OK;
8318 }
8319
8320 return GetWebExposedOriginSerialization(uri, aOrigin);
8321 }
8322
8323 nsAutoCString scheme;
8324 aURI->GetScheme(scheme);
8325
8326 // If the protocol doesn't have URI_HAS_WEB_EXPOSED_ORIGIN, then
8327 // return "null" as the origin serialization.
8328 // We make an exception for "ftp" since we don't have a protocol handler
8329 // for this scheme
8330 uint32_t flags = 0;
8331 nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service(&rv);
8332 if (!scheme.Equals("ftp") && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) &&
8333 NS_SUCCEEDED(io->GetProtocolFlags(scheme.get(), &flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(io->GetProtocolFlags
(scheme.get(), &flags))), 1)))
) {
8334 if (!(flags & nsIProtocolHandler::URI_HAS_WEB_EXPOSED_ORIGIN)) {
8335 aOrigin.AssignLiteral("null");
8336 return NS_OK;
8337 }
8338 }
8339
8340 aOrigin.Truncate();
8341
8342 nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
8343 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"
, 8343); return NS_ERROR_UNEXPECTED; } } while (false)
;
8344
8345 nsAutoCString host;
8346 rv = uri->GetAsciiHost(host);
8347
8348 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !host.IsEmpty()) {
8349 nsAutoCString userPass;
8350 uri->GetUserPass(userPass);
8351
8352 nsAutoCString prePath;
8353 if (!userPass.IsEmpty()) {
8354 rv = NS_MutateURI(uri).SetUserPass(""_ns).Finalize(uri);
8355 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"
, 8355); return rv; } } while (false)
;
8356 }
8357
8358 rv = uri->GetPrePath(prePath);
8359 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"
, 8359); return rv; } } while (false)
;
8360
8361 aOrigin = std::move(prePath);
8362 } else {
8363 aOrigin.AssignLiteral("null");
8364 }
8365
8366 return NS_OK;
8367}
8368
8369/* static */
8370nsresult nsContentUtils::GetWebExposedOriginSerialization(
8371 nsIPrincipal* aPrincipal, nsAString& aOrigin) {
8372 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", 8372
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrincipal" ") ("
"missing principal" ")"); do { MOZ_CrashSequence(__null, 8372
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
8373
8374 aOrigin.Truncate();
8375 nsAutoCString webExposedOriginSerialization;
8376
8377 nsresult rv = aPrincipal->GetWebExposedOriginSerialization(
8378 webExposedOriginSerialization);
8379 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8380 webExposedOriginSerialization.AssignLiteral("null");
8381 }
8382
8383 CopyUTF8toUTF16(webExposedOriginSerialization, aOrigin);
8384 return NS_OK;
8385}
8386
8387/* static */
8388nsresult nsContentUtils::GetWebExposedOriginSerialization(nsIURI* aURI,
8389 nsAString& aOrigin) {
8390 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"
, 8390); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aURI" ") ("
"missing uri" ")"); do { MOZ_CrashSequence(__null, 8390); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
8391 nsresult rv;
8392
8393#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
8394 // Check if either URI has a special origin.
8395 nsCOMPtr<nsIURIWithSpecialOrigin> uriWithSpecialOrigin =
8396 do_QueryInterface(aURI);
8397 if (uriWithSpecialOrigin) {
8398 nsCOMPtr<nsIURI> origin;
8399 rv = uriWithSpecialOrigin->GetOrigin(getter_AddRefs(origin));
8400 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"
, 8400); return rv; } } while (false)
;
8401
8402 return GetWebExposedOriginSerialization(origin, aOrigin);
8403 }
8404#endif
8405
8406 nsAutoCString webExposedOriginSerialization;
8407 rv = GetWebExposedOriginSerialization(aURI, webExposedOriginSerialization);
8408 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"
, 8408); return rv; } } while (false)
;
8409
8410 CopyUTF8toUTF16(webExposedOriginSerialization, aOrigin);
8411 return NS_OK;
8412}
8413
8414/* static */
8415bool nsContentUtils::CheckMayLoad(nsIPrincipal* aPrincipal,
8416 nsIChannel* aChannel,
8417 bool aAllowIfInheritsPrincipal) {
8418 nsCOMPtr<nsIURI> channelURI;
8419 nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(channelURI));
8420 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"
, 8420); return false; } } while (false)
;
8421
8422 return NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->CheckMayLoad
(channelURI, aAllowIfInheritsPrincipal))), 1)))
8423 aPrincipal->CheckMayLoad(channelURI, aAllowIfInheritsPrincipal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aPrincipal->CheckMayLoad
(channelURI, aAllowIfInheritsPrincipal))), 1)))
;
8424}
8425
8426/* static */
8427bool nsContentUtils::CanAccessNativeAnon() {
8428 return LegacyIsCallerChromeOrNativeCode();
8429}
8430
8431/* static */
8432nsresult nsContentUtils::DispatchXULCommand(nsIContent* aTarget, bool aTrusted,
8433 Event* aSourceEvent,
8434 PresShell* aPresShell, bool aCtrl,
8435 bool aAlt, bool aShift, bool aMeta,
8436 uint16_t aInputSource,
8437 int16_t aButton) {
8438 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", 8438); return
NS_ERROR_UNEXPECTED; } } while (false)
;
8439 Document* doc = aTarget->OwnerDoc();
8440 nsPresContext* presContext = doc->GetPresContext();
8441
8442 RefPtr<XULCommandEvent> xulCommand =
8443 new XULCommandEvent(doc, presContext, nullptr);
8444 xulCommand->InitCommandEvent(u"command"_ns, true, true,
8445 nsGlobalWindowInner::Cast(doc->GetInnerWindow()),
8446 0, aCtrl, aAlt, aShift, aMeta, aButton,
8447 aSourceEvent, aInputSource, IgnoreErrors());
8448
8449 if (aPresShell) {
8450 nsEventStatus status = nsEventStatus_eIgnore;
8451 return aPresShell->HandleDOMEventWithTarget(aTarget, xulCommand, &status);
8452 }
8453
8454 ErrorResult rv;
8455 aTarget->DispatchEvent(*xulCommand, rv);
8456 return rv.StealNSResult();
8457}
8458
8459// static
8460nsresult nsContentUtils::WrapNative(JSContext* cx, nsISupports* native,
8461 nsWrapperCache* cache, const nsIID* aIID,
8462 JS::MutableHandle<JS::Value> vp,
8463 bool aAllowWrapping) {
8464 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", 8464); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "cx == GetCurrentJSContext()" ")"); do { MOZ_CrashSequence
(__null, 8464); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
8465
8466 if (!native) {
8467 vp.setNull();
8468
8469 return NS_OK;
8470 }
8471
8472 JSObject* wrapper = xpc_FastGetCachedWrapper(cx, cache, vp);
8473 if (wrapper) {
8474 return NS_OK;
8475 }
8476
8477 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", 8477
); return NS_ERROR_UNEXPECTED; } } while (false)
;
8478
8479 if (!NS_IsMainThread()) {
8480 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8480); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { MOZ_CrashSequence
(__null, 8480); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
8481 }
8482
8483 JS::Rooted<JSObject*> scope(cx, JS::CurrentGlobalOrNull(cx));
8484 nsresult rv = sXPConnect->WrapNativeToJSVal(cx, scope, native, cache, aIID,
8485 aAllowWrapping, vp);
8486 return rv;
8487}
8488
8489void nsContentUtils::StripNullChars(const nsAString& aInStr,
8490 nsAString& aOutStr) {
8491 // In common cases where we don't have nulls in the
8492 // string we can simple simply bypass the checking code.
8493 int32_t firstNullPos = aInStr.FindChar('\0');
8494 if (firstNullPos == kNotFound) {
8495 aOutStr.Assign(aInStr);
8496 return;
8497 }
8498
8499 aOutStr.SetCapacity(aInStr.Length() - 1);
8500 nsAString::const_iterator start, end;
8501 aInStr.BeginReading(start);
8502 aInStr.EndReading(end);
8503 while (start != end) {
8504 if (*start != '\0') aOutStr.Append(*start);
8505 ++start;
8506 }
8507}
8508
8509struct ClassMatchingInfo {
8510 AtomArray mClasses;
8511 nsCaseTreatment mCaseTreatment;
8512};
8513
8514// static
8515bool nsContentUtils::MatchClassNames(Element* aElement, int32_t aNamespaceID,
8516 nsAtom* aAtom, void* aData) {
8517 // We can't match if there are no class names
8518 const nsAttrValue* classAttr = aElement->GetClasses();
8519 if (!classAttr) {
8520 return false;
8521 }
8522
8523 // need to match *all* of the classes
8524 ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
8525 if (info->mClasses.IsEmpty()) {
8526 // If we actually had no classes, don't match.
8527 return false;
8528 }
8529
8530 for (nsAtom* cls : info->mClasses) {
8531 if (!classAttr->Contains(cls, info->mCaseTreatment)) {
8532 return false;
8533 }
8534 }
8535 return true;
8536}
8537
8538// static
8539void nsContentUtils::DestroyClassNameArray(void* aData) {
8540 ClassMatchingInfo* info = static_cast<ClassMatchingInfo*>(aData);
8541 delete info;
8542}
8543
8544// static
8545void* nsContentUtils::AllocClassMatchingInfo(nsINode* aRootNode,
8546 const nsString* aClasses) {
8547 nsAttrValue attrValue;
8548 attrValue.ParseAtomArray(*aClasses);
8549 // nsAttrValue::Equals is sensitive to order, so we'll send an array
8550 auto* info = new ClassMatchingInfo;
8551 if (attrValue.Type() == nsAttrValue::eAtomArray) {
8552 info->mClasses.AppendElements(attrValue.GetAtomArrayValue()->Array());
8553 } else if (attrValue.Type() == nsAttrValue::eAtom) {
8554 info->mClasses.AppendElement(attrValue.GetAtomValue());
8555 }
8556
8557 info->mCaseTreatment =
8558 aRootNode->OwnerDoc()->GetCompatibilityMode() == eCompatibility_NavQuirks
8559 ? eIgnoreCase
8560 : eCaseMatters;
8561 return info;
8562}
8563
8564void nsContentUtils::FlushLayoutForTree(nsPIDOMWindowOuter* aWindow) {
8565 if (!aWindow) {
8566 return;
8567 }
8568
8569 // Note that because FlushPendingNotifications flushes parents, this
8570 // is O(N^2) in docshell tree depth. However, the docshell tree is
8571 // usually pretty shallow.
8572
8573 if (RefPtr<Document> doc = aWindow->GetDoc()) {
8574 doc->FlushPendingNotifications(FlushType::Layout);
8575 }
8576
8577 if (nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell()) {
8578 int32_t i = 0, i_end;
8579 docShell->GetInProcessChildCount(&i_end);
8580 for (; i < i_end; ++i) {
8581 nsCOMPtr<nsIDocShellTreeItem> item;
8582 if (docShell->GetInProcessChildAt(i, getter_AddRefs(item)) == NS_OK &&
8583 item) {
8584 if (nsCOMPtr<nsPIDOMWindowOuter> win = item->GetWindow()) {
8585 FlushLayoutForTree(win);
8586 }
8587 }
8588 }
8589 }
8590}
8591
8592void nsContentUtils::RemoveNewlines(nsAString& aString) { aString.StripCRLF(); }
8593
8594void nsContentUtils::PlatformToDOMLineBreaks(nsAString& aString) {
8595 if (!PlatformToDOMLineBreaks(aString, fallible)) {
8596 aString.AllocFailed(aString.Length());
8597 }
8598}
8599
8600bool nsContentUtils::PlatformToDOMLineBreaks(nsAString& aString,
8601 const fallible_t& aFallible) {
8602 if (aString.FindChar(char16_t('\r')) != -1) {
8603 // Windows linebreaks: Map CRLF to LF:
8604 if (!aString.ReplaceSubstring(u"\r\n", u"\n", aFallible)) {
8605 return false;
8606 }
8607
8608 // Mac linebreaks: Map any remaining CR to LF:
8609 if (!aString.ReplaceSubstring(u"\r", u"\n", aFallible)) {
8610 return false;
8611 }
8612 }
8613
8614 return true;
8615}
8616
8617already_AddRefed<ContentList> nsContentUtils::GetElementsByClassName(
8618 nsINode* aRootNode, const nsAString& aClasses) {
8619 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", 8619
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRootNode" ") (" "Must have root node"
")"); do { MOZ_CrashSequence(__null, 8619); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8620
8621 return GetFuncStringContentList<CacheableFuncStringHTMLCollection>(
8622 aRootNode, MatchClassNames, DestroyClassNameArray, AllocClassMatchingInfo,
8623 aClasses);
8624}
8625
8626PresShell* nsContentUtils::FindPresShellForDocument(const Document* aDocument) {
8627 const Document* doc = aDocument;
8628 Document* displayDoc = doc->GetDisplayDocument();
8629 if (displayDoc) {
8630 doc = displayDoc;
8631 }
8632
8633 PresShell* presShell = doc->GetPresShell();
8634 if (presShell) {
8635 return presShell;
8636 }
8637
8638 nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem = doc->GetDocShell();
8639 while (docShellTreeItem) {
8640 // We may be in a display:none subdocument, or we may not have a presshell
8641 // created yet.
8642 // Walk the docshell tree to find the nearest container that has a
8643 // presshell, and return that.
8644 nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(docShellTreeItem);
8645 if (PresShell* presShell = docShell->GetPresShell()) {
8646 return presShell;
8647 }
8648 nsCOMPtr<nsIDocShellTreeItem> parent;
8649 docShellTreeItem->GetInProcessParent(getter_AddRefs(parent));
8650 docShellTreeItem = parent;
8651 }
8652
8653 return nullptr;
8654}
8655
8656/* static */
8657nsPresContext* nsContentUtils::FindPresContextForDocument(
8658 const Document* aDocument) {
8659 if (PresShell* presShell = FindPresShellForDocument(aDocument)) {
8660 return presShell->GetPresContext();
8661 }
8662 return nullptr;
8663}
8664
8665nsIWidget* nsContentUtils::WidgetForDocument(const Document* aDocument) {
8666 PresShell* presShell = FindPresShellForDocument(aDocument);
8667 return presShell ? presShell->GetNearestWidget() : nullptr;
8668}
8669
8670nsIWidget* nsContentUtils::WidgetForContent(const nsIContent* aContent) {
8671 nsIFrame* frame = aContent->GetPrimaryFrame();
8672 if (!frame) {
8673 return nullptr;
8674 }
8675 return frame->GetNearestWidget();
8676}
8677
8678WindowRenderer* nsContentUtils::WindowRendererForContent(
8679 const nsIContent* aContent) {
8680 nsIWidget* widget = nsContentUtils::WidgetForContent(aContent);
8681 if (widget) {
8682 return widget->GetWindowRenderer();
8683 }
8684
8685 return nullptr;
8686}
8687
8688WindowRenderer* nsContentUtils::WindowRendererForDocument(
8689 const Document* aDoc) {
8690 if (nsIWidget* widget = nsContentUtils::WidgetForDocument(aDoc)) {
8691 return widget->GetWindowRenderer();
8692 }
8693 return nullptr;
8694}
8695
8696bool nsContentUtils::AllowXULXBLForPrincipal(nsIPrincipal* aPrincipal) {
8697 if (!aPrincipal) {
8698 return false;
8699 }
8700
8701 if (aPrincipal->IsSystemPrincipal()) {
8702 return true;
8703 }
8704
8705 return xpc::IsInAutomation() && IsSitePermAllow(aPrincipal, "allowXULXBL"_ns);
8706}
8707
8708bool nsContentUtils::IsPDFJSEnabled() { return !StaticPrefs::pdfjs_disabled(); }
8709
8710bool nsContentUtils::IsPDFJS(nsIPrincipal* aPrincipal) {
8711 if (!aPrincipal || !aPrincipal->SchemeIs("resource")) {
8712 return false;
8713 }
8714 nsAutoCString spec;
8715 nsresult rv = aPrincipal->GetAsciiSpec(spec);
8716 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"
, 8716); return false; } } while (false)
;
8717 return spec.EqualsLiteral("resource://pdf.js/web/viewer.html");
8718}
8719
8720bool nsContentUtils::IsSystemOrPDFJS(JSContext* aCx, JSObject*) {
8721 nsIPrincipal* principal = SubjectPrincipal(aCx);
8722 return principal && (principal->IsSystemPrincipal() || IsPDFJS(principal));
8723}
8724
8725bool nsContentUtils::IsSecureContextOrWebExtension(JSContext* aCx,
8726 JSObject* aGlobal) {
8727 nsIPrincipal* principal = SubjectPrincipal(aCx);
8728 return mozilla::dom::IsSecureContextOrObjectIsFromSecureContext(aCx,
8729 aGlobal) ||
8730 (principal && principal->GetIsAddonOrExpandedAddonPrincipal());
8731}
8732
8733already_AddRefed<nsIDocumentLoaderFactory>
8734nsContentUtils::FindInternalDocumentViewer(const nsACString& aType,
8735 DocumentViewerType* aLoaderType) {
8736 if (aLoaderType) {
8737 *aLoaderType = TYPE_UNSUPPORTED;
8738 }
8739
8740 // one helper factory, please
8741 nsCOMPtr<nsICategoryManager> catMan(
8742 do_GetService(NS_CATEGORYMANAGER_CONTRACTID"@mozilla.org/categorymanager;1"));
8743 if (!catMan) return nullptr;
8744
8745 nsCOMPtr<nsIDocumentLoaderFactory> docFactory;
8746
8747 nsCString contractID;
8748 nsresult rv =
8749 catMan->GetCategoryEntry("Gecko-Content-Viewers", aType, contractID);
8750 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
8751 docFactory = do_GetService(contractID.get());
8752 if (docFactory && aLoaderType) {
8753 if (contractID.EqualsLiteral(CONTENT_DLF_CONTRACTID"@mozilla.org/content/document-loader-factory;1"))
8754 *aLoaderType = TYPE_CONTENT;
8755 else
8756 *aLoaderType = TYPE_UNKNOWN;
8757 }
8758 return docFactory.forget();
8759 }
8760
8761 // If the type wasn't registered in `Gecko-Content-Viewers`, check if it's
8762 // another type which we may dynamically support, such as `text/*` types or
8763 // video document types. These types are all backed by the nsContentDLF.
8764 if (IsPlainTextType(aType) ||
8765 DecoderTraits::IsSupportedInVideoDocument(aType)) {
8766 docFactory = do_GetService(CONTENT_DLF_CONTRACTID"@mozilla.org/content/document-loader-factory;1");
8767 if (docFactory && aLoaderType) {
8768 *aLoaderType = TYPE_CONTENT;
8769 }
8770 return docFactory.forget();
8771 }
8772
8773 return nullptr;
8774}
8775
8776static void ReportPatternCompileFailure(nsAString& aPattern,
8777 const JS::RegExpFlags& aFlags,
8778 const Document* aDocument,
8779 JS::MutableHandle<JS::Value> error,
8780 JSContext* cx) {
8781 AutoTArray<nsString, 3> strings;
8782
8783 strings.AppendElement(aPattern);
8784
8785 std::stringstream flag_ss;
8786 flag_ss << aFlags;
8787 nsString* flagstr = strings.AppendElement();
8788 AppendUTF8toUTF16(flag_ss.str(), *flagstr);
8789
8790 JS::AutoSaveExceptionState savedExc(cx);
8791 JS::Rooted<JSObject*> exnObj(cx, &error.toObject());
8792 JS::Rooted<JS::Value> messageVal(cx);
8793 if (!JS_GetProperty(cx, exnObj, "message", &messageVal)) {
8794 return;
8795 }
8796 JS::Rooted<JSString*> messageStr(cx, messageVal.toString());
8797 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"
, 8797); AnnotateMozCrashReason("MOZ_ASSERT" "(" "messageStr"
")"); do { MOZ_CrashSequence(__null, 8797); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8798 if (!AssignJSString(cx, *strings.AppendElement(), messageStr)) {
8799 return;
8800 }
8801
8802 nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, "DOM"_ns,
8803 aDocument, PropertiesFile::DOM_PROPERTIES,
8804 "PatternAttributeCompileFailurev2", strings);
8805 savedExc.drop();
8806}
8807
8808// static
8809Maybe<bool> nsContentUtils::IsPatternMatching(const nsAString& aValue,
8810 nsString&& aPattern,
8811 const Document* aDocument,
8812 bool aHasMultiple,
8813 JS::RegExpFlags aFlags) {
8814 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"
, 8814); MOZ_PretendNoReturn(); } } while (0)
;
8815
8816 // The fact that we're using a JS regexp under the hood should not be visible
8817 // to things like window onerror handlers, so we don't initialize our JSAPI
8818 // with the document's window (which may not exist anyway).
8819 AutoJSAPI jsapi;
8820 jsapi.Init();
8821 JSContext* cx = jsapi.cx();
8822 AutoDisableJSInterruptCallback disabler(cx);
8823
8824 // We can use the junk scope here, because we're just using it for regexp
8825 // evaluation, not actual script execution, and we disable statics so that the
8826 // evaluation does not interact with the execution global.
8827 JSAutoRealm ar(cx, xpc::PrivilegedJunkScope());
8828
8829 // Check if the pattern by itself is valid first, and not that it only becomes
8830 // valid once we add ^(?: and )$.
8831 JS::Rooted<JS::Value> error(cx);
8832 if (!JS::CheckRegExpSyntax(cx, aPattern.BeginReading(), aPattern.Length(),
8833 aFlags, &error)) {
8834 return Nothing();
8835 }
8836
8837 if (!error.isUndefined()) {
8838 ReportPatternCompileFailure(aPattern, aFlags, aDocument, &error, cx);
8839 return Some(true);
8840 }
8841
8842 // The pattern has to match the entire value.
8843 aPattern.InsertLiteral(u"^(?:", 0);
8844 aPattern.AppendLiteral(")$");
8845
8846 JS::Rooted<JSObject*> re(
8847 cx, JS::NewUCRegExpObject(cx, aPattern.BeginReading(), aPattern.Length(),
8848 aFlags));
8849 if (!re) {
8850 return Nothing();
8851 }
8852
8853 JS::Rooted<JS::Value> rval(cx, JS::NullValue());
8854 if (!aHasMultiple) {
8855 size_t idx = 0;
8856 if (!JS::ExecuteRegExpNoStatics(cx, re, aValue.BeginReading(),
8857 aValue.Length(), &idx, true, &rval)) {
8858 return Nothing();
8859 }
8860 return Some(!rval.isNull());
8861 }
8862
8863 HTMLSplitOnSpacesTokenizer tokenizer(aValue, ',');
8864 while (tokenizer.hasMoreTokens()) {
8865 const nsAString& value = tokenizer.nextToken();
8866 size_t idx = 0;
8867 if (!JS::ExecuteRegExpNoStatics(cx, re, value.BeginReading(),
8868 value.Length(), &idx, true, &rval)) {
8869 return Nothing();
8870 }
8871 if (rval.isNull()) {
8872 return Some(false);
8873 }
8874 }
8875 return Some(true);
8876}
8877
8878// static
8879nsresult nsContentUtils::URIInheritsSecurityContext(nsIURI* aURI,
8880 bool* aResult) {
8881 // Note: about:blank URIs do NOT inherit the security context from the
8882 // current document, which is what this function tests for...
8883 return NS_URIChainHasFlags(
8884 aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, aResult);
8885}
8886
8887// static
8888bool nsContentUtils::ChannelShouldInheritPrincipal(
8889 nsIPrincipal* aLoadingPrincipal, nsIURI* aURI, bool aInheritForAboutBlank,
8890 bool aForceInherit) {
8891 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"
, 8892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Can not check inheritance without a principal" ")"); do
{ MOZ_CrashSequence(__null, 8892); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
8892 "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"
, 8892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingPrincipal"
") (" "Can not check inheritance without a principal" ")"); do
{ MOZ_CrashSequence(__null, 8892); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
8893
8894 // Only tell the channel to inherit if it can't provide its own security
8895 // context.
8896 //
8897 // XXX: If this is ever changed, check all callers for what owners
8898 // they're passing in. In particular, see the code and
8899 // comments in nsDocShell::LoadURI where we fall back on
8900 // inheriting the owner if called from chrome. That would be
8901 // very wrong if this code changed anything but channels that
8902 // can't provide their own security context!
8903 //
8904 // If aForceInherit is true, we will inherit, even for a channel that
8905 // can provide its own security context. This is used for srcdoc loads.
8906 bool inherit = aForceInherit;
8907 if (!inherit) {
8908 bool uriInherits;
8909 // We expect URIInheritsSecurityContext to return success for an
8910 // about:blank URI, so don't call NS_IsAboutBlank() if this call fails.
8911 // This condition needs to match the one in nsDocShell::InternalLoad where
8912 // we're checking for things that will use the owner.
8913 inherit =
8914 (NS_SUCCEEDED(URIInheritsSecurityContext(aURI, &uriInherits))((bool)(__builtin_expect(!!(!NS_FAILED_impl(URIInheritsSecurityContext
(aURI, &uriInherits))), 1)))
&&
8915 (uriInherits || (aInheritForAboutBlank &&
8916 NS_IsAboutBlankAllowQueryAndFragment(aURI)))) ||
8917 //
8918 // file: uri special-casing
8919 //
8920 // If this is a file: load opened from another file: then it may need
8921 // to inherit the owner from the referrer so they can script each other.
8922 // If we don't set the owner explicitly then each file: gets an owner
8923 // based on its own codebase later.
8924 //
8925 (URIIsLocalFile(aURI) &&
8926 NS_SUCCEEDED(aLoadingPrincipal->CheckMayLoad(aURI, false))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aLoadingPrincipal
->CheckMayLoad(aURI, false))), 1)))
&&
8927 // One more check here. CheckMayLoad will always return true for the
8928 // system principal, but we do NOT want to inherit in that case.
8929 !aLoadingPrincipal->IsSystemPrincipal());
8930 }
8931 return inherit;
8932}
8933
8934/* static */
8935bool nsContentUtils::IsCutCopyAllowed(Document* aDocument,
8936 nsIPrincipal& aSubjectPrincipal) {
8937 if (StaticPrefs::dom_allow_cut_copy() && aDocument &&
8938 aDocument->HasValidTransientUserGestureActivation()) {
8939 return true;
8940 }
8941
8942 return PrincipalHasPermission(aSubjectPrincipal, nsGkAtoms::clipboardWrite);
8943}
8944
8945/* static */
8946bool nsContentUtils::HaveEqualPrincipals(Document* aDoc1, Document* aDoc2) {
8947 if (!aDoc1 || !aDoc2) {
8948 return false;
8949 }
8950 bool principalsEqual = false;
8951 aDoc1->NodePrincipal()->Equals(aDoc2->NodePrincipal(), &principalsEqual);
8952 return principalsEqual;
8953}
8954
8955/* static */
8956const Document* nsContentUtils::GetInProcessSubtreeRootDocument(
8957 const Document* aDoc) {
8958 if (!aDoc) {
8959 return nullptr;
8960 }
8961 const Document* doc = aDoc;
8962 while (doc->GetInProcessParentDocument()) {
8963 doc = doc->GetInProcessParentDocument();
8964 }
8965 return doc;
8966}
8967
8968// static
8969bool nsContentUtils::IsPointInSelection(
8970 const mozilla::dom::Selection& aSelection, const nsINode& aNode,
8971 const uint32_t aOffset, const bool aAllowCrossShadowBoundary) {
8972 const bool selectionIsCollapsed =
8973 !aAllowCrossShadowBoundary
8974 ? aSelection.IsCollapsed()
8975 : aSelection.AreNormalAndCrossShadowBoundaryRangesCollapsed();
8976 if (selectionIsCollapsed) {
8977 return false;
8978 }
8979
8980 const uint32_t rangeCount = aSelection.RangeCount();
8981 for (const uint32_t i : IntegerRange(rangeCount)) {
8982 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", 8982); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aSelection.RangeCount() == rangeCount" ")"
); do { MOZ_CrashSequence(__null, 8982); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8983 RefPtr<const nsRange> range = aSelection.GetRangeAt(i);
8984 if (NS_WARN_IF(!range)NS_warn_if_impl(!range, "!range", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 8984)
) {
8985 // Don't bail yet, iterate through them all
8986 continue;
8987 }
8988
8989 // Done when we find a range that we are in
8990 if (range->IsPointInRange(aNode, aOffset, IgnoreErrors(),
8991 aAllowCrossShadowBoundary)) {
8992 return true;
8993 }
8994 }
8995
8996 return false;
8997}
8998
8999// static
9000void nsContentUtils::GetSelectionInTextControl(Selection* aSelection,
9001 Element* aRoot,
9002 uint32_t& aOutStartOffset,
9003 uint32_t& aOutEndOffset) {
9004 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", 9004); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aSelection && aRoot" ")"); do { MOZ_CrashSequence
(__null, 9004); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9005
9006 // We don't care which end of this selection is anchor and which is focus. In
9007 // fact, we explicitly want to know which is the _start_ and which is the
9008 // _end_, not anchor vs focus.
9009 const nsRange* range = aSelection->GetAnchorFocusRange();
9010 if (!range) {
9011 // Nothing selected
9012 aOutStartOffset = aOutEndOffset = 0;
9013 return;
9014 }
9015
9016 // All the node pointers here are raw pointers for performance. We shouldn't
9017 // be doing anything in this function that invalidates the node tree.
9018 nsINode* startContainer = range->GetStartContainer();
9019 uint32_t startOffset = range->StartOffset();
9020 nsINode* endContainer = range->GetEndContainer();
9021 uint32_t endOffset = range->EndOffset();
9022
9023 // We have at most two children, consisting of an optional text node followed
9024 // by an optional <br>.
9025 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", 9025); MOZ_PretendNoReturn
(); } } while (0)
;
9026 nsIContent* firstChild = aRoot->GetFirstChild();
9027#ifdef DEBUG1
9028 nsCOMPtr<nsIContent> lastChild = aRoot->GetLastChild();
9029 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", 9031); MOZ_PretendNoReturn
(); } } while (0)
9030 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", 9031); MOZ_PretendNoReturn
(); } } while (0)
9031 "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", 9031); MOZ_PretendNoReturn
(); } } while (0)
;
9032 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", 9034); MOZ_PretendNoReturn
(); } } while (0)
9033 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", 9034); MOZ_PretendNoReturn
(); } } while (0)
9034 "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", 9034); MOZ_PretendNoReturn
(); } } while (0)
;
9035 // firstChild is either text or a <br> (hence an element).
9036 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"
, 9036); AnnotateMozCrashReason("MOZ_ASSERT" "(" "firstChild->IsText() || firstChild->IsElement()"
")"); do { MOZ_CrashSequence(__null, 9036); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
9037#endif
9038 if (!firstChild || firstChild->IsElement()) {
9039 // No text node, so everything is 0
9040 startOffset = endOffset = 0;
9041 } else {
9042 // First child is text. If the start/end is already in the text node,
9043 // or the start of the root node, no change needed. If it's in the root
9044 // node but not the start, or in the trailing <br>, we need to set the
9045 // offset to the end.
9046 if ((startContainer == aRoot && startOffset != 0) ||
9047 (startContainer != aRoot && startContainer != firstChild)) {
9048 startOffset = firstChild->Length();
9049 }
9050 if ((endContainer == aRoot && endOffset != 0) ||
9051 (endContainer != aRoot && endContainer != firstChild)) {
9052 endOffset = firstChild->Length();
9053 }
9054 }
9055
9056 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", 9056); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "startOffset <= endOffset" ")"); do { MOZ_CrashSequence
(__null, 9056); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9057 aOutStartOffset = startOffset;
9058 aOutEndOffset = endOffset;
9059}
9060
9061// static
9062HTMLEditor* nsContentUtils::GetHTMLEditor(nsPresContext* aPresContext) {
9063 if (!aPresContext) {
9064 return nullptr;
9065 }
9066 return GetHTMLEditor(aPresContext->GetDocShell());
9067}
9068
9069// static
9070HTMLEditor* nsContentUtils::GetHTMLEditor(nsDocShell* aDocShell) {
9071 bool isEditable;
9072 if (!aDocShell || NS_FAILED(aDocShell->GetEditable(&isEditable))((bool)(__builtin_expect(!!(NS_FAILED_impl(aDocShell->GetEditable
(&isEditable))), 0)))
||
9073 !isEditable) {
9074 return nullptr;
9075 }
9076 return aDocShell->GetHTMLEditor();
9077}
9078
9079// static
9080EditorBase* nsContentUtils::GetActiveEditor(nsPresContext* aPresContext) {
9081 if (!aPresContext) {
9082 return nullptr;
9083 }
9084
9085 return GetActiveEditor(aPresContext->Document()->GetWindow());
9086}
9087
9088// static
9089EditorBase* nsContentUtils::GetActiveEditor(nsPIDOMWindowOuter* aWindow) {
9090 if (!aWindow || !aWindow->GetExtantDoc()) {
9091 return nullptr;
9092 }
9093
9094 // If it's in designMode, nobody can have focus. Therefore, the HTMLEditor
9095 // handles all events. I.e., it's focused editor in this case.
9096 if (aWindow->GetExtantDoc()->IsInDesignMode()) {
9097 return GetHTMLEditor(nsDocShell::Cast(aWindow->GetDocShell()));
9098 }
9099
9100 // If focused element is associated with TextEditor, it must be <input>
9101 // element or <textarea> element. Let's return it even if it's in a
9102 // contenteditable element.
9103 nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
9104 if (Element* focusedElement = nsFocusManager::GetFocusedDescendant(
9105 aWindow, nsFocusManager::SearchRange::eOnlyCurrentWindow,
9106 getter_AddRefs(focusedWindow))) {
9107 if (TextEditor* textEditor = focusedElement->GetTextEditorInternal()) {
9108 return textEditor;
9109 }
9110 }
9111
9112 // Otherwise, HTMLEditor may handle inputs even non-editable element has
9113 // focus or nobody has focus.
9114 return GetHTMLEditor(nsDocShell::Cast(aWindow->GetDocShell()));
9115}
9116
9117// static
9118TextEditor* nsContentUtils::GetExtantTextEditorFromAnonymousNode(
9119 const nsIContent* aAnonymousContent) {
9120 if (!aAnonymousContent) {
9121 return nullptr;
9122 }
9123 nsIContent* parent = aAnonymousContent->FindFirstNonChromeOnlyAccessContent();
9124 if (!parent || parent == aAnonymousContent) {
9125 return nullptr;
9126 }
9127 if (const HTMLInputElement* const inputElement =
9128 HTMLInputElement::FromNodeOrNull(parent)) {
9129 return inputElement->GetExtantTextEditor();
9130 }
9131 if (const HTMLTextAreaElement* const textareaElement =
9132 HTMLTextAreaElement::FromNodeOrNull(parent)) {
9133 return textareaElement->GetExtantTextEditor();
9134 }
9135 return nullptr;
9136}
9137
9138// static
9139bool nsContentUtils::IsNodeInEditableRegion(nsINode* aNode) {
9140 while (aNode) {
9141 if (aNode->IsEditable()) {
9142 return true;
9143 }
9144 aNode = aNode->GetParent();
9145 }
9146 return false;
9147}
9148
9149// static
9150bool nsContentUtils::IsForbiddenRequestHeader(const nsACString& aHeader,
9151 const nsACString& aValue) {
9152 if (IsForbiddenSystemRequestHeader(aHeader)) {
9153 return true;
9154 }
9155
9156 if ((nsContentUtils::IsOverrideMethodHeader(aHeader) &&
9157 nsContentUtils::ContainsForbiddenMethod(aValue))) {
9158 return true;
9159 }
9160
9161 if (StringBeginsWith(aHeader, "proxy-"_ns,
9162 nsCaseInsensitiveCStringComparator) ||
9163 StringBeginsWith(aHeader, "sec-"_ns,
9164 nsCaseInsensitiveCStringComparator)) {
9165 return true;
9166 }
9167
9168 return false;
9169}
9170
9171// static
9172bool nsContentUtils::IsForbiddenSystemRequestHeader(const nsACString& aHeader) {
9173 static const char* kInvalidHeaders[] = {"accept-charset",
9174 "accept-encoding",
9175 "access-control-request-headers",
9176 "access-control-request-method",
9177 "connection",
9178 "content-length",
9179 "cookie",
9180 "cookie2",
9181 "date",
9182 "dnt",
9183 "expect",
9184 "host",
9185 "keep-alive",
9186 "origin",
9187 "referer",
9188 "set-cookie",
9189 "te",
9190 "trailer",
9191 "transfer-encoding",
9192 "upgrade",
9193 "via"};
9194 for (auto& kInvalidHeader : kInvalidHeaders) {
9195 if (aHeader.LowerCaseEqualsASCII(kInvalidHeader)) {
9196 return true;
9197 }
9198 }
9199 return false;
9200}
9201
9202// static
9203bool nsContentUtils::IsForbiddenResponseHeader(const nsACString& aHeader) {
9204 return (aHeader.LowerCaseEqualsASCII("set-cookie") ||
9205 aHeader.LowerCaseEqualsASCII("set-cookie2"));
9206}
9207
9208// static
9209bool nsContentUtils::IsOverrideMethodHeader(const nsACString& headerName) {
9210 return headerName.EqualsIgnoreCase("x-http-method-override") ||
9211 headerName.EqualsIgnoreCase("x-http-method") ||
9212 headerName.EqualsIgnoreCase("x-method-override");
9213}
9214
9215// static
9216bool nsContentUtils::ContainsForbiddenMethod(const nsACString& headerValue) {
9217 bool hasInsecureMethod = false;
9218 nsCCharSeparatedTokenizer tokenizer(headerValue, ',');
9219
9220 while (tokenizer.hasMoreTokens()) {
9221 const nsDependentCSubstring& value = tokenizer.nextToken();
9222
9223 if (value.EqualsIgnoreCase("connect") || value.EqualsIgnoreCase("trace") ||
9224 value.EqualsIgnoreCase("track")) {
9225 hasInsecureMethod = true;
9226 break;
9227 }
9228 }
9229
9230 return hasInsecureMethod;
9231}
9232
9233Maybe<nsContentUtils::ParsedRange> nsContentUtils::ParseSingleRangeRequest(
9234 const nsACString& aHeaderValue, bool aAllowWhitespace) {
9235 // See https://fetch.spec.whatwg.org/#simple-range-header-value
9236 mozilla::Tokenizer p(aHeaderValue);
9237 Maybe<uint64_t> rangeStart;
9238 Maybe<uint64_t> rangeEnd;
9239
9240 // Step 2 and 3
9241 if (!p.CheckWord("bytes")) {
9242 return Nothing();
9243 }
9244
9245 // Step 4
9246 if (aAllowWhitespace) {
9247 p.SkipWhites();
9248 }
9249
9250 // Step 5 and 6
9251 if (!p.CheckChar('=')) {
9252 return Nothing();
9253 }
9254
9255 // Step 7
9256 if (aAllowWhitespace) {
9257 p.SkipWhites();
9258 }
9259
9260 // Step 8 and 9
9261 uint64_t res;
9262 if (p.ReadInteger(&res)) {
9263 rangeStart = Some(res);
9264 }
9265
9266 // Step 10
9267 if (aAllowWhitespace) {
9268 p.SkipWhites();
9269 }
9270
9271 // Step 11
9272 if (!p.CheckChar('-')) {
9273 return Nothing();
9274 }
9275
9276 // Step 13
9277 if (aAllowWhitespace) {
9278 p.SkipWhites();
9279 }
9280
9281 // Step 14 and 15
9282 if (p.ReadInteger(&res)) {
9283 rangeEnd = Some(res);
9284 }
9285
9286 // Step 16
9287 if (!p.CheckEOF()) {
9288 return Nothing();
9289 }
9290
9291 // Step 17
9292 if (!rangeStart && !rangeEnd) {
9293 return Nothing();
9294 }
9295
9296 // Step 18
9297 if (rangeStart && rangeEnd && *rangeStart > *rangeEnd) {
9298 return Nothing();
9299 }
9300
9301 return Some(ParsedRange(rangeStart, rangeEnd));
9302}
9303
9304// static
9305bool nsContentUtils::IsCorsUnsafeRequestHeaderValue(
9306 const nsACString& aHeaderValue) {
9307 const char* cur = aHeaderValue.BeginReading();
9308 const char* end = aHeaderValue.EndReading();
9309
9310 while (cur != end) {
9311 // Implementation of
9312 // https://fetch.spec.whatwg.org/#cors-unsafe-request-header-byte Is less
9313 // than a space but not a horizontal tab
9314 if ((*cur < ' ' && *cur != '\t') || *cur == '"' || *cur == '(' ||
9315 *cur == ')' || *cur == ':' || *cur == '<' || *cur == '>' ||
9316 *cur == '?' || *cur == '@' || *cur == '[' || *cur == '\\' ||
9317 *cur == ']' || *cur == '{' || *cur == '}' ||
9318 *cur == 0x7F) { // 0x75 is DEL
9319 return true;
9320 }
9321 cur++;
9322 }
9323 return false;
9324}
9325
9326// static
9327bool nsContentUtils::IsAllowedNonCorsAccept(const nsACString& aHeaderValue) {
9328 if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) {
9329 return false;
9330 }
9331 return true;
9332}
9333
9334// static
9335bool nsContentUtils::IsAllowedNonCorsContentType(
9336 const nsACString& aHeaderValue) {
9337 nsAutoCString contentType;
9338 nsAutoCString unused;
9339
9340 if (IsCorsUnsafeRequestHeaderValue(aHeaderValue)) {
9341 return false;
9342 }
9343
9344 nsresult rv = NS_ParseRequestContentType(aHeaderValue, contentType, unused);
9345 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9346 return false;
9347 }
9348
9349 return contentType.LowerCaseEqualsLiteral("text/plain") ||
9350 contentType.LowerCaseEqualsLiteral(
9351 "application/x-www-form-urlencoded") ||
9352 contentType.LowerCaseEqualsLiteral("multipart/form-data");
9353}
9354
9355// static
9356bool nsContentUtils::IsAllowedNonCorsLanguage(const nsACString& aHeaderValue) {
9357 const char* cur = aHeaderValue.BeginReading();
9358 const char* end = aHeaderValue.EndReading();
9359
9360 while (cur != end) {
9361 if ((*cur >= '0' && *cur <= '9') || (*cur >= 'A' && *cur <= 'Z') ||
9362 (*cur >= 'a' && *cur <= 'z') || *cur == ' ' || *cur == '*' ||
9363 *cur == ',' || *cur == '-' || *cur == '.' || *cur == ';' ||
9364 *cur == '=') {
9365 cur++;
9366 continue;
9367 }
9368 return false;
9369 }
9370 return true;
9371}
9372
9373bool nsContentUtils::IsAllowedNonCorsRange(const nsACString& aHeaderValue) {
9374 Maybe<ParsedRange> parsedRange = ParseSingleRangeRequest(aHeaderValue, false);
9375 if (!parsedRange) {
9376 return false;
9377 }
9378
9379 if (!parsedRange->Start()) {
9380 return false;
9381 }
9382
9383 return true;
9384}
9385
9386// static
9387bool nsContentUtils::IsCORSSafelistedRequestHeader(const nsACString& aName,
9388 const nsACString& aValue) {
9389 // see https://fetch.spec.whatwg.org/#cors-safelisted-request-header
9390 if (aValue.Length() > 128) {
9391 return false;
9392 }
9393 return (aName.LowerCaseEqualsLiteral("accept") &&
9394 nsContentUtils::IsAllowedNonCorsAccept(aValue)) ||
9395 (aName.LowerCaseEqualsLiteral("accept-language") &&
9396 nsContentUtils::IsAllowedNonCorsLanguage(aValue)) ||
9397 (aName.LowerCaseEqualsLiteral("content-language") &&
9398 nsContentUtils::IsAllowedNonCorsLanguage(aValue)) ||
9399 (aName.LowerCaseEqualsLiteral("content-type") &&
9400 nsContentUtils::IsAllowedNonCorsContentType(aValue)) ||
9401 (aName.LowerCaseEqualsLiteral("range") &&
9402 nsContentUtils::IsAllowedNonCorsRange(aValue)) ||
9403 (StaticPrefs::network_http_idempotencyKey_enabled() &&
9404 aName.LowerCaseEqualsLiteral("idempotency-key"));
9405}
9406
9407mozilla::LogModule* nsContentUtils::ResistFingerprintingLog() {
9408 return gResistFingerprintingLog;
9409}
9410mozilla::LogModule* nsContentUtils::DOMDumpLog() { return sDOMDumpLog; }
9411
9412bool nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep,
9413 nsAString& aResult,
9414 const fallible_t& aFallible) {
9415 aResult.Truncate();
9416 return AppendNodeTextContent(aNode, aDeep, aResult, aFallible);
9417}
9418
9419bool nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep,
9420 nsACString& aResult,
9421 const fallible_t& aFallible) {
9422 aResult.Truncate();
9423 return AppendNodeTextContent(aNode, aDeep, aResult, aFallible);
9424}
9425
9426void nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep,
9427 nsAString& aResult) {
9428 if (!GetNodeTextContent(aNode, aDeep, aResult, fallible)) {
9429 NS_ABORT_OOM(0); // Unfortunately we don't know the allocation size
9430 }
9431}
9432
9433void nsContentUtils::GetNodeTextContent(const nsINode* aNode, bool aDeep,
9434 nsACString& aResult) {
9435 if (!GetNodeTextContent(aNode, aDeep, aResult, fallible)) {
9436 NS_ABORT_OOM(0); // Unfortunately we don't know the allocation size
9437 }
9438}
9439
9440void nsContentUtils::DestroyMatchString(void* aData) {
9441 if (aData) {
9442 nsString* matchString = static_cast<nsString*>(aData);
9443 delete matchString;
9444 }
9445}
9446
9447// Table ordered from most to least likely JS MIME types.
9448static constexpr std::string_view kJavascriptMIMETypes[] = {
9449 "text/javascript",
9450 "text/ecmascript",
9451 "application/javascript",
9452 "application/ecmascript",
9453 "application/x-javascript",
9454 "application/x-ecmascript",
9455 "text/javascript1.0",
9456 "text/javascript1.1",
9457 "text/javascript1.2",
9458 "text/javascript1.3",
9459 "text/javascript1.4",
9460 "text/javascript1.5",
9461 "text/jscript",
9462 "text/livescript",
9463 "text/x-ecmascript",
9464 "text/x-javascript"};
9465
9466bool nsContentUtils::IsJavascriptMIMEType(const nsAString& aMIMEType) {
9467 for (std::string_view type : kJavascriptMIMETypes) {
9468 if (aMIMEType.LowerCaseEqualsASCII(type.data(), type.length())) {
9469 return true;
9470 }
9471 }
9472 return false;
9473}
9474
9475bool nsContentUtils::IsJavascriptMIMEType(const nsACString& aMIMEType) {
9476 for (std::string_view type : kJavascriptMIMETypes) {
9477 if (aMIMEType.LowerCaseEqualsASCII(type.data(), type.length())) {
9478 return true;
9479 }
9480 }
9481 return false;
9482}
9483
9484// https://mimesniff.spec.whatwg.org/#json-mime-type
9485bool nsContentUtils::IsJsonMimeType(const nsAString& aMimeType) {
9486 // Table ordered from most to least likely JSON MIME types.
9487 static constexpr std::string_view jsonTypes[] = {"application/json",
9488 "text/json"};
9489
9490 for (std::string_view type : jsonTypes) {
9491 if (aMimeType.LowerCaseEqualsASCII(type.data(), type.length())) {
9492 return true;
9493 }
9494 }
9495
9496 // Below checks if the 'subtype' ends in "+json".
9497 RefPtr<MimeType> parsed = MimeType::Parse(aMimeType);
9498 if (!parsed) {
9499 return false;
9500 }
9501
9502 nsAutoString subtype;
9503 parsed->GetSubtype(subtype);
9504 return StringEndsWith(subtype, u"+json"_ns);
9505}
9506
9507// https://html.spec.whatwg.org/#fetch-a-single-module-script, 13.7.3
9508bool nsContentUtils::HasCssMimeTypeEssence(const nsAString& aMimeType) {
9509 nsString contentType, contentCharset;
9510 if (MimeType::Parse(aMimeType, contentType, contentCharset)) {
9511 return contentType.LowerCaseEqualsLiteral("text/css");
9512 }
9513 return false;
9514}
9515
9516// https://html.spec.whatwg.org/#fetch-a-single-module-script, 13.6
9517bool nsContentUtils::HasWasmMimeTypeEssence(const nsAString& aMimeType) {
9518 nsString contentType, contentCharset;
9519 if (MimeType::Parse(aMimeType, contentType, contentCharset)) {
9520 return contentType.LowerCaseEqualsLiteral("application/wasm");
9521 }
9522 return false;
9523}
9524
9525bool nsContentUtils::PrefetchPreloadEnabled(nsIDocShell* aDocShell) {
9526 //
9527 // SECURITY CHECK: disable prefetching and preloading from mailnews!
9528 //
9529 // walk up the docshell tree to see if any containing
9530 // docshell are of type MAIL.
9531 //
9532
9533 if (!aDocShell) {
9534 return false;
9535 }
9536
9537 nsCOMPtr<nsIDocShell> docshell = aDocShell;
9538 nsCOMPtr<nsIDocShellTreeItem> parentItem;
9539
9540 do {
9541 auto appType = docshell->GetAppType();
9542 if (appType == nsIDocShell::APP_TYPE_MAIL) {
9543 return false; // do not prefetch, preload, preconnect from mailnews
9544 }
9545
9546 docshell->GetInProcessParent(getter_AddRefs(parentItem));
9547 if (parentItem) {
9548 docshell = do_QueryInterface(parentItem);
9549 if (!docshell) {
9550 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",
9550); MOZ_PretendNoReturn(); } while (0)
;
9551 return false;
9552 }
9553 }
9554 } while (parentItem);
9555
9556 return true;
9557}
9558
9559uint64_t nsContentUtils::GetInnerWindowID(nsIRequest* aRequest) {
9560 // can't do anything if there's no nsIRequest!
9561 if (!aRequest) {
9562 return 0;
9563 }
9564
9565 if (nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest)) {
9566 nsCOMPtr loadInfo = channel->LoadInfo();
9567 if (auto id = loadInfo->GetInnerWindowID()) {
9568 return id;
9569 }
9570 if (auto id = loadInfo->GetTriggeringWindowId()) {
9571 return id;
9572 }
9573 }
9574
9575 nsCOMPtr<nsILoadGroup> loadGroup;
9576 nsresult rv = aRequest->GetLoadGroup(getter_AddRefs(loadGroup));
9577
9578 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !loadGroup) {
9579 return 0;
9580 }
9581
9582 return GetInnerWindowID(loadGroup);
9583}
9584
9585uint64_t nsContentUtils::GetInnerWindowID(nsILoadGroup* aLoadGroup) {
9586 if (!aLoadGroup) {
9587 return 0;
9588 }
9589
9590 nsCOMPtr<nsIInterfaceRequestor> callbacks;
9591 nsresult rv = aLoadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
9592 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !callbacks) {
9593 return 0;
9594 }
9595
9596 nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
9597 if (!loadContext) {
9598 return 0;
9599 }
9600
9601 nsCOMPtr<mozIDOMWindowProxy> window;
9602 rv = loadContext->GetAssociatedWindow(getter_AddRefs(window));
9603 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !window) {
9604 return 0;
9605 }
9606
9607 auto* pwindow = nsPIDOMWindowOuter::From(window);
9608 if (!pwindow) {
9609 return 0;
9610 }
9611
9612 nsPIDOMWindowInner* inner = pwindow->GetCurrentInnerWindow();
9613 return inner ? inner->WindowID() : 0;
9614}
9615
9616// static
9617void nsContentUtils::MaybeFixIPv6Host(nsACString& aHost) {
9618 if (aHost.FindChar(':') != -1) { // Escape IPv6 address
9619 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", 9619); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!aHost.IsEmpty()" ")"); do { MOZ_CrashSequence
(__null, 9619); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9620 if (aHost.Length() >= 2 && aHost[0] != '[' &&
9621 aHost[aHost.Length() - 1] != ']') {
9622 aHost.Insert('[', 0);
9623 aHost.Append(']');
9624 }
9625 }
9626}
9627
9628nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI,
9629 nsACString& aHost) {
9630 aHost.Truncate();
9631 nsresult rv = aURI->GetHost(aHost);
9632 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { // Some URIs do not have a host
9633 return rv;
9634 }
9635
9636 MaybeFixIPv6Host(aHost);
9637
9638 return NS_OK;
9639}
9640
9641nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIURI* aURI,
9642 nsAString& aHost) {
9643 nsAutoCString hostname;
9644 nsresult rv = GetHostOrIPv6WithBrackets(aURI, hostname);
9645 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9646 return rv;
9647 }
9648 CopyUTF8toUTF16(hostname, aHost);
9649 return NS_OK;
9650}
9651
9652nsresult nsContentUtils::GetHostOrIPv6WithBrackets(nsIPrincipal* aPrincipal,
9653 nsACString& aHost) {
9654 nsresult rv = aPrincipal->GetAsciiHost(aHost);
9655 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { // Some URIs do not have a host
9656 return rv;
9657 }
9658
9659 MaybeFixIPv6Host(aHost);
9660 return NS_OK;
9661}
9662
9663nsresult nsContentUtils::GetAsciiHostOrIPv6WithBrackets(nsIURI* aURI,
9664 nsACString& aHost) {
9665 aHost.Truncate();
9666 nsresult rv = aURI->GetAsciiHost(aHost);
9667 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9668 return rv;
9669 }
9670
9671 MaybeFixIPv6Host(aHost);
9672 return NS_OK;
9673}
9674
9675CallState nsContentUtils::CallOnAllRemoteChildren(
9676 MessageBroadcaster* aManager,
9677 const std::function<CallState(BrowserParent*)>& aCallback) {
9678 uint32_t browserChildCount = aManager->ChildCount();
9679 for (uint32_t j = 0; j < browserChildCount; ++j) {
9680 RefPtr<MessageListenerManager> childMM = aManager->GetChildAt(j);
9681 if (!childMM) {
9682 continue;
9683 }
9684
9685 RefPtr<MessageBroadcaster> nonLeafMM = MessageBroadcaster::From(childMM);
9686 if (nonLeafMM) {
9687 if (CallOnAllRemoteChildren(nonLeafMM, aCallback) == CallState::Stop) {
9688 return CallState::Stop;
9689 }
9690 continue;
9691 }
9692
9693 mozilla::dom::ipc::MessageManagerCallback* cb = childMM->GetCallback();
9694 if (cb) {
9695 nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb);
9696 BrowserParent* remote = BrowserParent::GetFrom(fl);
9697 if (remote && aCallback) {
9698 if (aCallback(remote) == CallState::Stop) {
9699 return CallState::Stop;
9700 }
9701 }
9702 }
9703 }
9704
9705 return CallState::Continue;
9706}
9707
9708void nsContentUtils::CallOnAllRemoteChildren(
9709 nsPIDOMWindowOuter* aWindow,
9710 const std::function<CallState(BrowserParent*)>& aCallback) {
9711 nsGlobalWindowOuter* window = nsGlobalWindowOuter::Cast(aWindow);
9712 if (window->IsChromeWindow()) {
9713 RefPtr<MessageBroadcaster> windowMM = window->GetMessageManager();
9714 if (windowMM) {
9715 CallOnAllRemoteChildren(windowMM, aCallback);
9716 }
9717 }
9718}
9719
9720bool nsContentUtils::IPCTransferableDataItemHasKnownFlavor(
9721 const IPCTransferableDataItem& aItem) {
9722 // Unknown types are converted to kCustomTypesMime.
9723 if (aItem.flavor().EqualsASCII(kCustomTypesMime"application/x-moz-custom-clipdata")) {
9724 return true;
9725 }
9726
9727 for (const char* format : DataTransfer::kKnownFormats) {
9728 if (aItem.flavor().EqualsASCII(format)) {
9729 return true;
9730 }
9731 }
9732
9733 // Clipboard custom type. Only recognise "web foo/bar" as a known flavor
9734 // when the web custom format feature is enabled; otherwise DnD or other
9735 // callers must not be able to slip web custom flavors through this helper.
9736 const nsCString& flavor = aItem.flavor();
9737 if (StaticPrefs::dom_clipboard_customFormatSupport_enabled() &&
9738 StringBeginsWith(flavor, nsLiteralCString(kWebCustomFormatPrefix"web "))) {
9739 if (RefPtr<CMimeType> parsedType = CMimeType::Parse(Substring(
9740 flavor, strlen(kWebCustomFormatPrefix"web "), flavor.Length()))) {
9741 return true;
9742 }
9743 }
9744
9745 return false;
9746}
9747
9748nsresult nsContentUtils::IPCTransferableDataToTransferable(
9749 const IPCTransferableData& aTransferableData, bool aAddDataFlavor,
9750 nsITransferable* aTransferable, const bool aFilterUnknownFlavors) {
9751 nsresult rv;
9752 const nsTArray<IPCTransferableDataItem>& items = aTransferableData.items();
9753 for (const auto& item : items) {
9754 if (aFilterUnknownFlavors) {
9755 if (item.flavor().EqualsLiteral(kFilePromiseDirectoryMime"application/x-moz-file-promise-dir")) {
9756 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9758)
9757 "Ignoring unknown flavor in "NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9758)
9758 "nsContentUtils::IPCTransferableDataToTransferable")NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9758)
;
9759 continue;
9760 }
9761
9762 if ((item.flavor().EqualsLiteral(kFilePromiseMime"application/x-moz-file-promise") ||
9763 item.flavor().EqualsLiteral(kFilePromiseURLMime"application/x-moz-file-promise-url") ||
9764 item.flavor().EqualsLiteral(kFilePromiseDestFilename"application/x-moz-file-promise-dest-filename"))
9765#ifdef XP_WIN
9766 && !StaticPrefs::clipboard_imageAsFile_enabled()
9767#endif
9768 ) {
9769 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9771)
9770 "Ignoring unknown flavor in "NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9771)
9771 "nsContentUtils::IPCTransferableDataToTransferable")NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9771)
;
9772 continue;
9773 }
9774
9775 if (!IPCTransferableDataItemHasKnownFlavor(item)) {
9776 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9778)
9777 "Ignoring unknown flavor in "NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9778)
9778 "nsContentUtils::IPCTransferableDataToTransferable")NS_DebugBreak(NS_DEBUG_WARNING, "Ignoring unknown flavor in "
"nsContentUtils::IPCTransferableDataToTransferable", nullptr
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 9778)
;
9779 continue;
9780 }
9781 }
9782
9783 if (aAddDataFlavor) {
9784 aTransferable->AddDataFlavor(item.flavor().get());
9785 }
9786
9787 nsCOMPtr<nsISupports> transferData;
9788 switch (item.data().type()) {
9789 case IPCTransferableDataType::TIPCTransferableDataString: {
9790 const auto& data = item.data().get_IPCTransferableDataString();
9791 nsCOMPtr<nsISupportsString> dataWrapper =
9792 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID"@mozilla.org/supports-string;1", &rv);
9793 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"
, 9793); return rv; } } while (false)
;
9794 rv = dataWrapper->SetData(nsDependentSubstring(
9795 reinterpret_cast<const char16_t*>(data.data().Data()),
9796 data.data().Size() / sizeof(char16_t)));
9797 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"
, 9797); return rv; } } while (false)
;
9798 transferData = dataWrapper;
9799 break;
9800 }
9801 case IPCTransferableDataType::TIPCTransferableDataCString: {
9802 const auto& data = item.data().get_IPCTransferableDataCString();
9803 nsCOMPtr<nsISupportsCString> dataWrapper =
9804 do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID"@mozilla.org/supports-cstring;1", &rv);
9805 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"
, 9805); return rv; } } while (false)
;
9806 rv = dataWrapper->SetData(nsDependentCSubstring(
9807 reinterpret_cast<const char*>(data.data().Data()),
9808 data.data().Size()));
9809 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"
, 9809); return rv; } } while (false)
;
9810 transferData = dataWrapper;
9811 break;
9812 }
9813 case IPCTransferableDataType::TIPCTransferableDataInputStream: {
9814 const auto& data = item.data().get_IPCTransferableDataInputStream();
9815 nsCOMPtr<nsIInputStream> stream;
9816 rv = NS_NewByteInputStream(getter_AddRefs(stream),
9817 AsChars(data.data().AsSpan()),
9818 NS_ASSIGNMENT_COPY);
9819 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"
, 9819); return rv; } } while (false)
;
9820 transferData = stream.forget();
9821 break;
9822 }
9823 case IPCTransferableDataType::TIPCTransferableDataImageContainer: {
9824 const auto& data = item.data().get_IPCTransferableDataImageContainer();
9825 nsCOMPtr<imgIContainer> container = IPCImageToImage(data.image());
9826 if (!container) {
9827 return NS_ERROR_FAILURE;
9828 }
9829 transferData = container;
9830 break;
9831 }
9832 case IPCTransferableDataType::TIPCTransferableDataBlob: {
9833 const auto& data = item.data().get_IPCTransferableDataBlob();
9834 transferData = IPCBlobUtils::Deserialize(data.blob());
9835 break;
9836 }
9837 case IPCTransferableDataType::T__None:
9838 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", 9838
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
")"); do { MOZ_CrashSequence(__null, 9838); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9839 return NS_ERROR_FAILURE;
9840 }
9841
9842 rv = aTransferable->SetTransferData(item.flavor().get(), transferData);
9843 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"
, 9843); return rv; } } while (false)
;
9844 }
9845 return NS_OK;
9846}
9847
9848nsresult nsContentUtils::IPCTransferableToTransferable(
9849 const IPCTransferable& aIPCTransferable, bool aAddDataFlavor,
9850 nsITransferable* aTransferable, const bool aFilterUnknownFlavors) {
9851 // Note that we need to set privacy status of transferable before adding any
9852 // data into it.
9853 aTransferable->SetIsPrivateData(aIPCTransferable.isPrivateData());
9854
9855 nsresult rv =
9856 IPCTransferableDataToTransferable(aIPCTransferable.data(), aAddDataFlavor,
9857 aTransferable, aFilterUnknownFlavors);
9858 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"
, 9858); return rv; } } while (false)
;
9859
9860 if (aIPCTransferable.cookieJarSettings().isSome()) {
9861 nsCOMPtr<nsICookieJarSettings> cookieJarSettings;
9862 net::CookieJarSettings::Deserialize(
9863 aIPCTransferable.cookieJarSettings().ref(),
9864 getter_AddRefs(cookieJarSettings));
9865 aTransferable->SetCookieJarSettings(cookieJarSettings);
9866 }
9867 aTransferable->SetReferrerInfo(aIPCTransferable.referrerInfo());
9868 aTransferable->SetDataPrincipal(aIPCTransferable.dataPrincipal());
9869 aTransferable->SetContentPolicyType(aIPCTransferable.contentPolicyType());
9870
9871 return NS_OK;
9872}
9873
9874nsresult nsContentUtils::IPCTransferableDataItemToVariant(
9875 const IPCTransferableDataItem& aItem, nsIWritableVariant* aVariant) {
9876 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"
, 9876); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aVariant" ")"
); do { MOZ_CrashSequence(__null, 9876); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9877
9878 switch (aItem.data().type()) {
9879 case IPCTransferableDataType::TIPCTransferableDataString: {
9880 const auto& data = aItem.data().get_IPCTransferableDataString();
9881 return aVariant->SetAsAString(nsDependentSubstring(
9882 reinterpret_cast<const char16_t*>(data.data().Data()),
9883 data.data().Size() / sizeof(char16_t)));
9884 }
9885 case IPCTransferableDataType::TIPCTransferableDataCString: {
9886 const auto& data = aItem.data().get_IPCTransferableDataCString();
9887 return aVariant->SetAsACString(nsDependentCSubstring(
9888 reinterpret_cast<const char*>(data.data().Data()),
9889 data.data().Size()));
9890 }
9891 case IPCTransferableDataType::TIPCTransferableDataInputStream: {
9892 const auto& data = aItem.data().get_IPCTransferableDataInputStream();
9893 nsCOMPtr<nsIInputStream> stream;
9894 nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
9895 AsChars(data.data().AsSpan()),
9896 NS_ASSIGNMENT_COPY);
9897 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"
, 9897); return rv; } } while (false)
;
9898 return aVariant->SetAsISupports(stream);
9899 }
9900 case IPCTransferableDataType::TIPCTransferableDataImageContainer: {
9901 const auto& data = aItem.data().get_IPCTransferableDataImageContainer();
9902 nsCOMPtr<imgIContainer> container = IPCImageToImage(data.image());
9903 if (!container) {
9904 return NS_ERROR_FAILURE;
9905 }
9906 return aVariant->SetAsISupports(container);
9907 }
9908 case IPCTransferableDataType::TIPCTransferableDataBlob: {
9909 const auto& data = aItem.data().get_IPCTransferableDataBlob();
9910 RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(data.blob());
9911 return aVariant->SetAsISupports(blobImpl);
9912 }
9913 case IPCTransferableDataType::T__None:
9914 break;
9915 }
9916
9917 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", 9917
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
")"); do { MOZ_CrashSequence(__null, 9917); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9918 return NS_ERROR_UNEXPECTED;
9919}
9920
9921void nsContentUtils::TransferablesToIPCTransferableDatas(
9922 nsIArray* aTransferables, nsTArray<IPCTransferableData>& aIPC,
9923 bool aInSyncMessage, mozilla::dom::ContentParent* aParent) {
9924 aIPC.Clear();
9925 if (aTransferables) {
9926 uint32_t transferableCount = 0;
9927 aTransferables->GetLength(&transferableCount);
9928 for (uint32_t i = 0; i < transferableCount; ++i) {
9929 IPCTransferableData* dt = aIPC.AppendElement();
9930 nsCOMPtr<nsITransferable> transferable =
9931 do_QueryElementAt(aTransferables, i);
9932 TransferableToIPCTransferableData(transferable, dt, aInSyncMessage,
9933 aParent);
9934 }
9935 }
9936}
9937
9938nsresult nsContentUtils::CalculateBufferSizeForImage(
9939 const uint32_t& aStride, const IntSize& aImageSize,
9940 const SurfaceFormat& aFormat, size_t* aMaxBufferSize,
9941 size_t* aUsedBufferSize) {
9942 if (aImageSize.width <= 0 || aImageSize.height <= 0) {
9943 return NS_ERROR_FAILURE;
9944 }
9945
9946 CheckedInt32 rowBytes =
9947 CheckedInt32(aImageSize.width) * BytesPerPixel(aFormat);
9948 CheckedInt32 stride(aStride);
9949 if (!rowBytes.isValid() || !stride.isValid() ||
9950 stride.value() < rowBytes.value()) {
9951 return NS_ERROR_FAILURE;
9952 }
9953
9954 CheckedInt32 requiredBytes = stride * CheckedInt32(aImageSize.height);
9955 CheckedInt32 usedBytes = requiredBytes - stride + rowBytes;
9956 if (!requiredBytes.isValid() || !usedBytes.isValid()) {
9957 return NS_ERROR_FAILURE;
9958 }
9959
9960 *aMaxBufferSize = requiredBytes.value();
9961 *aUsedBufferSize = usedBytes.value();
9962 return NS_OK;
9963}
9964
9965static already_AddRefed<DataSourceSurface> BigBufferToDataSurface(
9966 const BigBuffer& aData, uint32_t aStride, const IntSize& aImageSize,
9967 SurfaceFormat aFormat) {
9968 if (!aData.Size() || !aImageSize.width || !aImageSize.height) {
9969 return nullptr;
9970 }
9971
9972 // Validate shared memory buffer size
9973 size_t imageBufLen = 0;
9974 size_t maxBufLen = 0;
9975 if (NS_FAILED(nsContentUtils::CalculateBufferSizeForImage(((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::CalculateBufferSizeForImage
( aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen
))), 0)))
9976 aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen))((bool)(__builtin_expect(!!(NS_FAILED_impl(nsContentUtils::CalculateBufferSizeForImage
( aStride, aImageSize, aFormat, &maxBufLen, &imageBufLen
))), 0)))
) {
9977 return nullptr;
9978 }
9979 if (imageBufLen > aData.Size()) {
9980 return nullptr;
9981 }
9982 return CreateDataSourceSurfaceFromData(aImageSize, aFormat, aData.Data(),
9983 aStride);
9984}
9985
9986bool nsContentUtils::IsFlavorImage(const nsACString& aFlavor) {
9987 return aFlavor.EqualsLiteral(kNativeImageMime"application/x-moz-nativeimage") ||
9988 aFlavor.EqualsLiteral(kJPEGImageMime"image/jpeg") ||
9989 aFlavor.EqualsLiteral(kJPGImageMime"image/jpg") ||
9990 aFlavor.EqualsLiteral(kPNGImageMime"image/png") ||
9991 aFlavor.EqualsLiteral(kGIFImageMime"image/gif");
9992}
9993
9994// FIXME: This can probably be removed once bug 1783240 lands, as `nsString`
9995// will be implicitly serialized in shmem when sent over IPDL directly.
9996static IPCTransferableDataString AsIPCTransferableDataString(
9997 Span<const char16_t> aInput) {
9998 return IPCTransferableDataString{BigBuffer(AsBytes(aInput))};
9999}
10000
10001// FIXME: This can probably be removed once bug 1783240 lands, as `nsCString`
10002// will be implicitly serialized in shmem when sent over IPDL directly.
10003static IPCTransferableDataCString AsIPCTransferableDataCString(
10004 Span<const char> aInput) {
10005 return IPCTransferableDataCString{BigBuffer(AsBytes(aInput))};
10006}
10007
10008void nsContentUtils::TransferableToIPCTransferableData(
10009 nsITransferable* aTransferable, IPCTransferableData* aTransferableData,
10010 bool aInSyncMessage, mozilla::dom::ContentParent* aParent) {
10011 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"
, 10011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aParent" ")"
); do { MOZ_CrashSequence(__null, 10011); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
10012
10013 if (aTransferable) {
10014 nsTArray<nsCString> flavorList;
10015 aTransferable->FlavorsTransferableCanExport(flavorList);
10016
10017 for (uint32_t j = 0; j < flavorList.Length(); ++j) {
10018 nsCString& flavorStr = flavorList[j];
10019 if (!flavorStr.Length()) {
10020 continue;
10021 }
10022
10023 nsCOMPtr<nsISupports> data;
10024 nsresult rv =
10025 aTransferable->GetTransferData(flavorStr.get(), getter_AddRefs(data));
10026
10027 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !data) {
10028 if (aInSyncMessage) {
10029 // Can't do anything.
10030 // FIXME: This shouldn't be the case anymore!
10031 continue;
10032 }
10033
10034 // This is a hack to support kFilePromiseMime.
10035 // On Windows there just needs to be an entry for it,
10036 // and for OSX we need to create
10037 // nsContentAreaDragDropDataProvider as nsIFlavorDataProvider.
10038 if (flavorStr.EqualsLiteral(kFilePromiseMime"application/x-moz-file-promise")) {
10039 IPCTransferableDataItem* item =
10040 aTransferableData->items().AppendElement();
10041 item->flavor() = flavorStr;
10042 item->data() =
10043 AsIPCTransferableDataString(NS_ConvertUTF8toUTF16(flavorStr));
10044 continue;
10045 }
10046
10047 // Empty element, transfer only the flavor
10048 IPCTransferableDataItem* item =
10049 aTransferableData->items().AppendElement();
10050 item->flavor() = flavorStr;
10051 item->data() = AsIPCTransferableDataString(EmptyString());
10052 continue;
10053 }
10054
10055 // We need to handle nsIInputStream before nsISupportsCString, otherwise
10056 // nsStringInputStream would be converted into a wrong type.
10057 if (nsCOMPtr<nsIInputStream> stream = do_QueryInterface(data)) {
10058 IPCTransferableDataItem* item =
10059 aTransferableData->items().AppendElement();
10060 item->flavor() = flavorStr;
10061 nsCString imageData;
10062 DebugOnly<nsresult> rv =
10063 NS_ConsumeStream(stream, UINT32_MAX(4294967295U), imageData);
10064 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", 10066
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK"
") (" "cannot use async input streams in nsITransferable right now"
")"); do { MOZ_CrashSequence(__null, 10066); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10065 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", 10066
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK"
") (" "cannot use async input streams in nsITransferable right now"
")"); do { MOZ_CrashSequence(__null, 10066); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10066 "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", 10066
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "rv != NS_BASE_STREAM_WOULD_BLOCK"
") (" "cannot use async input streams in nsITransferable right now"
")"); do { MOZ_CrashSequence(__null, 10066); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10067 // FIXME: This can probably be simplified once bug 1783240 lands, as
10068 // `nsCString` will be implicitly serialized in shmem when sent over
10069 // IPDL directly.
10070 item->data() =
10071 IPCTransferableDataInputStream(BigBuffer(AsBytes(Span(imageData))));
10072 continue;
10073 }
10074
10075 if (nsCOMPtr<nsISupportsString> text = do_QueryInterface(data)) {
10076 nsAutoString dataAsString;
10077 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", 10077); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(text->GetData(dataAsString))" ")"
); do { MOZ_CrashSequence(__null, 10077); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
10078
10079 IPCTransferableDataItem* item =
10080 aTransferableData->items().AppendElement();
10081 item->flavor() = flavorStr;
10082 item->data() = AsIPCTransferableDataString(dataAsString);
10083 continue;
10084 }
10085
10086 if (nsCOMPtr<nsISupportsCString> ctext = do_QueryInterface(data)) {
10087 nsAutoCString dataAsString;
10088 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", 10088); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(ctext->GetData(dataAsString))"
")"); do { MOZ_CrashSequence(__null, 10088); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
10089
10090 IPCTransferableDataItem* item =
10091 aTransferableData->items().AppendElement();
10092 item->flavor() = flavorStr;
10093 item->data() = AsIPCTransferableDataCString(dataAsString);
10094 continue;
10095 }
10096
10097 if (nsCOMPtr<imgIContainer> image = do_QueryInterface(data)) {
10098 // Images to be placed on the clipboard are imgIContainers.
10099 RefPtr<mozilla::gfx::SourceSurface> surface = image->GetFrame(
10100 imgIContainer::FRAME_CURRENT,
10101 imgIContainer::FLAG_SYNC_DECODE | imgIContainer::FLAG_ASYNC_NOTIFY);
10102 if (!surface) {
10103 continue;
10104 }
10105 RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
10106 surface->GetDataSurface();
10107 if (!dataSurface) {
10108 continue;
10109 }
10110
10111 auto imageData = nsContentUtils::SurfaceToIPCImage(*dataSurface);
10112 if (!imageData) {
10113 continue;
10114 }
10115
10116 IPCTransferableDataItem* item =
10117 aTransferableData->items().AppendElement();
10118 item->flavor() = flavorStr;
10119 item->data() = IPCTransferableDataImageContainer(std::move(*imageData));
10120 continue;
10121 }
10122
10123 // Otherwise, handle this as a file.
10124 nsCOMPtr<BlobImpl> blobImpl;
10125 if (nsCOMPtr<nsIFile> file = do_QueryInterface(data)) {
10126 if (aParent) {
10127 bool isDir = false;
10128 if (NS_SUCCEEDED(file->IsDirectory(&isDir))((bool)(__builtin_expect(!!(!NS_FAILED_impl(file->IsDirectory
(&isDir))), 1)))
&& isDir) {
10129 nsAutoString path;
10130 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", 10130)
) {
10131 continue;
10132 }
10133
10134 RefPtr<FileSystemSecurity> fss = FileSystemSecurity::GetOrCreate();
10135 fss->GrantAccessToContentProcess(aParent->ChildID(), path);
10136 }
10137 }
10138
10139 blobImpl = new FileBlobImpl(file);
10140
10141 IgnoredErrorResult rv;
10142
10143 // Ensure that file data is cached no that the content process
10144 // has this data available to it when passed over:
10145 blobImpl->GetSize(rv);
10146 if (NS_WARN_IF(rv.Failed())NS_warn_if_impl(rv.Failed(), "rv.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10146)
) {
10147 continue;
10148 }
10149
10150 blobImpl->GetLastModified(rv);
10151 if (NS_WARN_IF(rv.Failed())NS_warn_if_impl(rv.Failed(), "rv.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 10151)
) {
10152 continue;
10153 }
10154 } else {
10155 if (aInSyncMessage) {
10156 // Can't do anything.
10157 // FIXME: This shouldn't be the case anymore!
10158 continue;
10159 }
10160
10161 blobImpl = do_QueryInterface(data);
10162 }
10163
10164 if (blobImpl) {
10165 // If we failed to create the blob actor, then this blob probably
10166 // can't get the file size for the underlying file, ignore it for
10167 // now. TODO pass this through anyway.
10168 IPCBlob ipcBlob;
10169 nsresult rv = IPCBlobUtils::Serialize(blobImpl, ipcBlob);
10170 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"
, 10170)
) {
10171 continue;
10172 }
10173
10174 IPCTransferableDataItem* item =
10175 aTransferableData->items().AppendElement();
10176 item->flavor() = flavorStr;
10177 item->data() = IPCTransferableDataBlob(ipcBlob);
10178 }
10179 }
10180 }
10181}
10182
10183void nsContentUtils::TransferableToIPCTransferable(
10184 nsITransferable* aTransferable, IPCTransferable* aIPCTransferable,
10185 bool aInSyncMessage, mozilla::dom::ContentParent* aParent) {
10186 IPCTransferableData ipcTransferableData;
10187 TransferableToIPCTransferableData(aTransferable, &ipcTransferableData,
10188 aInSyncMessage, aParent);
10189
10190 Maybe<net::CookieJarSettingsArgs> cookieJarSettingsArgs;
10191 if (nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
10192 aTransferable->GetCookieJarSettings()) {
10193 net::CookieJarSettingsArgs args;
10194 net::CookieJarSettings::Cast(cookieJarSettings)->Serialize(args);
10195 cookieJarSettingsArgs = Some(std::move(args));
10196 }
10197
10198 aIPCTransferable->data() = std::move(ipcTransferableData);
10199 aIPCTransferable->isPrivateData() = aTransferable->GetIsPrivateData();
10200 aIPCTransferable->dataPrincipal() = aTransferable->GetDataPrincipal();
10201 aIPCTransferable->cookieJarSettings() = std::move(cookieJarSettingsArgs);
10202 aIPCTransferable->contentPolicyType() = aTransferable->GetContentPolicyType();
10203 aIPCTransferable->referrerInfo() = aTransferable->GetReferrerInfo();
10204}
10205
10206Maybe<BigBuffer> nsContentUtils::GetSurfaceData(DataSourceSurface& aSurface,
10207 size_t* aLength,
10208 int32_t* aStride) {
10209 mozilla::gfx::DataSourceSurface::MappedSurface map;
10210 if (!aSurface.Map(mozilla::gfx::DataSourceSurface::MapType::READ, &map)) {
10211 return Nothing();
10212 }
10213
10214 size_t bufLen = 0;
10215 size_t maxBufLen = 0;
10216 nsresult rv = nsContentUtils::CalculateBufferSizeForImage(
10217 map.mStride, aSurface.GetSize(), aSurface.GetFormat(), &maxBufLen,
10218 &bufLen);
10219 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10220 aSurface.Unmap();
10221 return Nothing();
10222 }
10223
10224 BigBuffer surfaceData(maxBufLen);
10225 memcpy(surfaceData.Data(), map.mData, bufLen);
10226 memset(surfaceData.Data() + bufLen, 0, maxBufLen - bufLen);
10227
10228 *aLength = maxBufLen;
10229 *aStride = map.mStride;
10230
10231 aSurface.Unmap();
10232 return Some(std::move(surfaceData));
10233}
10234
10235Maybe<IPCImage> nsContentUtils::SurfaceToIPCImage(DataSourceSurface& aSurface) {
10236 size_t len = 0;
10237 int32_t stride = 0;
10238 auto mem = GetSurfaceData(aSurface, &len, &stride);
10239 if (!mem) {
10240 return Nothing();
10241 }
10242 return Some(IPCImage{std::move(*mem), uint32_t(stride), aSurface.GetFormat(),
10243 ImageIntSize::FromUnknownSize(aSurface.GetSize())});
10244}
10245
10246already_AddRefed<DataSourceSurface> nsContentUtils::IPCImageToSurface(
10247 const IPCImage& aImage) {
10248 return BigBufferToDataSurface(aImage.data(), aImage.stride(),
10249 aImage.size().ToUnknownSize(), aImage.format());
10250}
10251
10252already_AddRefed<imgIContainer> nsContentUtils::IPCImageToImage(
10253 const IPCImage& aImage) {
10254 RefPtr<DataSourceSurface> surface = IPCImageToSurface(aImage);
10255 if (!surface) {
10256 return nullptr;
10257 }
10258
10259 auto drawable = MakeRefPtr<gfxSurfaceDrawable>(surface, surface->GetSize());
10260 nsCOMPtr<imgIContainer> imageContainer =
10261 image::ImageOps::CreateFromDrawable(drawable);
10262 return imageContainer.forget();
10263}
10264
10265Modifiers nsContentUtils::GetWidgetModifiers(int32_t aModifiers) {
10266 Modifiers result = 0;
10267 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SHIFT) {
10268 result |= mozilla::MODIFIER_SHIFT;
10269 }
10270 if (aModifiers & nsIDOMWindowUtils::MODIFIER_CONTROL) {
10271 result |= mozilla::MODIFIER_CONTROL;
10272 }
10273 if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALT) {
10274 result |= mozilla::MODIFIER_ALT;
10275 }
10276 if (aModifiers & nsIDOMWindowUtils::MODIFIER_META) {
10277 result |= mozilla::MODIFIER_META;
10278 }
10279 if (aModifiers & nsIDOMWindowUtils::MODIFIER_ALTGRAPH) {
10280 result |= mozilla::MODIFIER_ALTGRAPH;
10281 }
10282 if (aModifiers & nsIDOMWindowUtils::MODIFIER_CAPSLOCK) {
10283 result |= mozilla::MODIFIER_CAPSLOCK;
10284 }
10285 if (aModifiers & nsIDOMWindowUtils::MODIFIER_FN) {
10286 result |= mozilla::MODIFIER_FN;
10287 }
10288 if (aModifiers & nsIDOMWindowUtils::MODIFIER_FNLOCK) {
10289 result |= mozilla::MODIFIER_FNLOCK;
10290 }
10291 if (aModifiers & nsIDOMWindowUtils::MODIFIER_NUMLOCK) {
10292 result |= mozilla::MODIFIER_NUMLOCK;
10293 }
10294 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SCROLLLOCK) {
10295 result |= mozilla::MODIFIER_SCROLLLOCK;
10296 }
10297 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOL) {
10298 result |= mozilla::MODIFIER_SYMBOL;
10299 }
10300 if (aModifiers & nsIDOMWindowUtils::MODIFIER_SYMBOLLOCK) {
10301 result |= mozilla::MODIFIER_SYMBOLLOCK;
10302 }
10303 return result;
10304}
10305
10306nsIWidget* nsContentUtils::GetWidget(PresShell* aPresShell, nsPoint* aOffset) {
10307 if (!aPresShell) {
10308 return nullptr;
10309 }
10310 nsIFrame* frame = aPresShell->GetRootFrame();
10311 if (!frame) {
10312 return nullptr;
10313 }
10314 return aOffset ? frame->GetNearestWidget(*aOffset)
10315 : frame->GetNearestWidget();
10316}
10317
10318int16_t nsContentUtils::GetButtonsFlagForButton(int32_t aButton) {
10319 switch (aButton) {
10320 case -1:
10321 return MouseButtonsFlag::eNoButtons;
10322 case MouseButton::ePrimary:
10323 return MouseButtonsFlag::ePrimaryFlag;
10324 case MouseButton::eMiddle:
10325 return MouseButtonsFlag::eMiddleFlag;
10326 case MouseButton::eSecondary:
10327 return MouseButtonsFlag::eSecondaryFlag;
10328 case 3:
10329 return MouseButtonsFlag::e4thFlag;
10330 case 4:
10331 return MouseButtonsFlag::e5thFlag;
10332 case MouseButton::eEraser:
10333 return MouseButtonsFlag::eEraserFlag;
10334 default:
10335 NS_ERROR("Button not known.")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Button not known.", "Error"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 10335); MOZ_PretendNoReturn
(); } while (0)
;
10336 return 0;
10337 }
10338}
10339
10340LayoutDeviceIntPoint nsContentUtils::ToWidgetPoint(
10341 const CSSPoint& aPoint, const nsPoint& aOffset,
10342 nsPresContext* aPresContext) {
10343 nsPoint layoutRelative = CSSPoint::ToAppUnits(aPoint) + aOffset;
10344 nsPoint visualRelative =
10345 ViewportUtils::LayoutToVisual(layoutRelative, aPresContext->PresShell());
10346 return LayoutDeviceIntPoint::FromAppUnitsRounded(
10347 visualRelative, aPresContext->AppUnitsPerDevPixel());
10348}
10349
10350namespace {
10351
10352class SynthesizedEventCallback final : public nsISynthesizedEventCallback {
10353 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:
10354
10355 public:
10356 explicit SynthesizedEventCallback(VoidFunction& aCallback)
10357 : mCallback(&aCallback) {}
10358
10359 MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODvirtual nsresult OnCompleteDispatch() override {
10360 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", 10360
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCallback" ") (" "How can we have a null mCallback here?"
")"); do { MOZ_CrashSequence(__null, 10360); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10361
10362 ErrorResult rv;
10363 MOZ_KnownLive(mCallback)(mCallback)->Call(rv);
10364 if (MOZ_UNLIKELY(rv.Failed())(__builtin_expect(!!(rv.Failed()), 0))) {
10365 return rv.StealNSResult();
10366 }
10367
10368 return NS_OK;
10369 }
10370
10371 private:
10372 virtual ~SynthesizedEventCallback() = default;
10373
10374 const RefPtr<VoidFunction> mCallback;
10375};
10376
10377NS_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"
, 10377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 10377
); __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"
, 10377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SynthesizedEventCallback\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 10377); __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"
, 10377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 10377
); __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"
, 10377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"SynthesizedEventCallback\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 10377); __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"
, 10377); 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; }
10378
10379} // namespace
10380
10381Result<bool, nsresult> nsContentUtils::SynthesizeMouseEvent(
10382 mozilla::PresShell* aPresShell, nsIWidget* aWidget, const nsAString& aType,
10383 LayoutDeviceIntPoint& aRefPoint,
10384 const SynthesizeMouseEventData& aMouseEventData,
10385 const SynthesizeMouseEventOptions& aOptions,
10386 const Optional<OwningNonNull<VoidFunction>>& aCallback) {
10387 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"
, 10387); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresShell"
")"); do { MOZ_CrashSequence(__null, 10387); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10388 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"
, 10388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWidget" ")"
); do { MOZ_CrashSequence(__null, 10388); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10389 AUTO_PROFILER_LABEL("nsContentUtils::SynthesizeMouseEvent", OTHER)mozilla::AutoProfilerLabel raiiObject10389( "nsContentUtils::SynthesizeMouseEvent"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
10390
10391 if (aCallback.WasPassed()) {
10392 if (!XRE_IsParentProcess()) {
10393 // TODO(edgar): There is currently no real use case for synthesizing a
10394 // mouse event with a callback from the content process. For now, throw an
10395 // error in this case. We can add support later if a valid use case
10396 // arises.
10397 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"
, 10399)
10398 "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"
, 10399)
10399 "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"
, 10399)
;
10400 return Err(NS_ERROR_FAILURE);
10401 }
10402
10403 if (!aOptions.mIsDOMEventSynthesized) {
10404 // TODO(edgar): There is currently no real use case for synthesizing a
10405 // mouse event with a callback that could be coalesced. For now, throw an
10406 // error. We can add support later if a need arises.
10407 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", 10410)
10408 "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", 10410)
10409 "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", 10410)
10410 "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", 10410)
;
10411 return Err(NS_ERROR_FAILURE);
10412 }
10413 }
10414
10415 EventMessage msg;
10416 Maybe<WidgetMouseEvent::ExitFrom> exitFrom;
10417 bool contextMenuKey = false;
10418 if (aType.EqualsLiteral("mousedown")) {
10419 msg = eMouseDown;
10420 } else if (aType.EqualsLiteral("mouseup")) {
10421 msg = eMouseUp;
10422 } else if (aType.EqualsLiteral("mousemove")) {
10423 msg = eMouseMove;
10424 } else if (aType.EqualsLiteral("mouseover")) {
10425 msg = eMouseEnterIntoWidget;
10426 } else if (aType.EqualsLiteral("mouseout")) {
10427 msg = eMouseExitFromWidget;
10428 exitFrom = Some(WidgetMouseEvent::ePlatformChild);
10429 } else if (aType.EqualsLiteral("mousecancel")) {
10430 msg = eMouseExitFromWidget;
10431 exitFrom = Some(XRE_IsParentProcess() ? WidgetMouseEvent::ePlatformTopLevel
10432 : WidgetMouseEvent::ePuppet);
10433 } else if (aType.EqualsLiteral("mouselongtap")) {
10434 msg = eMouseLongTap;
10435 } else if (aType.EqualsLiteral("contextmenu")) {
10436 msg = eContextMenu;
10437 contextMenuKey =
10438 !aMouseEventData.mButton &&
10439 aMouseEventData.mInputSource != MouseEvent_Binding::MOZ_SOURCE_TOUCH;
10440 } else if (aType.EqualsLiteral("MozMouseHittest")) {
10441 msg = eMouseHitTest;
10442 } else if (aType.EqualsLiteral("MozMouseExploreByTouch")) {
10443 msg = eMouseExploreByTouch;
10444 } else {
10445 return Err(NS_ERROR_FAILURE);
10446 }
10447
10448 Maybe<WidgetPointerEvent> pointerEvent;
10449 Maybe<WidgetMouseEvent> mouseEvent;
10450 if (IsPointerEventMessage(msg)) {
10451 if (MOZ_UNLIKELY(aOptions.mIsWidgetEventSynthesized)(__builtin_expect(!!(aOptions.mIsWidgetEventSynthesized), 0))) {
10452 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", 10453); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "The event shouldn't be dispatched as a synthesized event"
")"); do { MOZ_CrashSequence(__null, 10453); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10453 "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", 10453); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: " "The event shouldn't be dispatched as a synthesized event"
")"); do { MOZ_CrashSequence(__null, 10453); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10454 // `click`, `auxclick` nor `contextmenu` should not be dispatched as a
10455 // synthesized event.
10456 return Err(NS_ERROR_INVALID_ARG);
10457 }
10458 pointerEvent.emplace(true, msg, aWidget,
10459 contextMenuKey ? WidgetMouseEvent::eContextMenuKey
10460 : WidgetMouseEvent::eNormal);
10461 } else {
10462 mouseEvent.emplace(true, msg, aWidget,
10463 aOptions.mIsWidgetEventSynthesized
10464 ? WidgetMouseEvent::eSynthesized
10465 : WidgetMouseEvent::eReal,
10466 contextMenuKey ? WidgetMouseEvent::eContextMenuKey
10467 : WidgetMouseEvent::eNormal);
10468 }
10469
10470 nsCOMPtr<nsISynthesizedEventCallback> callback;
10471 if (aCallback.WasPassed()) {
10472 callback = MakeAndAddRef<SynthesizedEventCallback>(aCallback.Value());
10473 }
10474
10475 mozilla::widget::AutoSynthesizedEventCallbackNotifier notifier(callback);
10476
10477 WidgetMouseEvent& mouseOrPointerEvent =
10478 pointerEvent.isSome() ? pointerEvent.ref() : mouseEvent.ref();
10479 mouseOrPointerEvent.pointerId = aMouseEventData.mIdentifier;
10480 mouseOrPointerEvent.mModifiers =
10481 GetWidgetModifiers(aMouseEventData.mModifiers);
10482 mouseOrPointerEvent.mButton = aMouseEventData.mButton;
10483 mouseOrPointerEvent.mButtons =
10484 aMouseEventData.mButtons.WasPassed()
10485 ? aMouseEventData.mButtons.Value()
10486 : (msg != eMouseDown
10487 ? 0
10488 : GetButtonsFlagForButton(aMouseEventData.mButton));
10489 // https://w3c.github.io/pointerevents/#dom-pointerevent-pressure.
10490 mouseOrPointerEvent.mPressure =
10491 aMouseEventData.mPressure.WasPassed()
10492 ? aMouseEventData.mPressure.Value()
10493 : ((mouseOrPointerEvent.mButtons == 0) ? 0.0f : 0.5f);
10494 mouseOrPointerEvent.mInputSource = aMouseEventData.mInputSource;
10495 mouseOrPointerEvent.mClickCount =
10496 aMouseEventData.mClickCount.WasPassed()
10497 ? aMouseEventData.mClickCount.Value()
10498 : ((msg == eMouseDown || msg == eMouseUp) ? 1 : 0);
10499 mouseOrPointerEvent.mFlags.mIsSynthesizedForTests =
10500 aOptions.mIsDOMEventSynthesized;
10501 mouseOrPointerEvent.mExitFrom = std::move(exitFrom);
10502 mouseOrPointerEvent.mCallbackId = notifier.SaveCallback();
10503
10504 nsPresContext* presContext = aPresShell->GetPresContext();
10505 if (!presContext) {
10506 return Err(NS_ERROR_FAILURE);
10507 }
10508
10509 mouseOrPointerEvent.mRefPoint = aRefPoint;
10510 mouseOrPointerEvent.mIgnoreRootScrollFrame = aOptions.mIgnoreRootScrollFrame;
10511
10512 nsEventStatus status = nsEventStatus_eIgnore;
10513 if (aOptions.mToWindow) {
10514 nsresult rv = aPresShell->HandleEvent(aPresShell->GetRootFrame(),
10515 &mouseOrPointerEvent, false, &status);
10516 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10517 return Err(rv);
10518 }
10519 } else if (aOptions.mIsAsyncEnabled ||
10520 StaticPrefs::test_events_async_enabled()) {
10521 // The event is dispatched asynchronously via WebDriver when it is not
10522 // targeted directly at a window and async dispatching is requested.
10523 mouseOrPointerEvent.mFlags.mIsAsyncSynthesizedForTests =
10524 aOptions.mIsDOMEventSynthesized;
10525 status = aWidget->DispatchInputEvent(&mouseOrPointerEvent).mContentStatus;
10526 } else {
10527 status = aWidget->DispatchEvent(&mouseOrPointerEvent);
10528 }
10529
10530 // The callback ID may be cleared when the event also needs to be dispatched
10531 // to a content process. In such cases, the callback will be notified after
10532 // the event has been dispatched in the target content process.
10533 if (mouseOrPointerEvent.mCallbackId.isSome()) {
10534 mozilla::widget::AutoSynthesizedEventCallbackNotifier::NotifySavedCallback(
10535 mouseOrPointerEvent.mCallbackId.ref());
10536 }
10537
10538 return status == nsEventStatus_eConsumeNoDefault;
10539}
10540
10541mozilla::Result<bool, nsresult> nsContentUtils::SynthesizeTouchEvent(
10542 nsPresContext* aPresContext, nsIWidget* aWidget,
10543 const nsPoint& aWidgetOffset, const nsAString& aType,
10544 const nsTArray<SynthesizeTouchEventData>& aTouches,
10545 const int32_t aModifiers, const SynthesizeTouchEventOptions& aOptions,
10546 const Optional<OwningNonNull<VoidFunction>>& aCallback) {
10547 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"
, 10547); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPresContext"
")"); do { MOZ_CrashSequence(__null, 10547); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10548 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"
, 10548); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWidget" ")"
); do { MOZ_CrashSequence(__null, 10548); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10549 AUTO_PROFILER_LABEL("nsContentUtils::SynthesizeTouchEvent", OTHER)mozilla::AutoProfilerLabel raiiObject10549( "nsContentUtils::SynthesizeTouchEvent"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
10550
10551 if (aCallback.WasPassed()) {
10552 if (!XRE_IsParentProcess()) {
10553 // TODO(edgar): There is currently no real use case for synthesizing a
10554 // touch event with a callback from the content process. For now, throw an
10555 // error in this case. We can add support later if a valid use case
10556 // arises.
10557 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"
, 10559)
10558 "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"
, 10559)
10559 "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"
, 10559)
;
10560 return Err(NS_ERROR_FAILURE);
10561 }
10562
10563 if (!aOptions.mIsDOMEventSynthesized) {
10564 // TODO(edgar): There is currently no real use case for synthesizing a
10565 // touch event with a callback that could be coalesced. For now, throw an
10566 // error. We can add support later if a need arises.
10567 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", 10570)
10568 "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", 10570)
10569 "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", 10570)
10570 "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", 10570)
;
10571 return Err(NS_ERROR_FAILURE);
10572 }
10573 }
10574
10575 if (XRE_IsParentProcess() && !aOptions.mIsAsyncEnabled &&
10576 !StaticPrefs::test_events_async_enabled()) {
10577 // TODO(edgar): Currently, dispatching touch event from parent process
10578 // without going through APZ would cause content process crash on debug
10579 // build.
10580 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", 10582)
10581 "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", 10582)
10582 "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", 10582)
;
10583 return Err(NS_ERROR_FAILURE);
10584 }
10585
10586 EventMessage msg;
10587 if (aType.EqualsLiteral("touchstart")) {
10588 msg = eTouchStart;
10589 } else if (aType.EqualsLiteral("touchmove")) {
10590 msg = eTouchMove;
10591 } else if (aType.EqualsLiteral("touchend")) {
10592 msg = eTouchEnd;
10593 } else if (aType.EqualsLiteral("touchcancel")) {
10594 msg = eTouchCancel;
10595 } else {
10596 return Err(NS_ERROR_UNEXPECTED);
10597 }
10598
10599 nsCOMPtr<nsISynthesizedEventCallback> callback;
10600 if (aCallback.WasPassed()) {
10601 callback = MakeAndAddRef<SynthesizedEventCallback>(aCallback.Value());
10602 }
10603
10604 mozilla::widget::AutoSynthesizedEventCallbackNotifier notifier(callback);
10605
10606 WidgetTouchEvent event(true, msg, aWidget);
10607 event.mFlags.mIsSynthesizedForTests = aOptions.mIsDOMEventSynthesized;
10608 event.mModifiers = nsContentUtils::GetWidgetModifiers(aModifiers);
10609 if (aOptions.mIsPen) {
10610 event.mInputSource = MouseEvent_Binding::MOZ_SOURCE_PEN;
10611 }
10612 event.mCallbackId = notifier.SaveCallback();
10613
10614 uint32_t count = aTouches.Length();
10615 event.mTouches.SetCapacity(count);
10616 for (uint32_t i = 0; i < count; ++i) {
10617 if (aTouches[i].mAltitudeAngle.WasPassed() !=
10618 aTouches[i].mAzimuthAngle.WasPassed()) {
10619 return Err(NS_ERROR_INVALID_ARG);
10620 }
10621
10622 LayoutDeviceIntPoint pt = nsContentUtils::ToWidgetPoint(
10623 CSSPoint(aTouches[i].mOffsetX, aTouches[i].mOffsetY), aWidgetOffset,
10624 aPresContext);
10625 LayoutDeviceIntPoint radius = LayoutDeviceIntPoint::FromAppUnitsRounded(
10626 CSSPoint::ToAppUnits(
10627 CSSPoint(aTouches[i].mRadiiX, aTouches[i].mRadiiY)),
10628 aPresContext->AppUnitsPerDevPixel());
10629 // https://w3c.github.io/pointerevents/#dom-pointerevent-pressure.
10630 float pressure = aTouches[i].mPressure.WasPassed()
10631 ? aTouches[i].mPressure.Value()
10632 : (msg == eTouchEnd ? 0.0f : 0.5f);
10633
10634 RefPtr<Touch> t =
10635 new Touch(CheckedInt<int32_t>(aTouches[i].mIdentifier).value(), pt,
10636 radius, aTouches[i].mRotationAngle, pressure);
10637 if (aTouches[i].mAltitudeAngle.WasPassed()) {
10638 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", 10638); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aTouches[i].mAzimuthAngle.WasPassed()" ")"
); do { MOZ_CrashSequence(__null, 10638); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10639 t->mAngle.emplace(aTouches[i].mAltitudeAngle.Value(),
10640 aTouches[i].mAzimuthAngle.Value());
10641 } else {
10642 t->mTilt.emplace(aTouches[i].mTiltX, aTouches[i].mTiltY);
10643 }
10644 t->twist = aTouches[i].mTwist;
10645 event.mTouches.AppendElement(t);
10646 }
10647
10648 nsEventStatus status = nsEventStatus_eIgnore;
10649 if (aOptions.mToWindow) {
10650 RefPtr<PresShell> presShell = aPresContext->PresShell();
10651 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(); })
10652 &status))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(presShell->HandleEvent(presShell->GetRootFrame(), &
event, false, &status)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
;
10653 } else if (aOptions.mIsAsyncEnabled ||
10654 StaticPrefs::test_events_async_enabled()) {
10655 status = aWidget->DispatchInputEvent(&event).mContentStatus;
10656 } else {
10657 status = aWidget->DispatchEvent(&event);
10658 }
10659
10660 // The callback ID may be cleared when the event also needs to be dispatched
10661 // to a content process. In such cases, the callback will be notified after
10662 // the event has been dispatched in the target content process.
10663 if (event.mCallbackId.isSome()) {
10664 mozilla::widget::AutoSynthesizedEventCallbackNotifier::NotifySavedCallback(
10665 event.mCallbackId.ref());
10666 }
10667
10668 return status == nsEventStatus_eConsumeNoDefault;
10669}
10670
10671/* static */
10672void nsContentUtils::FirePageHideEventForFrameLoaderSwap(
10673 nsIDocShellTreeItem* aItem, EventTarget* aChromeEventHandler,
10674 bool aOnlySystemGroup) {
10675 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"
, 10675); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "aItem"
")"); do { MOZ_CrashSequence(__null, 10675); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10676 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", 10676); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "aChromeEventHandler" ")"); do {
MOZ_CrashSequence(__null, 10676); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
10677
10678 if (RefPtr<Document> doc = aItem->GetDocument()) {
10679 doc->OnPageHide(true, aChromeEventHandler, aOnlySystemGroup);
10680 }
10681
10682 int32_t childCount = 0;
10683 aItem->GetInProcessChildCount(&childCount);
10684 AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids;
10685 kids.AppendElements(childCount);
10686 for (int32_t i = 0; i < childCount; ++i) {
10687 aItem->GetInProcessChildAt(i, getter_AddRefs(kids[i]));
10688 }
10689
10690 for (uint32_t i = 0; i < kids.Length(); ++i) {
10691 if (kids[i]) {
10692 FirePageHideEventForFrameLoaderSwap(
10693 MOZ_KnownLive(kids[i])(kids[i]), aChromeEventHandler, aOnlySystemGroup);
10694 }
10695 }
10696}
10697
10698// The pageshow event is fired for a given document only if IsShowing()
10699// returns the same thing as aFireIfShowing. This gives us a way to fire
10700// pageshow only on documents that are still loading or only on documents that
10701// are already loaded.
10702/* static */
10703void nsContentUtils::FirePageShowEventForFrameLoaderSwap(
10704 nsIDocShellTreeItem* aItem, EventTarget* aChromeEventHandler,
10705 bool aFireIfShowing, bool aOnlySystemGroup) {
10706 int32_t childCount = 0;
10707 aItem->GetInProcessChildCount(&childCount);
10708 AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> kids;
10709 kids.AppendElements(childCount);
10710 for (int32_t i = 0; i < childCount; ++i) {
10711 aItem->GetInProcessChildAt(i, getter_AddRefs(kids[i]));
10712 }
10713
10714 for (uint32_t i = 0; i < kids.Length(); ++i) {
10715 if (kids[i]) {
10716 FirePageShowEventForFrameLoaderSwap(MOZ_KnownLive(kids[i])(kids[i]),
10717 aChromeEventHandler, aFireIfShowing,
10718 aOnlySystemGroup);
10719 }
10720 }
10721
10722 RefPtr<Document> doc = aItem->GetDocument();
10723 if (doc && doc->IsShowing() == aFireIfShowing) {
10724 doc->OnPageShow(true, aChromeEventHandler, aOnlySystemGroup);
10725 }
10726}
10727
10728/* static */
10729already_AddRefed<nsPIWindowRoot> nsContentUtils::GetWindowRoot(Document* aDoc) {
10730 if (aDoc) {
10731 if (nsPIDOMWindowOuter* win = aDoc->GetWindow()) {
10732 return win->GetTopWindowRoot();
10733 }
10734 }
10735 return nullptr;
10736}
10737
10738/* static */
10739bool nsContentUtils::LinkContextIsURI(const nsAString& aAnchor,
10740 nsIURI* aDocURI) {
10741 if (aAnchor.IsEmpty()) {
10742 // anchor parameter not present or empty -> same document reference
10743 return true;
10744 }
10745
10746 // the document URI might contain a fragment identifier ("#...')
10747 // we want to ignore that because it's invisible to the server
10748 // and just affects the local interpretation in the recipient
10749 nsCOMPtr<nsIURI> contextUri;
10750 nsresult rv = NS_GetURIWithoutRef(aDocURI, getter_AddRefs(contextUri));
10751
10752 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10753 // copying failed
10754 return false;
10755 }
10756
10757 // resolve anchor against context
10758 nsCOMPtr<nsIURI> resolvedUri;
10759 rv = NS_NewURI(getter_AddRefs(resolvedUri), aAnchor, nullptr, contextUri);
10760
10761 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10762 // resolving failed
10763 return false;
10764 }
10765
10766 bool same;
10767 rv = contextUri->Equals(resolvedUri, &same);
10768 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10769 // comparison failed
10770 return false;
10771 }
10772
10773 return same;
10774}
10775
10776/* static */
10777bool nsContentUtils::IsPreloadType(nsContentPolicyType aType) {
10778 return (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD ||
10779 aType == nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD ||
10780 aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD ||
10781 aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD ||
10782 aType == nsIContentPolicy::TYPE_INTERNAL_FONT_PRELOAD ||
10783 aType == nsIContentPolicy::TYPE_INTERNAL_JSON_PRELOAD ||
10784 aType == nsIContentPolicy::TYPE_INTERNAL_TEXT_PRELOAD ||
10785 aType == nsIContentPolicy::TYPE_INTERNAL_FETCH_PRELOAD);
10786}
10787
10788// static
10789bool nsContentUtils::IsImageType(ExtContentPolicy aType) {
10790 return aType == ExtContentPolicy::TYPE_IMAGE ||
10791 aType == ExtContentPolicy::TYPE_IMAGESET;
10792}
10793
10794// static
10795ReferrerPolicy nsContentUtils::GetReferrerPolicyFromChannel(
10796 nsIChannel* aChannel) {
10797 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
10798 if (!httpChannel) {
10799 return ReferrerPolicy::_empty;
10800 }
10801
10802 nsresult rv;
10803 nsAutoCString headerValue;
10804 rv = httpChannel->GetResponseHeader("referrer-policy"_ns, headerValue);
10805 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || headerValue.IsEmpty()) {
10806 return ReferrerPolicy::_empty;
10807 }
10808
10809 return ReferrerInfo::ReferrerPolicyFromHeaderString(
10810 NS_ConvertUTF8toUTF16(headerValue));
10811}
10812
10813// static
10814bool nsContentUtils::HasRelNoReferrer(const Element& aElement) {
10815 // rel=noreferrer is only supported in <a>, <area>, and <form>
10816 if (!aElement.IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area,
10817 nsGkAtoms::form) &&
10818 !aElement.IsSVGElement(nsGkAtoms::a)) {
10819 return false;
10820 }
10821
10822 nsAutoString rel;
10823 aElement.GetAttr(nsGkAtoms::rel, rel);
10824 nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(rel);
10825
10826 while (tok.hasMoreTokens()) {
10827 const nsAString& token = tok.nextToken();
10828 if (token.LowerCaseEqualsLiteral("noreferrer")) {
10829 return true;
10830 }
10831 }
10832
10833 return false;
10834}
10835
10836// static
10837bool nsContentUtils::IsNonSubresourceRequest(nsIChannel* aChannel) {
10838 nsLoadFlags loadFlags = 0;
10839 aChannel->GetLoadFlags(&loadFlags);
10840 if (loadFlags & nsIChannel::LOAD_DOCUMENT_URI) {
10841 return true;
10842 }
10843
10844 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
10845 nsContentPolicyType type = loadInfo->InternalContentPolicyType();
10846 return IsNonSubresourceInternalPolicyType(type);
10847}
10848
10849// static
10850bool nsContentUtils::IsNonSubresourceInternalPolicyType(
10851 nsContentPolicyType aType) {
10852 return aType == nsIContentPolicy::TYPE_DOCUMENT ||
10853 aType == nsIContentPolicy::TYPE_INTERNAL_IFRAME ||
10854 aType == nsIContentPolicy::TYPE_INTERNAL_FRAME ||
10855 aType == nsIContentPolicy::TYPE_INTERNAL_WORKER ||
10856 aType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER;
10857}
10858
10859// static public
10860bool nsContentUtils::IsThirdPartyTrackingResourceWindow(
10861 nsPIDOMWindowInner* aWindow) {
10862 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"
, 10862); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")"
); do { MOZ_CrashSequence(__null, 10862); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10863
10864 Document* document = aWindow->GetExtantDoc();
10865 if (!document) {
10866 return false;
10867 }
10868
10869 nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
10870 do_QueryInterface(document->GetChannel());
10871 if (!classifiedChannel) {
10872 return false;
10873 }
10874
10875 return classifiedChannel->IsThirdPartyTrackingResource();
10876}
10877
10878// static public
10879bool nsContentUtils::IsFirstPartyTrackingResourceWindow(
10880 nsPIDOMWindowInner* aWindow) {
10881 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"
, 10881); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aWindow" ")"
); do { MOZ_CrashSequence(__null, 10881); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10882
10883 Document* document = aWindow->GetExtantDoc();
10884 if (!document) {
10885 return false;
10886 }
10887
10888 nsCOMPtr<nsIClassifiedChannel> classifiedChannel =
10889 do_QueryInterface(document->GetChannel());
10890 if (!classifiedChannel) {
10891 return false;
10892 }
10893
10894 uint32_t classificationFlags =
10895 classifiedChannel->GetFirstPartyClassificationFlags();
10896
10897 return mozilla::net::ChannelClassifierUtils::IsTrackingClassificationFlag(
10898 classificationFlags, NS_UsePrivateBrowsing(document->GetChannel()));
10899}
10900
10901namespace {
10902
10903// We put StringBuilder in the anonymous namespace to prevent anything outside
10904// this file from accidentally being linked against it.
10905class BulkAppender {
10906 using size_type = typename nsAString::size_type;
10907
10908 public:
10909 explicit BulkAppender(BulkWriteHandle<char16_t>&& aHandle)
10910 : mHandle(std::move(aHandle)), mPosition(0) {}
10911 ~BulkAppender() = default;
10912
10913 template <int N>
10914 void AppendLiteral(const char16_t (&aStr)[N]) {
10915 size_t len = N - 1;
10916 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", 10916); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()" ")"
); do { MOZ_CrashSequence(__null, 10916); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10917 memcpy(mHandle.Elements() + mPosition, aStr, len * sizeof(char16_t));
10918 mPosition += len;
10919 }
10920
10921 void Append(Span<const char16_t> aStr) {
10922 size_t len = aStr.Length();
10923 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", 10923); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()" ")"
); do { MOZ_CrashSequence(__null, 10923); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10924 // Both mHandle.Elements() and aStr.Elements() are guaranteed
10925 // to be non-null (by the string implementation and by Span,
10926 // respectively), so not checking the pointers for null before
10927 // memcpy does not lead to UB even if len was zero.
10928 memcpy(mHandle.Elements() + mPosition, aStr.Elements(),
10929 len * sizeof(char16_t));
10930 mPosition += len;
10931 }
10932
10933 void Append(Span<const char> aStr) {
10934 size_t len = aStr.Length();
10935 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", 10935); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "mPosition + len <= mHandle.Length()" ")"
); do { MOZ_CrashSequence(__null, 10935); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10936 ConvertLatin1toUtf16(aStr, mHandle.AsSpan().From(mPosition));
10937 mPosition += len;
10938 }
10939
10940 void Finish() { mHandle.Finish(mPosition, false); }
10941
10942 private:
10943 BulkWriteHandle<char16_t> mHandle;
10944 size_type mPosition;
10945};
10946
10947class StringBuilderSIMD {
10948 public:
10949 static const bool SIMD = true;
10950};
10951
10952class StringBuilderALU {
10953 public:
10954 static const bool SIMD = false;
10955};
10956
10957class StringBuilder {
10958 private:
10959 class Unit {
10960 public:
10961 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)
; }
10962 ~Unit() {
10963 if (mType == Type::String || mType == Type::StringWithEncode) {
10964 mString.~nsString();
10965 }
10966 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)
;
10967 }
10968
10969 enum class Type : uint8_t {
10970 Unknown,
10971 Atom,
10972 String,
10973 StringWithEncode,
10974 Literal,
10975 TextFragment,
10976 TextFragmentWithEncode,
10977 };
10978
10979 struct LiteralSpan {
10980 const char16_t* mData;
10981 uint32_t mLength;
10982
10983 Span<const char16_t> AsSpan() { return Span(mData, mLength); }
10984 };
10985
10986 union {
10987 nsAtom* mAtom;
10988 LiteralSpan mLiteral;
10989 nsString mString;
10990 const CharacterDataBuffer* mCharacterDataBuffer;
10991 };
10992 Type mType = Type::Unknown;
10993 };
10994
10995 static_assert(sizeof(void*) != 8 || sizeof(Unit) <= 3 * sizeof(void*),
10996 "Unit should remain small");
10997
10998 public:
10999 // Try to keep the size of StringBuilder close to a jemalloc bucket size
11000 // (the 16kb one in this case).
11001 static constexpr uint32_t TARGET_SIZE = 16 * 1024;
11002
11003 // The number of units we need to remove from the inline buffer so that the
11004 // rest of the builder members fit. A more precise approach would be to
11005 // calculate that extra size and use (TARGET_SIZE - OTHER_SIZE) /
11006 // sizeof(Unit) or so, but this is simpler.
11007 static constexpr uint32_t PADDING_UNITS = sizeof(void*) == 8 ? 1 : 2;
11008
11009 static constexpr uint32_t STRING_BUFFER_UNITS =
11010 TARGET_SIZE / sizeof(Unit) - PADDING_UNITS;
11011
11012 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)
; }
11013
11014 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); }
11015
11016 void Append(nsAtom* aAtom) {
11017 Unit* u = AddUnit();
11018 u->mAtom = aAtom;
11019 u->mType = Unit::Type::Atom;
11020 uint32_t len = aAtom->GetLength();
11021 mLength += len;
11022 }
11023
11024 template <int N>
11025 void Append(const char16_t (&aLiteral)[N]) {
11026 constexpr uint32_t len = N - 1;
11027 Unit* u = AddUnit();
11028 u->mLiteral = {aLiteral, len};
11029 u->mType = Unit::Type::Literal;
11030 mLength += len;
11031 }
11032
11033 void Append(nsString&& aString) {
11034 Unit* u = AddUnit();
11035 uint32_t len = aString.Length();
11036 new (&u->mString) nsString(std::move(aString));
11037 u->mType = Unit::Type::String;
11038 mLength += len;
11039 }
11040
11041 // aLen can be !isValid(), which will get propagated into mLength.
11042 void AppendWithAttrEncode(nsString&& aString, CheckedInt<uint32_t> aLen) {
11043 Unit* u = AddUnit();
11044 new (&u->mString) nsString(std::move(aString));
11045 u->mType = Unit::Type::StringWithEncode;
11046 mLength += aLen;
11047 }
11048
11049 void Append(const CharacterDataBuffer* aCharacterDataBuffer) {
11050 Unit* u = AddUnit();
11051 u->mCharacterDataBuffer = aCharacterDataBuffer;
11052 u->mType = Unit::Type::TextFragment;
11053 uint32_t len = aCharacterDataBuffer->GetLength();
11054 mLength += len;
11055 }
11056
11057 // aLen can be !isValid(), which will get propagated into mLength.
11058 void AppendWithEncode(const CharacterDataBuffer* aCharacterDataBuffer,
11059 CheckedInt<uint32_t> aLen) {
11060 Unit* u = AddUnit();
11061 u->mCharacterDataBuffer = aCharacterDataBuffer;
11062 u->mType = Unit::Type::TextFragmentWithEncode;
11063 mLength += aLen;
11064 }
11065
11066 bool ToString(nsAString& aOut) {
11067 if (!mLength.isValid()) {
11068 return false;
11069 }
11070 auto appenderOrErr = aOut.BulkWrite(mLength.value(), 0, true);
11071 if (appenderOrErr.isErr()) {
11072 return false;
11073 }
11074
11075 BulkAppender appender{appenderOrErr.unwrap()};
11076
11077 // Experiment with moving this higher up the call stack
11078 // after we have experience from
11079 // https://bugzilla.mozilla.org/show_bug.cgi?id=1997255
11080 // on the parser side.
11081 bool simd = mozilla::htmlaccel::htmlaccelEnabled();
11082
11083 for (StringBuilder* current = this; current;
11084 current = current->mNext.get()) {
11085 uint32_t len = current->mUnits.Length();
11086 for (uint32_t i = 0; i < len; ++i) {
11087 Unit& u = current->mUnits[i];
11088 switch (u.mType) {
11089 case Unit::Type::Atom:
11090 appender.Append(*(u.mAtom));
11091 break;
11092 case Unit::Type::String:
11093 appender.Append(u.mString);
11094 break;
11095 case Unit::Type::StringWithEncode:
11096 if (simd) {
11097 EncodeAttrString<StringBuilderSIMD>(u.mString, appender);
11098 } else {
11099 EncodeAttrString<StringBuilderALU>(u.mString, appender);
11100 }
11101 break;
11102 case Unit::Type::Literal:
11103 appender.Append(u.mLiteral.AsSpan());
11104 break;
11105 case Unit::Type::TextFragment:
11106 if (u.mCharacterDataBuffer->Is2b()) {
11107 appender.Append(Span(u.mCharacterDataBuffer->Get2b(),
11108 u.mCharacterDataBuffer->GetLength()));
11109 } else {
11110 appender.Append(Span(u.mCharacterDataBuffer->Get1b(),
11111 u.mCharacterDataBuffer->GetLength()));
11112 }
11113 break;
11114 case Unit::Type::TextFragmentWithEncode:
11115 if (u.mCharacterDataBuffer->Is2b()) {
11116 if (simd) {
11117 EncodeTextFragment<StringBuilderSIMD>(
11118 Span(u.mCharacterDataBuffer->Get2b(),
11119 u.mCharacterDataBuffer->GetLength()),
11120 appender);
11121
11122 } else {
11123 EncodeTextFragment<StringBuilderALU>(
11124 Span(u.mCharacterDataBuffer->Get2b(),
11125 u.mCharacterDataBuffer->GetLength()),
11126 appender);
11127 }
11128 } else {
11129 if (simd) {
11130 EncodeTextFragment<StringBuilderSIMD>(
11131 Span(u.mCharacterDataBuffer->Get1b(),
11132 u.mCharacterDataBuffer->GetLength()),
11133 appender);
11134
11135 } else {
11136 EncodeTextFragment<StringBuilderALU>(
11137 Span(u.mCharacterDataBuffer->Get1b(),
11138 u.mCharacterDataBuffer->GetLength()),
11139 appender);
11140 }
11141 }
11142 break;
11143 default:
11144 MOZ_CRASH("Unknown unit type?")do { do { } while (false); MOZ_ReportCrash("" "Unknown unit type?"
, "/root/firefox-clang/dom/base/nsContentUtils.cpp", 11144); AnnotateMozCrashReason
("MOZ_CRASH(" "Unknown unit type?" ")"); do { MOZ_CrashSequence
(__null, 11144); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
11145 }
11146 }
11147 }
11148 appender.Finish();
11149 return true;
11150 }
11151
11152 private:
11153 Unit* AddUnit() {
11154 if (mLast->mUnits.Length() == STRING_BUFFER_UNITS) {
11155 new StringBuilder(this);
11156 }
11157 return mLast->mUnits.AppendElement();
11158 }
11159
11160 explicit StringBuilder(StringBuilder* aFirst) : mLast(nullptr), mLength(0) {
11161 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)
;
11162 aFirst->mLast->mNext = WrapUnique(this);
11163 aFirst->mLast = this;
11164 }
11165
11166 template <class S>
11167 void EncodeAttrString(Span<const char16_t> aStr, BulkAppender& aAppender) {
11168 size_t flushedUntil = 0;
11169 size_t currentPosition = 0;
11170 const char16_t* ptr = aStr.Elements();
11171 const char16_t* end = ptr + aStr.Length();
11172
11173 // continue by label (committee proposal P3568) isn't in C++, yet, so
11174 // goto is used for what's logically continuing an outer loop.
11175 //
11176 // The purpose of two loop levels is to efficiently stay in the inner
11177 // loop when there isn't a full SIMD stride left.
11178 //
11179 // Strange indent thanks to clang-format.
11180 outer:
11181 // Check for having at least a SIMD stride of data to avoid useless
11182 // non-inline function calls when there isn't a full stride left.
11183 // This should become unnecessary if it turns out to be feasible
11184 // to inline the call without triggering
11185 // https://github.com/llvm/llvm-project/issues/160886 .
11186 if (S::SIMD && (end - ptr >= 16)) {
11187 // Need to check ifdef inside here in order to make even non-opt
11188 // build consider `S::SIMD` used.
11189#ifdef MOZ_MAY_HAVE_HTMLACCEL1
11190 size_t skipped =
11191 mozilla::htmlaccel::SkipNonEscapedInAttributeValue(ptr, end);
11192 ptr += skipped;
11193 currentPosition += skipped;
11194#endif
11195 }
11196 while (ptr != end) {
11197 char16_t c = *ptr;
11198 ptr++;
11199 switch (c) {
11200 case '"':
11201 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11202 aAppender.AppendLiteral(u"&quot;");
11203 currentPosition++;
11204 flushedUntil = currentPosition;
11205 goto outer;
11206 case '&':
11207 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11208 aAppender.AppendLiteral(u"&amp;");
11209 currentPosition++;
11210 flushedUntil = currentPosition;
11211 goto outer;
11212 case 0x00A0:
11213 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11214 aAppender.AppendLiteral(u"&nbsp;");
11215 currentPosition++;
11216 flushedUntil = currentPosition;
11217 goto outer;
11218 case '<':
11219 if (StaticPrefs::dom_security_html_serialization_escape_lt_gt()) {
11220 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11221 aAppender.AppendLiteral(u"&lt;");
11222 currentPosition++;
11223 flushedUntil = currentPosition;
11224 } else {
11225 currentPosition++;
11226 }
11227 goto outer;
11228 case '>':
11229 if (StaticPrefs::dom_security_html_serialization_escape_lt_gt()) {
11230 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11231 aAppender.AppendLiteral(u"&gt;");
11232 currentPosition++;
11233 flushedUntil = currentPosition;
11234 } else {
11235 currentPosition++;
11236 }
11237 goto outer;
11238 default:
11239 currentPosition++;
11240 continue;
11241 }
11242 }
11243 // Logically the outer loop ends here.
11244 if (currentPosition > flushedUntil) {
11245 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11246 }
11247 }
11248
11249 template <class S, class T>
11250 void EncodeTextFragment(Span<const T> aStr, BulkAppender& aAppender) {
11251 size_t flushedUntil = 0;
11252 size_t currentPosition = 0;
11253 const T* ptr = aStr.Elements();
11254 const T* end = ptr + aStr.Length();
11255
11256 // continue by label (committee proposal P3568) isn't in C++, yet, so
11257 // goto is used for what's logically continuing an outer loop.
11258 //
11259 // The purpose of two loop levels is to efficiently stay in the inner
11260 // loop when there isn't a full SIMD stride left.
11261 //
11262 // Strange indent thanks to clang-format.
11263 outer:
11264 // Check for having at least a SIMD stride of data to avoid useless
11265 // non-inline function calls when there isn't a full stride left.
11266 // This should become unnecessary if it turns out to be feasible
11267 // to inline the call without triggering
11268 // https://github.com/llvm/llvm-project/issues/160886 .
11269 if (S::SIMD && (end - ptr >= 16)) {
11270 // Need to check ifdef inside here in order to make even non-opt
11271 // build consider `S::SIMD` used.
11272#ifdef MOZ_MAY_HAVE_HTMLACCEL1
11273 size_t skipped = mozilla::htmlaccel::SkipNonEscapedInTextNode(ptr, end);
11274 ptr += skipped;
11275 currentPosition += skipped;
11276#endif
11277 }
11278 while (ptr != end) {
11279 T c = *ptr;
11280 ++ptr;
11281 switch (c) {
11282 case '<':
11283 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11284 aAppender.AppendLiteral(u"&lt;");
11285 currentPosition++;
11286 flushedUntil = currentPosition;
11287 goto outer;
11288 case '>':
11289 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11290 aAppender.AppendLiteral(u"&gt;");
11291 currentPosition++;
11292 flushedUntil = currentPosition;
11293 goto outer;
11294 case '&':
11295 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11296 aAppender.AppendLiteral(u"&amp;");
11297 currentPosition++;
11298 flushedUntil = currentPosition;
11299 goto outer;
11300 case T(0xA0):
11301 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11302 aAppender.AppendLiteral(u"&nbsp;");
11303 currentPosition++;
11304 flushedUntil = currentPosition;
11305 goto outer;
11306 default:
11307 currentPosition++;
11308 continue;
11309 }
11310 }
11311 // Logically the outer loop ends here.
11312 if (currentPosition > flushedUntil) {
11313 aAppender.Append(aStr.FromTo(flushedUntil, currentPosition));
11314 }
11315 }
11316
11317 AutoTArray<Unit, STRING_BUFFER_UNITS> mUnits;
11318 UniquePtr<StringBuilder> mNext;
11319 StringBuilder* mLast;
11320 // mLength is used only in the first StringBuilder object in the linked
11321 // list.
11322 CheckedInt<uint32_t> mLength;
11323};
11324
11325static_assert(sizeof(StringBuilder) <= StringBuilder::TARGET_SIZE,
11326 "StringBuilder should fit in the target bucket");
11327
11328} // namespace
11329
11330static void AppendEncodedCharacters(const CharacterDataBuffer* aText,
11331 StringBuilder& aBuilder) {
11332 uint32_t numEncodedChars = 0;
11333 uint32_t len = aText->GetLength();
11334 if (aText->Is2b()) {
11335 const char16_t* data = aText->Get2b();
11336#ifdef MOZ_MAY_HAVE_HTMLACCEL1
11337 if (mozilla::htmlaccel::htmlaccelEnabled()) {
11338 numEncodedChars =
11339 mozilla::htmlaccel::CountEscapedInTextNode(data, data + len);
11340 } else
11341#endif
11342 {
11343 for (uint32_t i = 0; i < len; ++i) {
11344 const char16_t c = data[i];
11345 switch (c) {
11346 case '<':
11347 case '>':
11348 case '&':
11349 case 0x00A0:
11350 ++numEncodedChars;
11351 break;
11352 default:
11353 break;
11354 }
11355 }
11356 }
11357 } else {
11358 const char* data = aText->Get1b();
11359#ifdef MOZ_MAY_HAVE_HTMLACCEL1
11360 if (mozilla::htmlaccel::htmlaccelEnabled()) {
11361 numEncodedChars =
11362 mozilla::htmlaccel::CountEscapedInTextNode(data, data + len);
11363 } else
11364#endif
11365 {
11366 for (uint32_t i = 0; i < len; ++i) {
11367 const unsigned char c = data[i];
11368 switch (c) {
11369 case '<':
11370 case '>':
11371 case '&':
11372 case 0x00A0:
11373 ++numEncodedChars;
11374 break;
11375 default:
11376 break;
11377 }
11378 }
11379 }
11380 }
11381
11382 if (numEncodedChars) {
11383 // For simplicity, conservatively estimate the size of the string after
11384 // encoding. This will result in reserving more memory than we actually
11385 // need, but that should be fine unless the string has an enormous number
11386 // of eg < in it. We subtract 1 for the null terminator, then 1 more for
11387 // the existing character that will be replaced.
11388 constexpr uint32_t maxCharExtraSpace =
11389 std::max({std::size("&lt;"), std::size("&gt;"), std::size("&amp;"),
11390 std::size("&nbsp;")}) -
11391 2;
11392 static_assert(maxCharExtraSpace < 100, "Possible underflow");
11393 CheckedInt<uint32_t> maxExtraSpace =
11394 CheckedInt<uint32_t>(numEncodedChars) * maxCharExtraSpace;
11395 aBuilder.AppendWithEncode(aText, maxExtraSpace + len);
11396 } else {
11397 aBuilder.Append(aText);
11398 }
11399}
11400
11401static CheckedInt<uint32_t> ExtraSpaceNeededForAttrEncoding(
11402 const nsAString& aValue) {
11403 const char16_t* c = aValue.BeginReading();
11404 const char16_t* end = aValue.EndReading();
11405
11406 uint32_t numEncodedChars = 0;
11407#ifdef MOZ_MAY_HAVE_HTMLACCEL1
11408 if (mozilla::htmlaccel::htmlaccelEnabled()) {
11409 numEncodedChars = mozilla::htmlaccel::CountEscapedInAttributeValue(c, end);
11410 } else
11411#endif
11412 {
11413 while (c < end) {
11414 switch (*c) {
11415 case '"':
11416 case '&':
11417 case 0x00A0: // NO-BREAK SPACE
11418 case '<':
11419 case '>':
11420 ++numEncodedChars;
11421 break;
11422 default:
11423 break;
11424 }
11425 ++c;
11426 }
11427 }
11428
11429 if (!numEncodedChars) {
11430 return 0;
11431 }
11432
11433 // For simplicity, conservatively estimate the size of the string after
11434 // encoding. This will result in reserving more memory than we actually
11435 // need, but that should be fine unless the string has an enormous number of
11436 // & in it. We subtract 1 for the null terminator, then 1 more for the
11437 // existing character that will be replaced.
11438 constexpr uint32_t maxCharExtraSpace =
11439 std::max({std::size("&quot;"), std::size("&amp;"), std::size("&nbsp;"),
11440 std::size("&lt;"), std::size("&gt;")}) -
11441 2;
11442 static_assert(maxCharExtraSpace < 100, "Possible underflow");
11443 return CheckedInt<uint32_t>(numEncodedChars) * maxCharExtraSpace;
11444}
11445
11446static void AppendEncodedAtomAttributeValue(nsAtom* aAtom,
11447 StringBuilder& aBuilder) {
11448 nsDependentAtomString atomStr(aAtom);
11449 auto space = ExtraSpaceNeededForAttrEncoding(atomStr);
11450 if (space.isValid() && !space.value()) {
11451 aBuilder.Append(aAtom);
11452 } else {
11453 aBuilder.AppendWithAttrEncode(nsString(atomStr), space + atomStr.Length());
11454 }
11455}
11456
11457static void AppendEncodedAttributeValue(const nsAttrValue& aValue,
11458 StringBuilder& aBuilder) {
11459 if (nsAtom* atom = aValue.GetStoredAtom()) {
11460 AppendEncodedAtomAttributeValue(atom, aBuilder);
11461 return;
11462 }
11463
11464 // NOTE(emilio): In most cases this will just be a reference to the stored
11465 // nsStringBuffer.
11466 nsString str;
11467 aValue.ToString(str);
11468 auto space = ExtraSpaceNeededForAttrEncoding(str);
11469 if (!space.isValid() || space.value()) {
11470 aBuilder.AppendWithAttrEncode(std::move(str), space + str.Length());
11471 } else {
11472 aBuilder.Append(std::move(str));
11473 }
11474}
11475
11476static void StartElement(Element* aElement, StringBuilder& aBuilder) {
11477 nsAtom* localName = aElement->NodeInfo()->NameAtom();
11478 const int32_t tagNS = aElement->GetNameSpaceID();
11479
11480 aBuilder.Append(u"<");
11481 if (tagNS == kNameSpaceID_XHTML3 || tagNS == kNameSpaceID_SVG9 ||
11482 tagNS == kNameSpaceID_MathML6) {
11483 aBuilder.Append(localName);
11484 } else {
11485 aBuilder.Append(nsString(aElement->NodeName()));
11486 }
11487
11488 if (CustomElementData* ceData = aElement->GetCustomElementData()) {
11489 nsAtom* isAttr = ceData->GetIs(aElement);
11490 if (isAttr && !aElement->HasAttr(nsGkAtoms::is)) {
11491 aBuilder.Append(uR"( is=")");
11492 AppendEncodedAtomAttributeValue(isAttr, aBuilder);
11493 aBuilder.Append(uR"(")");
11494 }
11495 }
11496
11497 uint32_t i = 0;
11498 while (BorrowedAttrInfo info = aElement->GetAttrInfoAt(i++)) {
11499 const nsAttrName* name = info.mName;
11500
11501 int32_t attNs = name->NamespaceID();
11502 nsAtom* attName = name->LocalName();
11503
11504 // Filter out any attribute starting with [-|_]moz
11505 // FIXME(emilio): Do we still need this?
11506 nsDependentAtomString attrNameStr(attName);
11507 if (StringBeginsWith(attrNameStr, u"_moz"_ns) ||
11508 StringBeginsWith(attrNameStr, u"-moz"_ns)) {
11509 continue;
11510 }
11511
11512 aBuilder.Append(u" ");
11513
11514 if (MOZ_LIKELY(attNs == kNameSpaceID_None)(__builtin_expect(!!(attNs == kNameSpaceID_None), 1)) ||
11515 (attNs == kNameSpaceID_XMLNS1 && attName == nsGkAtoms::xmlns)) {
11516 // Nothing else required
11517 } else if (attNs == kNameSpaceID_XML2) {
11518 aBuilder.Append(u"xml:");
11519 } else if (attNs == kNameSpaceID_XMLNS1) {
11520 aBuilder.Append(u"xmlns:");
11521 } else if (attNs == kNameSpaceID_XLink4) {
11522 aBuilder.Append(u"xlink:");
11523 } else if (nsAtom* prefix = name->GetPrefix()) {
11524 aBuilder.Append(prefix);
11525 aBuilder.Append(u":");
11526 }
11527
11528 aBuilder.Append(attName);
11529 aBuilder.Append(uR"(=")");
11530 AppendEncodedAttributeValue(*info.mValue, aBuilder);
11531 aBuilder.Append(uR"(")");
11532 }
11533
11534 aBuilder.Append(u">");
11535
11536 /*
11537 // Per HTML spec we should append one \n if the first child of
11538 // pre/textarea/listing is a textnode and starts with a \n.
11539 // But because browsers haven't traditionally had that behavior,
11540 // we're not changing our behavior either - yet.
11541 if (aContent->IsHTMLElement()) {
11542 if (localName == nsGkAtoms::pre || localName == nsGkAtoms::textarea ||
11543 localName == nsGkAtoms::listing) {
11544 nsIContent* fc = aContent->GetFirstChild();
11545 if (fc &&
11546 (fc->NodeType() == nsINode::TEXT_NODE ||
11547 fc->NodeType() == nsINode::CDATA_SECTION_NODE)) {
11548 const CharacterDataBuffer* text = fc->GetText();
11549 if (text && text->GetLength() && text->CharAt(0) == char16_t('\n')) {
11550 aBuilder.Append("\n");
11551 }
11552 }
11553 }
11554 }*/
11555}
11556
11557static inline bool ShouldEscape(nsIContent* aParent) {
11558 if (!aParent || !aParent->IsHTMLElement()) {
11559 return true;
11560 }
11561
11562 static const nsAtom* nonEscapingElements[] = {
11563 nsGkAtoms::style, nsGkAtoms::script, nsGkAtoms::xmp,
11564 nsGkAtoms::iframe, nsGkAtoms::noembed, nsGkAtoms::noframes,
11565 nsGkAtoms::plaintext, nsGkAtoms::noscript};
11566 static mozilla::BitBloomFilter<12, nsAtom> sFilter;
11567 static bool sInitialized = false;
11568 if (!sInitialized) {
11569 sInitialized = true;
11570 for (auto& nonEscapingElement : nonEscapingElements) {
11571 sFilter.add(nonEscapingElement);
11572 }
11573 }
11574
11575 nsAtom* tag = aParent->NodeInfo()->NameAtom();
11576 if (sFilter.mightContain(tag)) {
11577 for (auto& nonEscapingElement : nonEscapingElements) {
11578 if (tag == nonEscapingElement) {
11579 if (MOZ_UNLIKELY(tag == nsGkAtoms::noscript)(__builtin_expect(!!(tag == nsGkAtoms::noscript), 0)) &&
11580 MOZ_UNLIKELY(!aParent->OwnerDoc()->IsScriptEnabled())(__builtin_expect(!!(!aParent->OwnerDoc()->IsScriptEnabled
()), 0))
) {
11581 return true;
11582 }
11583 return false;
11584 }
11585 }
11586 }
11587 return true;
11588}
11589
11590static inline bool IsVoidTag(Element* aElement) {
11591 if (!aElement->IsHTMLElement()) {
11592 return false;
11593 }
11594 return FragmentOrElement::IsHTMLVoid(aElement->NodeInfo()->NameAtom());
11595}
11596
11597static bool StartSerializingShadowDOM(
11598 nsINode* aNode, StringBuilder& aBuilder, bool aSerializableShadowRoots,
11599 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
11600 ShadowRoot* shadow = aNode->GetShadowRoot();
11601 if (!shadow || ((!aSerializableShadowRoots || !shadow->Serializable()) &&
11602 !aShadowRoots.Contains(shadow))) {
11603 return false;
11604 }
11605
11606 // https://html.spec.whatwg.org/#html-fragment-serialisation-algorithm
11607 // steps 4-12
11608
11609 // 4.2.1. Append "<template shadowrootmode="".
11610 aBuilder.Append(u"<template shadowrootmode=\"");
11611
11612 // 4.2.2. If shadow's mode is "open", then append "open". Otherwise, append
11613 // "closed".
11614 // 3. Append U+0022 (").
11615 if (shadow->IsClosed()) {
11616 aBuilder.Append(u"closed\"");
11617 } else {
11618 aBuilder.Append(u"open\"");
11619 }
11620
11621 // 4. If shadow's delegates focus is set, then append "
11622 // shadowrootdelegatesfocus=""".
11623 if (shadow->DelegatesFocus()) {
11624 aBuilder.Append(u" shadowrootdelegatesfocus=\"\"");
11625 }
11626
11627 // 5. If shadow's serializable is set, then append "
11628 // shadowrootserializable=""".
11629 if (shadow->Serializable()) {
11630 aBuilder.Append(u" shadowrootserializable=\"\"");
11631 }
11632
11633 // 6. If shadow's slot assignment is "manual", then append "
11634 // shadowrootslotassignment="manual"".
11635 if (StaticPrefs::dom_shadowdom_shadowRootSlotAssignment_enabled() &&
11636 shadow->SlotAssignment() == SlotAssignmentMode::Manual) {
11637 aBuilder.Append(u" shadowrootslotassignment=\"manual\"");
11638 }
11639
11640 // 7. If shadow's slot assignment is "manual", then append "
11641 // shadowrootslotassignment="manual"".
11642 if (shadow->Clonable()) {
11643 aBuilder.Append(u" shadowrootclonable=\"\"");
11644 }
11645
11646 auto isGlobalCustomElementRegistry = [](CustomElementRegistry* registry) {
11647 return registry && !registry->IsScoped();
11648 };
11649
11650 // 8. Let shouldAppendRegistryAttribute be the result of running these steps:
11651 const bool shouldAppendRegistryAttribute = [&]() {
11652 if (!StaticPrefs::dom_scoped_custom_element_registries_enabled()) {
11653 return false;
11654 }
11655
11656 // 8.1. Let documentRegistry be shadow's node document's custom element
11657 // registry.
11658 CustomElementRegistry* documentRegistry =
11659 shadow->OwnerDoc()->GetCustomElementRegistry();
11660 // 8.2. Let shadowRegistry be shadow's custom element registry.
11661 CustomElementRegistry* shadowRegistry = shadow->GetCustomElementRegistry();
11662
11663 // 8.3. If documentRegistry is null and shadowRegistry is null, then return
11664 // false.
11665 if (!documentRegistry && !shadowRegistry) {
11666 return false;
11667 }
11668 // 8.4. If documentRegistry is a global custom element registry and
11669 // shadowRegistry is a global custom element registry, then return
11670 // false.
11671 else if (isGlobalCustomElementRegistry(documentRegistry) &&
11672 isGlobalCustomElementRegistry(shadowRegistry)) {
11673 return false;
11674 }
11675
11676 // 8.5. Return true.
11677 return true;
11678 }();
11679
11680 // 9. If shouldAppendRegistryAttribute is true, then append "
11681 // shadowrootcustomelementregistry=""".
11682 if (shouldAppendRegistryAttribute) {
11683 aBuilder.Append(u" shadowrootcustomelementregistry=\"\"");
11684 }
11685
11686 // 10. Append U+003E (>).
11687 aBuilder.Append(u">");
11688
11689 // 11. Append the value of running the HTML fragment serialization algorithm
11690 // with shadow, serializableShadowRoots, and shadowRoots (thus recursing
11691 // into this algorithm for that element).
11692 // (Returning `true` tells the caller to continue).
11693 if (!shadow->HasChildren()) {
11694 // 12. Append "</template>".
11695 aBuilder.Append(u"</template>");
11696 return false;
11697 }
11698 return true;
11699}
11700
11701template <SerializeShadowRoots ShouldSerializeShadowRoots>
11702static void SerializeNodeToMarkupInternal(
11703 nsINode* aRoot, bool aDescendantsOnly, StringBuilder& aBuilder,
11704 bool aSerializableShadowRoots,
11705 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
11706 nsINode* current =
11707 aDescendantsOnly ? aRoot->GetFirstChildOfTemplateOrNode() : aRoot;
11708 if (!current) {
11709 return;
11710 }
11711
11712 nsIContent* next;
11713 while (true) {
11714 bool isVoid = false;
11715 switch (current->NodeType()) {
11716 case nsINode::ELEMENT_NODE: {
11717 Element* elem = current->AsElement();
11718 StartElement(elem, aBuilder);
11719
11720 if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
11721 if (StartSerializingShadowDOM(
11722 current, aBuilder, aSerializableShadowRoots, aShadowRoots)) {
11723 current = current->GetShadowRoot()->GetFirstChild();
11724 continue;
11725 }
11726 }
11727
11728 isVoid = IsVoidTag(elem);
11729 if (!isVoid && (next = current->GetFirstChildOfTemplateOrNode())) {
11730 current = next;
11731 continue;
11732 }
11733 break;
11734 }
11735
11736 case nsINode::TEXT_NODE:
11737 case nsINode::CDATA_SECTION_NODE: {
11738 const CharacterDataBuffer* characterDataBuffer =
11739 &current->AsText()->DataBuffer();
11740 nsIContent* parent = current->GetParent();
11741 if (ShouldEscape(parent)) {
11742 AppendEncodedCharacters(characterDataBuffer, aBuilder);
11743 } else {
11744 aBuilder.Append(characterDataBuffer);
11745 }
11746 break;
11747 }
11748
11749 case nsINode::COMMENT_NODE: {
11750 aBuilder.Append(u"<!--");
11751 aBuilder.Append(
11752 static_cast<nsIContent*>(current)->GetCharacterDataBuffer());
11753 aBuilder.Append(u"-->");
11754 break;
11755 }
11756
11757 case nsINode::DOCUMENT_TYPE_NODE: {
11758 aBuilder.Append(u"<!DOCTYPE ");
11759 aBuilder.Append(nsString(current->NodeName()));
11760 aBuilder.Append(u">");
11761 break;
11762 }
11763
11764 case nsINode::PROCESSING_INSTRUCTION_NODE: {
11765 aBuilder.Append(u"<?");
11766 aBuilder.Append(nsString(current->NodeName()));
11767 aBuilder.Append(u" ");
11768 aBuilder.Append(
11769 static_cast<nsIContent*>(current)->GetCharacterDataBuffer());
11770 aBuilder.Append(u">");
11771 break;
11772 }
11773 }
11774
11775 while (true) {
11776 if (!isVoid && current->NodeType() == nsINode::ELEMENT_NODE) {
11777 aBuilder.Append(u"</");
11778 nsIContent* elem = static_cast<nsIContent*>(current);
11779 if (elem->IsHTMLElement() || elem->IsSVGElement() ||
11780 elem->IsMathMLElement()) {
11781 aBuilder.Append(elem->NodeInfo()->NameAtom());
11782 } else {
11783 aBuilder.Append(nsString(current->NodeName()));
11784 }
11785 aBuilder.Append(u">");
11786 }
11787 isVoid = false;
11788
11789 if (current == aRoot) {
11790 return;
11791 }
11792
11793 if ((next = current->GetNextSibling())) {
11794 current = next;
11795 break;
11796 }
11797
11798 if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
11799 // If the current node is a shadow root, then we must go to its host.
11800 // Since shadow DOMs are serialized declaratively as template
11801 // elements, we serialize the end tag of the template before going
11802 // back to serializing the shadow host.
11803 if (current->IsShadowRoot()) {
11804 current = current->GetContainingShadowHost();
11805 aBuilder.Append(u"</template>");
11806
11807 if (current->HasChildren()) {
11808 current = current->GetFirstChildOfTemplateOrNode();
11809 break;
11810 }
11811 continue;
11812 }
11813 }
11814
11815 current = current->GetParentNode();
11816
11817 // Handle template element. If the parent is a template's content,
11818 // then adjust the parent to be the template element.
11819 if (current != aRoot &&
11820 current->NodeType() == nsINode::DOCUMENT_FRAGMENT_NODE) {
11821 DocumentFragment* frag = static_cast<DocumentFragment*>(current);
11822 nsIContent* fragHost = frag->GetHost();
11823 if (fragHost && fragHost->IsTemplateElement()) {
11824 current = fragHost;
11825 }
11826 }
11827
11828 if (aDescendantsOnly && current == aRoot) {
11829 return;
11830 }
11831 }
11832 }
11833}
11834
11835template <SerializeShadowRoots ShouldSerializeShadowRoots>
11836bool nsContentUtils::SerializeNodeToMarkup(
11837 nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
11838 bool aSerializableShadowRoots,
11839 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots) {
11840 // If you pass in a DOCUMENT_NODE, you must pass aDescendentsOnly as true
11841 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", 11841); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aDescendantsOnly || aRoot->NodeType() != nsINode::DOCUMENT_NODE"
")"); do { MOZ_CrashSequence(__null, 11841); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11842
11843 StringBuilder builder;
11844 if constexpr (ShouldSerializeShadowRoots == SerializeShadowRoots::Yes) {
11845 if (aDescendantsOnly &&
11846 StartSerializingShadowDOM(aRoot, builder, aSerializableShadowRoots,
11847 aShadowRoots)) {
11848 SerializeNodeToMarkupInternal<SerializeShadowRoots::Yes>(
11849 aRoot->GetShadowRoot(), true, builder, aSerializableShadowRoots,
11850 aShadowRoots);
11851 // The template tag is opened in StartSerializingShadowDOM, so we need
11852 // to close it here before serializing any children of aRoot.
11853 builder.Append(u"</template>");
11854 }
11855 }
11856
11857 SerializeNodeToMarkupInternal<ShouldSerializeShadowRoots>(
11858 aRoot, aDescendantsOnly, builder, aSerializableShadowRoots, aShadowRoots);
11859 return builder.ToString(aOut);
11860}
11861
11862template bool nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::No>(
11863 nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
11864 bool aSerializableShadowRoots,
11865 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots);
11866template bool nsContentUtils::SerializeNodeToMarkup<SerializeShadowRoots::Yes>(
11867 nsINode* aRoot, bool aDescendantsOnly, nsAString& aOut,
11868 bool aSerializableShadowRoots,
11869 const Sequence<OwningNonNull<ShadowRoot>>& aShadowRoots);
11870
11871bool nsContentUtils::IsSpecificAboutPage(JSObject* aGlobal, const char* aUri) {
11872 // aUri must start with about: or this isn't the right function to be using.
11873 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"
, 11873); AnnotateMozCrashReason("MOZ_ASSERT" "(" "strncmp(aUri, \"about:\", 6) == 0"
")"); do { MOZ_CrashSequence(__null, 11873); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11874
11875 // Make sure the global is a window
11876 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", 11876); AnnotateMozCrashReason
("MOZ_DIAGNOSTIC_ASSERT" "(" "JS_IsGlobalObject(aGlobal)" ")"
); do { MOZ_CrashSequence(__null, 11876); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11877 nsGlobalWindowInner* win = xpc::WindowOrNull(aGlobal);
11878 if (!win) {
11879 return false;
11880 }
11881
11882 nsCOMPtr<nsIPrincipal> principal = win->GetPrincipal();
11883 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", 11883); return
false; } } while (false)
;
11884
11885 // First check the scheme to avoid getting long specs in the common case.
11886 if (!principal->SchemeIs("about")) {
11887 return false;
11888 }
11889
11890 nsAutoCString spec;
11891 principal->GetAsciiSpec(spec);
11892
11893 return spec.EqualsASCII(aUri);
11894}
11895
11896/* static */
11897nsIDocShell* nsContentUtils::GetDocShellForEventTarget(EventTarget* aTarget) {
11898 if (!aTarget) {
11899 return nullptr;
11900 }
11901
11902 nsCOMPtr<nsPIDOMWindowInner> innerWindow;
11903 if (nsCOMPtr<nsINode> node = nsINode::FromEventTarget(aTarget)) {
11904 bool ignore;
11905 innerWindow =
11906 do_QueryInterface(node->OwnerDoc()->GetScriptHandlingObject(ignore));
11907 } else if ((innerWindow = nsPIDOMWindowInner::FromEventTarget(aTarget))) {
11908 // Nothing else to do
11909 } else if (nsCOMPtr<DOMEventTargetHelper> helper =
11910 do_QueryInterface(aTarget)) {
11911 innerWindow = helper->GetOwnerWindow();
11912 }
11913
11914 if (innerWindow) {
11915 return innerWindow->GetDocShell();
11916 }
11917
11918 return nullptr;
11919}
11920
11921/*
11922 * Note: this function only relates to figuring out HTTPS state, which is an
11923 * input to the Secure Context algorithm. We are not actually implementing
11924 * any part of the Secure Context algorithm itself here.
11925 *
11926 * This is a bit of a hack. Ideally we'd propagate HTTPS state through
11927 * nsIChannel as described in the Fetch and HTML specs, but making channels
11928 * know about whether they should inherit HTTPS state, propagating information
11929 * about who the channel's "client" is, exposing GetHttpsState API on channels
11930 * and modifying the various cache implementations to store and retrieve HTTPS
11931 * state involves a huge amount of code (see bug 1220687). We avoid that for
11932 * now using this function.
11933 *
11934 * This function takes advantage of the observation that we can return true if
11935 * nsIContentSecurityManager::IsOriginPotentiallyTrustworthy returns true for
11936 * the document's origin (e.g. the origin has a scheme of 'https' or host
11937 * 'localhost' etc.). Since we generally propagate a creator document's
11938 * origin onto data:, blob:, etc. documents, this works for them too.
11939 *
11940 * The scenario where this observation breaks down is sandboxing without the
11941 * 'allow-same-origin' flag, since in this case a document is given a unique
11942 * origin (IsOriginPotentiallyTrustworthy would return false). We handle that
11943 * by using the origin that the document would have had had it not been
11944 * sandboxed.
11945 *
11946 * DEFICIENCIES: Note that this function uses nsIScriptSecurityManager's
11947 * getChannelResultPrincipalIfNotSandboxed, and that method's ignoring of
11948 * sandboxing is limited to the immediate sandbox. In the case that aDocument
11949 * should inherit its origin (e.g. data: URI) but its parent has ended up
11950 * with a unique origin due to sandboxing further up the parent chain we may
11951 * end up returning false when we would ideally return true (since we will
11952 * examine the parent's origin for 'https' and not finding it.) This means
11953 * that we may restrict the privileges of some pages unnecessarily in this
11954 * edge case.
11955 */
11956/* static */
11957bool nsContentUtils::HttpsStateIsModern(Document* aDocument) {
11958 if (!aDocument) {
11959 return false;
11960 }
11961
11962 nsCOMPtr<nsIPrincipal> principal = aDocument->NodePrincipal();
11963
11964 if (principal->IsSystemPrincipal()) {
11965 return true;
11966 }
11967
11968 // If aDocument is sandboxed, try and get the principal that it would have
11969 // been given had it not been sandboxed:
11970 if (principal->GetIsNullPrincipal() &&
11971 (aDocument->GetSandboxFlags() & SANDBOXED_ORIGIN)) {
11972 nsIChannel* channel = aDocument->GetChannel();
11973 if (channel) {
11974 nsCOMPtr<nsIScriptSecurityManager> ssm =
11975 nsContentUtils::GetSecurityManager();
11976 nsresult rv = ssm->GetChannelResultPrincipalIfNotSandboxed(
11977 channel, getter_AddRefs(principal));
11978 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11979 return false;
11980 }
11981 if (principal->IsSystemPrincipal()) {
11982 // If a document with the system principal is sandboxing a subdocument
11983 // that would normally inherit the embedding element's principal (e.g.
11984 // a srcdoc document) then the embedding document does not trust the
11985 // content that is written to the embedded document. Unlike when the
11986 // embedding document is https, in this case we have no indication as
11987 // to whether the embedded document's contents are delivered securely
11988 // or not, and the sandboxing would possibly indicate that they were
11989 // not. To play it safe we return false here. (See bug 1162772
11990 // comment 73-80.)
11991 return false;
11992 }
11993 }
11994 }
11995
11996 if (principal->GetIsNullPrincipal()) {
11997 return false;
11998 }
11999
12000 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", 12000); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "principal->GetIsContentPrincipal()" ")"
); do { MOZ_CrashSequence(__null, 12000); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12001
12002 return principal->GetIsOriginPotentiallyTrustworthy();
12003}
12004
12005/* static */
12006bool nsContentUtils::ComputeIsSecureContext(nsIChannel* aChannel) {
12007 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"
, 12007); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aChannel" ")"
); do { MOZ_CrashSequence(__null, 12007); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12008
12009 nsCOMPtr<nsIScriptSecurityManager> ssm = nsContentUtils::GetSecurityManager();
12010 nsCOMPtr<nsIPrincipal> principal;
12011 nsresult rv = ssm->GetChannelResultPrincipalIfNotSandboxed(
12012 aChannel, getter_AddRefs(principal));
12013 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12014 return false;
12015 }
12016
12017 const RefPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
12018
12019 if (principal->IsSystemPrincipal()) {
12020 // If the load would've been sandboxed, treat this load as an untrusted
12021 // load, as system code considers sandboxed resources insecure.
12022 return !loadInfo->GetLoadingSandboxed();
12023 }
12024
12025 if (principal->GetIsNullPrincipal()) {
12026 return false;
12027 }
12028
12029 if (const RefPtr<WindowContext> windowContext =
12030 WindowContext::GetById(loadInfo->GetInnerWindowID())) {
12031 if (!windowContext->GetIsSecureContext()) {
12032 return false;
12033 }
12034 }
12035
12036 return principal->GetIsOriginPotentiallyTrustworthy();
12037}
12038
12039/* https://html.spec.whatwg.org/#concept-try-upgrade */
12040void nsContentUtils::TryToUpgradeElement(Element* aElement) {
12041 // 1. "Let definition be the result of looking up a custom element definition
12042 // given element's custom element registry, element's namespace, element's
12043 // local name, and element's is value."
12044 NodeInfo* nodeInfo = aElement->NodeInfo();
12045 RefPtr<nsAtom> typeAtom =
12046 aElement->GetCustomElementData()->GetCustomElementType();
12047
12048 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", 12048); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())"
")"); do { MOZ_CrashSequence(__null, 12048); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12049
12050 // When scoped custom element registries are enabled, look up the element's
12051 // own custom element registry (which may be a scoped registry, null, or the
12052 // document's global registry as fallback).
12053 CustomElementRegistry* registry = nullptr;
12054 if (StaticPrefs::dom_scoped_custom_element_registries_enabled()) {
12055 registry = aElement->GetCustomElementRegistry();
12056 if (!registry) {
12057 return;
12058 }
12059 }
12060
12061 CustomElementDefinition* definition = nullptr;
12062 if (registry) {
12063 definition = registry->LookupCustomElementDefinition(
12064 nodeInfo->NameAtom(), nodeInfo->NamespaceID(), typeAtom);
12065 } else {
12066 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", 12066); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!StaticPrefs::dom_scoped_custom_element_registries_enabled()"
")"); do { MOZ_CrashSequence(__null, 12066); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12067 definition = nsContentUtils::LookupCustomElementDefinition(
12068 nodeInfo->GetDocument(), nodeInfo->NameAtom(), nodeInfo->NamespaceID(),
12069 typeAtom);
12070 }
12071
12072 // 2. "If definition is not null, then enqueue a custom element upgrade
12073 // reaction given element and definition."
12074 if (definition) {
12075 nsContentUtils::EnqueueUpgradeReaction(aElement, definition);
12076 } else if (registry) {
12077 registry->RegisterUnresolvedElement(aElement, typeAtom);
12078 } else {
12079 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", 12079); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!StaticPrefs::dom_scoped_custom_element_registries_enabled()"
")"); do { MOZ_CrashSequence(__null, 12079); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12080 // XXX: Not in spec. Add an unresolved custom element that is a candidate
12081 // for upgrade when a custom element is connected to the document.
12082 nsContentUtils::RegisterUnresolvedElement(aElement, typeAtom);
12083 }
12084}
12085
12086MOZ_CAN_RUN_SCRIPT
12087static void DoCustomElementCreate(Element** aElement, JSContext* aCx,
12088 Document* aDoc, NodeInfo* aNodeInfo,
12089 CustomElementConstructor* aConstructor,
12090 ErrorResult& aRv, FromParser aFromParser) {
12091 JS::Rooted<JS::Value> constructResult(aCx);
12092 aConstructor->Construct(&constructResult, aRv, "Custom Element Create",
12093 CallbackFunction::eRethrowExceptions);
12094 if (aRv.Failed()) {
12095 return;
12096 }
12097
12098 RefPtr<Element> element;
12099 // constructResult is an ObjectValue because construction with a callback
12100 // always forms the return value from a JSObject.
12101 UNWRAP_OBJECT(Element, &constructResult, element)mozilla::dom::binding_detail::UnwrapObjectWithCrossOriginAsserts
< mozilla::dom::prototypes::id::Element, mozilla::dom::Element_Binding
::NativeType>(&constructResult, element)
;
12102 if (aNodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
12103 if (!element || !element->IsHTMLElement()) {
12104 aRv.ThrowTypeError<MSG_DOES_NOT_IMPLEMENT_INTERFACE>("\"this\"",
12105 "HTMLElement");
12106 return;
12107 }
12108 } else {
12109 if (!element || !element->IsXULElement()) {
12110 aRv.ThrowTypeError<MSG_DOES_NOT_IMPLEMENT_INTERFACE>("\"this\"",
12111 "XULElement");
12112 return;
12113 }
12114 }
12115
12116 nsAtom* localName = aNodeInfo->NameAtom();
12117
12118 if (aDoc != element->OwnerDoc() || element->GetParentNode() ||
12119 element->HasChildren() || element->GetAttrCount() ||
12120 element->NodeInfo()->NameAtom() != localName) {
12121 aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
12122 return;
12123 }
12124
12125 if (element->IsHTMLElement()) {
12126 static_cast<HTMLElement*>(&*element)->InhibitRestoration(
12127 !(aFromParser & FROM_PARSER_NETWORK));
12128 }
12129
12130 element.forget(aElement);
12131}
12132
12133/* https://dom.spec.whatwg.org/#concept-create-element */
12134nsresult nsContentUtils::NewXULOrHTMLElement(
12135 Element** aResult, mozilla::dom::NodeInfo* aNodeInfo,
12136 FromParser aFromParser, nsAtom* aIsAtom,
12137 mozilla::dom::CustomElementDefinition* aDefinition,
12138 Maybe<RefPtr<CustomElementRegistry>> aCustomElementRegistry) {
12139 RefPtr<mozilla::dom::NodeInfo> nodeInfo = aNodeInfo;
12140 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"
, 12142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
") (" "Can only create XUL or XHTML elements." ")"); do { MOZ_CrashSequence
(__null, 12142); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1
Taking false branch
2
Loop condition is false. Exiting loop
12141 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"
, 12142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
") (" "Can only create XUL or XHTML elements." ")"); do { MOZ_CrashSequence
(__null, 12142); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
12142 "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"
, 12142); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3) || nodeInfo->NamespaceEquals(8)"
") (" "Can only create XUL or XHTML elements." ")"); do { MOZ_CrashSequence
(__null, 12142); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12143
12144 nsAtom* name = nodeInfo->NameAtom();
12145 bool isCustomElementName = false;
12146 const Maybe<const nsHTMLTag>& tag = nodeInfo->HTMLTag();
12147 if (tag.isSome()) {
3
Assuming the condition is false
4
Taking false branch
12148 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"
, 12148); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(3)"
")"); do { MOZ_CrashSequence(__null, 12148); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12149 isCustomElementName =
12150 (*tag == eHTMLTag_userdefined &&
12151 nsContentUtils::IsCustomElementName(name, kNameSpaceID_XHTML3));
12152 } else {
12153 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"
, 12153); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nodeInfo->NamespaceEquals(8)"
")"); do { MOZ_CrashSequence(__null, 12153); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
5
Taking false branch
6
Loop condition is false. Exiting loop
12154 if (aIsAtom) {
7
Assuming 'aIsAtom' is null
8
Taking false branch
12155 // Make sure the customized built-in element to be constructed confirms
12156 // to our naming requirement, i.e. [is] must be a dashed name and
12157 // the tag name must not.
12158 // if so, set isCustomElementName to false to kick off all the logics
12159 // that pick up aIsAtom.
12160 if (nsContentUtils::IsNameWithDash(aIsAtom) &&
12161 !nsContentUtils::IsNameWithDash(name)) {
12162 isCustomElementName = false;
12163 } else {
12164 isCustomElementName =
12165 nsContentUtils::IsCustomElementName(name, kNameSpaceID_XUL8);
12166 }
12167 } else {
12168 isCustomElementName =
12169 nsContentUtils::IsCustomElementName(name, kNameSpaceID_XUL8);
12170 }
12171 }
12172
12173 nsAtom* tagAtom = nodeInfo->NameAtom();
12174 nsAtom* typeAtom = nullptr;
12175 bool isCustomElement = isCustomElementName
8.1
'isCustomElementName' is true
8.1
'isCustomElementName' is true
|| aIsAtom;
12176 if (isCustomElement
8.2
'isCustomElement' is true
8.2
'isCustomElement' is true
) {
12177 typeAtom = isCustomElementName
9.1
'isCustomElementName' is true
9.1
'isCustomElementName' is true
? tagAtom : aIsAtom;
9
Taking true branch
10
'?' condition is true
12178 }
12179
12180 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"
, 12180); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isCustomElement"
")"); do { MOZ_CrashSequence(__null, 12180); __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
12181
12182 // 3. "Let definition be the result of looking up a custom element definition
12183 // given registry, namespace, localName, and is."
12184 RefPtr<CustomElementDefinition> definition = aDefinition;
12185 if (isCustomElement
15.1
'isCustomElement' is true
15.1
'isCustomElement' is true
&& !definition) {
12186 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", 12186); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "nodeInfo->NameAtom()->Equals(nodeInfo->LocalName())"
")"); do { MOZ_CrashSequence(__null, 12186); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12187 // When a custom element registry is provided (e.g. from fragment parsing
12188 // with a scoped registry), use it for definition lookup.
12189 if (aCustomElementRegistry.isSome()) {
12190 if (RefPtr<CustomElementRegistry> registry =
12191 aCustomElementRegistry.value()) {
12192 definition = registry->LookupCustomElementDefinition(
12193 nodeInfo->NameAtom(), nodeInfo->NamespaceID(), typeAtom);
12194 }
12195 // If registry is explicitly null, definition stays null (no upgrade).
12196 } else {
12197 definition = nsContentUtils::LookupCustomElementDefinition(
12198 nodeInfo->GetDocument(), nodeInfo->NameAtom(),
12199 nodeInfo->NamespaceID(), typeAtom);
12200 }
12201 }
12202
12203 /*
12204 * Synchronous custom elements flag is determined by 3 places in spec,
12205 * 1) create an element for a token, the flag is determined by
12206 * "will execute script" which is not originally created
12207 * for the HTML fragment parsing algorithm.
12208 * 2) createElement and createElementNS, the flag is the same as
12209 * NOT_FROM_PARSER.
12210 * 3) clone a node, our implementation will not go into this function.
12211 * For the unset case which is non-synchronous only applied for
12212 * inner/outerHTML.
12213 */
12214 bool synchronousCustomElements =
12215 definition && aFromParser != dom::FROM_PARSER_FRAGMENT;
16
Assuming 'aFromParser' is not equal to FROM_PARSER_FRAGMENT
12216 auto setRegistryOnExit = MakeScopeExit([&]() {
17
Calling 'MakeScopeExit<(lambda at /root/firefox-clang/dom/base/nsContentUtils.cpp:12216:42)>'
19
Returning from 'MakeScopeExit<(lambda at /root/firefox-clang/dom/base/nsContentUtils.cpp:12216:42)>'
12217 if (!*aResult ||
12218 !StaticPrefs::dom_scoped_custom_element_registries_enabled() ||
12219 synchronousCustomElements) {
12220 return;
12221 }
12222 if (aCustomElementRegistry.isSome()) {
12223 RefPtr<CustomElementRegistry> registry = aCustomElementRegistry.value();
12224 if (registry) {
12225 (*aResult)->SetCustomElementRegistry(registry);
12226 } else {
12227 (*aResult)->SetNullCustomElementRegistry();
12228 }
12229 } else {
12230 Document* doc = (*aResult)->OwnerDoc();
12231 if (CustomElementRegistry* globalRegistry =
12232 doc->GetEffectiveGlobalCustomElementRegistry()) {
12233 (*aResult)->SetCustomElementRegistry(globalRegistry);
12234 }
12235 }
12236 });
12237
12238 // It might be a problem that parser synchronously calls constructor, so
12239 // filed bug 1378079 to figure out what we should do for parser case.
12240 if (definition) {
20
Taking true branch
12241 // Per discussion in https://github.com/w3c/webcomponents/issues/635,
12242 // use entry global in those places that are called from JS APIs and use
12243 // the node document's global object if it is called from parser.
12244 nsIGlobalObject* global;
12245 if (aFromParser == dom::NOT_FROM_PARSER) {
21
Assuming 'aFromParser' is equal to NOT_FROM_PARSER
22
Taking true branch
12246 global = GetEntryGlobal();
12247
12248 // Documents created from the PrototypeDocumentSink always use
12249 // NOT_FROM_PARSER for non-XUL elements. We can get the global from the
12250 // document in that case.
12251 if (!global) {
23
Assuming 'global' is non-null
24
Taking false branch
12252 Document* doc = nodeInfo->GetDocument();
12253 if (doc && doc->LoadedFromPrototype()) {
12254 global = doc->GetScopeObject();
12255 }
12256 }
12257 } else {
12258 global = nodeInfo->GetDocument()->GetScopeObject();
12259 }
12260 if (!global
24.1
'global' is non-null
24.1
'global' is non-null
) {
25
Taking false branch
12261 // In browser chrome code, one may have access to a document which
12262 // doesn't have scope object anymore.
12263 return NS_ERROR_FAILURE;
12264 }
12265
12266 AutoAllowLegacyScriptExecution exemption;
12267 AutoEntryScript aes(global, "create custom elements");
12268 JSContext* cx = aes.cx();
12269 ErrorResult rv;
12270
12271 // 4. "If definition is non-null, and definition's name is not equal to its
12272 // local name (i.e., definition represents a customized built-in
12273 // element):"
12274 if (definition->IsCustomBuiltIn()) {
26
Taking false branch
12275 // 4.2. "Set result to the result of creating an element internal..."
12276 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
12277 *aResult =
12278 CreateHTMLElement(*tag, nodeInfo.forget(), aFromParser).take();
12279 } else {
12280 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
12281 }
12282 (*aResult)->SetCustomElementData(MakeUnique<CustomElementData>(typeAtom));
12283 if (synchronousCustomElements) {
12284 // 4.3. "If synchronousCustomElements is true, then run this step while
12285 // catching any exceptions: Upgrade result using definition."
12286 CustomElementRegistry::Upgrade(*aResult, definition, rv);
12287 if (rv.MaybeSetPendingException(cx)) {
12288 aes.ReportException();
12289 }
12290 } else {
12291 // 4.4. "Otherwise, enqueue a custom element upgrade reaction given
12292 // result and definition."
12293 nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
12294 }
12295
12296 return NS_OK;
12297 }
12298
12299 // 5. "Otherwise, if definition is non-null:"
12300 // 5.1. "If synchronousCustomElements is true:"
12301 if (synchronousCustomElements
26.1
'synchronousCustomElements' is true
26.1
'synchronousCustomElements' is true
) {
27
Taking true branch
12302 {
12303 // 5.1.1. "Let C be definition's constructor."
12304 CustomElementConstructor* constructor = definition->mConstructor;
12305
12306 RefPtr<Document> doc = nodeInfo->GetDocument();
12307 DocGroup* docGroup = doc->GetDocGroup();
12308
12309 // XXX: https://github.com/whatwg/dom/pull/1494
12310 // 5.1.2. Let previousRegistry be the surrounding agent's active
12311 // custom element constructor map[C] with default null.
12312 // 5.1.3. Set the surrounding agent's active custom element constructor
12313 // map[C] to registry.
12314 Maybe<DocGroup::AutoActiveConstructorRegistry>
12315 activeConstructorRegistry;
12316 if (StaticPrefs::dom_scoped_custom_element_registries_enabled() &&
28
Assuming the condition is false
12317 constructor->CallableOrNull() && docGroup) {
12318 if (aCustomElementRegistry.isSome()) {
12319 activeConstructorRegistry.emplace(docGroup, constructor,
12320 aCustomElementRegistry.ref());
12321 } else {
12322 activeConstructorRegistry.emplace(
12323 docGroup, constructor,
12324 doc->GetEffectiveGlobalCustomElementRegistry());
12325 }
12326 }
12327
12328 // 5.1.4. "Run these steps while catching any exceptions:
12329 DoCustomElementCreate(aResult, cx, doc, nodeInfo,
12330 MOZ_KnownLive(definition->mConstructor)(definition->mConstructor), rv,
12331 aFromParser);
12332
12333 // 5.1.5. If previousRegistry is null, then remove the surrounding
12334 // agent's active custom element constructor map[C]. Otherwise,
12335 // set it back to previousRegistry.
12336 // 5.1.6. Otherwise, set the surrounding agent ’s active custom element
12337 // constructor map[C] to previousRegistry.
12338 // (Handled by `activeRegistry`'s destructor during scope exit).
12339 }
12340
12341 if (rv.MaybeSetPendingException(cx)) {
29
Taking true branch
12342 // "If any of these steps threw an exception: ... Set result to the
12343 // result of creating an element internal given document,
12344 // HTMLUnknownElement..."
12345 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
30
Taking false branch
12346 NS_IF_ADDREF(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget(),ns_if_addref(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget
(), aFromParser))
12347 aFromParser))ns_if_addref(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget
(), aFromParser))
;
12348 } else {
12349 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
31
Assigning value
12350 }
12351 (*aResult)->SetDefined(false);
32
Called C++ object pointer is null
12352 // Set the fallback element's registry even on failure.
12353 if (StaticPrefs::dom_scoped_custom_element_registries_enabled()) {
12354 if (aCustomElementRegistry.isSome()) {
12355 if (CustomElementRegistry* registry =
12356 aCustomElementRegistry.ref()) {
12357 (*aResult)->SetCustomElementRegistry(registry);
12358 } else {
12359 (*aResult)->SetNullCustomElementRegistry();
12360 }
12361 }
12362 }
12363 } else if (*aResult && nodeInfo->GetPrefixAtom()) {
12364 // 5.1.3.9. Set result's namespace prefix to prefix.
12365 (*aResult)->SetNamespacePrefix(nodeInfo->GetPrefixAtom());
12366 }
12367 return NS_OK;
12368 }
12369
12370 // 5.2. "Otherwise:"
12371 // 5.2.1. "Set result to the result of creating an element internal given
12372 // document, HTMLElement, localName..."
12373 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
12374 NS_IF_ADDREF(*aResult =ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
12375 NS_NewHTMLElement(nodeInfo.forget(), aFromParser))ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
;
12376 } else {
12377 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
12378 }
12379 (*aResult)->SetCustomElementData(
12380 MakeUnique<CustomElementData>(definition->mType));
12381 // 5.2.2. "Enqueue a custom element upgrade reaction given result and
12382 // definition."
12383 nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
12384 return NS_OK;
12385 }
12386
12387 // 6. "Otherwise:"
12388 // 6.1. "Let interface be the element interface for localName and namespace."
12389 // 6.2. "Set result to the result of creating an element internal..."
12390 if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML3)) {
12391 // Per the Custom Element specification, unknown tags that are valid
12392 // custom element names should be HTMLElement instead of
12393 // HTMLUnknownElement.
12394 if (isCustomElementName) {
12395 NS_IF_ADDREF(*aResult =ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
12396 NS_NewHTMLElement(nodeInfo.forget(), aFromParser))ns_if_addref(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser
))
;
12397 } else {
12398 *aResult = CreateHTMLElement(*tag, nodeInfo.forget(), aFromParser).take();
12399 }
12400 } else {
12401 NS_IF_ADDREF(*aResult = nsXULElement::Construct(nodeInfo.forget()))ns_if_addref(*aResult = nsXULElement::Construct(nodeInfo.forget
()))
;
12402 }
12403
12404 if (!*aResult) {
12405 return NS_ERROR_OUT_OF_MEMORY;
12406 }
12407
12408 // 6.3. "If namespace is the HTML namespace, and either localName is a valid
12409 // custom element name or is is non-null, then set result's custom
12410 // element state to "undefined"."
12411 if (isCustomElement) {
12412 (*aResult)->SetCustomElementData(MakeUnique<CustomElementData>(typeAtom));
12413 if (aCustomElementRegistry.isSome()) {
12414 // When an explicit custom element registry is provided, register for
12415 // upgrade on that registry (if non-null), not the document's.
12416 if (CustomElementRegistry* registry = aCustomElementRegistry.ref()) {
12417 registry->RegisterCallbackUpgradeElement(*aResult, typeAtom);
12418 }
12419 } else {
12420 nsContentUtils::RegisterCallbackUpgradeElement(*aResult, typeAtom);
12421 }
12422 }
12423
12424 // 7. "Return result."
12425 return NS_OK;
12426}
12427
12428// https://html.spec.whatwg.org/#look-up-a-custom-element-registry
12429Maybe<RefPtr<CustomElementRegistry>> nsContentUtils::GetCustomElementRegistry(
12430 nsINode* aNode) {
12431 if (!aNode || !StaticPrefs::dom_scoped_custom_element_registries_enabled()) {
12432 return Nothing();
12433 }
12434 // 1. If node is an Element object, then return node's custom element
12435 // registry.
12436 // 2. If node is a ShadowRoot object, then return node's custom element
12437 // registry.
12438 // 3. If node is a Document object, then return node's custom element
12439 // registry.
12440 // A node specifies its own registry only when its state is not Global (i.e.
12441 // scoped, or explicitly null). A Global-state node inherits the global
12442 // registry, which we report as Nothing() so callers can fall back to a
12443 // context registry when parsing into the node.
12444 CustomElementRegistryState state = CustomElementRegistryState::Global;
12445 if (aNode->IsElement()) {
12446 state = aNode->AsElement()->GetCustomElementRegistryState();
12447 } else if (ShadowRoot* shadowRoot = ShadowRoot::FromNode(aNode)) {
12448 state = shadowRoot->GetCustomElementRegistryState();
12449 } else if (aNode->IsDocument()) {
12450 if (!aNode->AsDocument()->HasScopedCustomElementRegistry()) {
12451 // 4. Return null (reported as Nothing(): inherit the global registry).
12452 return Nothing();
12453 }
12454 state = CustomElementRegistryState::Scoped;
12455 } else {
12456 // 4. Return null.
12457 return Nothing();
12458 }
12459 if (state == CustomElementRegistryState::Global) {
12460 return Nothing();
12461 }
12462 RefPtr<CustomElementRegistry> registry;
12463 if (aNode->IsElement()) {
12464 registry = aNode->AsElement()->GetCustomElementRegistry();
12465 } else if (ShadowRoot* shadowRoot = ShadowRoot::FromNode(aNode)) {
12466 registry = shadowRoot->GetCustomElementRegistry();
12467 } else {
12468 registry = aNode->AsDocument()->GetCustomElementRegistry();
12469 }
12470 return Some(std::move(registry));
12471}
12472
12473/* https://html.spec.whatwg.org/#look-up-a-custom-element-definition */
12474CustomElementDefinition* nsContentUtils::LookupCustomElementDefinition(
12475 DocumentOrShadowRoot* aDoc, nsAtom* aNameAtom, uint32_t aNameSpaceID,
12476 nsAtom* aTypeAtom) {
12477 // 2. If namespace is not the HTML namespace, then return null.
12478 if (aNameSpaceID != kNameSpaceID_XUL8 && aNameSpaceID != kNameSpaceID_XHTML3) {
12479 return nullptr;
12480 }
12481
12482 // 1. If registry is null, then return null.
12483 // TODO(keithamus): re-order for Scoped Registries
12484 RefPtr<CustomElementRegistry> registry = aDoc->GetCustomElementRegistry();
12485 if (!registry) {
12486 return nullptr;
12487 }
12488
12489 // XXX: Steps 3-5 performed by
12490 // CustomElementRegistry::LookupCustomElementDefinition:
12491 // 3. If registry's custom element definition set contains an item with name
12492 // and local name both equal to localName, then return that item.
12493 // 4. If registry's custom element definition set contains an item with name
12494 // equal to is and local name equal to localName, then return that item.
12495 // 5. Return null.
12496 return registry->LookupCustomElementDefinition(aNameAtom, aNameSpaceID,
12497 aTypeAtom);
12498}
12499
12500/* static */
12501void nsContentUtils::RegisterCallbackUpgradeElement(Element* aElement,
12502 nsAtom* aTypeName) {
12503 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"
, 12503); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 12503); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12504
12505 CustomElementRegistry* registry = aElement->GetCustomElementRegistry();
12506 if (registry) {
12507 registry->RegisterCallbackUpgradeElement(aElement, aTypeName);
12508 }
12509}
12510
12511/* static */
12512void nsContentUtils::RegisterUnresolvedElement(Element* aElement,
12513 nsAtom* aTypeName) {
12514 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"
, 12514); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 12514); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12515
12516 CustomElementRegistry* registry = aElement->GetCustomElementRegistry();
12517 if (registry) {
12518 registry->RegisterUnresolvedElement(aElement, aTypeName);
12519 }
12520}
12521
12522/* static */
12523void nsContentUtils::UnregisterUnresolvedElement(Element* aElement) {
12524 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"
, 12524); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 12524); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12525
12526 nsAtom* typeAtom = aElement->GetCustomElementData()->GetCustomElementType();
12527 CustomElementRegistry* registry = aElement->GetCustomElementRegistry();
12528 if (registry) {
12529 registry->UnregisterUnresolvedElement(aElement, typeAtom);
12530 }
12531}
12532
12533/* static */
12534void nsContentUtils::EnqueueUpgradeReaction(
12535 Element* aElement, CustomElementDefinition* aDefinition) {
12536 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"
, 12536); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aElement" ")"
); do { MOZ_CrashSequence(__null, 12536); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12537
12538 Document* doc = aElement->OwnerDoc();
12539
12540 // No DocGroup means no custom element reactions stack.
12541 if (!doc->GetDocGroup()) {
12542 return;
12543 }
12544
12545 CustomElementReactionsStack* stack =
12546 doc->GetDocGroup()->CustomElementReactionsStack();
12547 stack->EnqueueUpgradeReaction(aElement, aDefinition);
12548}
12549
12550/* static */
12551void nsContentUtils::EnqueueLifecycleCallback(
12552 ElementCallbackType aType, Element* aCustomElement,
12553 const LifecycleCallbackArgs& aArgs, CustomElementDefinition* aDefinition) {
12554 // No DocGroup means no custom element reactions stack.
12555 if (!aCustomElement->OwnerDoc()->GetDocGroup()) {
12556 return;
12557 }
12558
12559 CustomElementRegistry::EnqueueLifecycleCallback(aType, aCustomElement, aArgs,
12560 aDefinition);
12561}
12562
12563/* static */
12564CustomElementFormValue nsContentUtils::ConvertToCustomElementFormValue(
12565 const Nullable<OwningFileOrUSVStringOrFormData>& aState) {
12566 if (aState.IsNull()) {
12567 return void_t{};
12568 }
12569 const auto& state = aState.Value();
12570 if (state.IsFile()) {
12571 RefPtr<BlobImpl> impl = state.GetAsFile()->Impl();
12572 return {std::move(impl)};
12573 }
12574 if (state.IsUSVString()) {
12575 return state.GetAsUSVString();
12576 }
12577 return state.GetAsFormData()->ConvertToCustomElementFormValue();
12578}
12579
12580/* static */
12581Nullable<OwningFileOrUSVStringOrFormData>
12582nsContentUtils::ExtractFormAssociatedCustomElementValue(
12583 nsIGlobalObject* aGlobal,
12584 const mozilla::dom::CustomElementFormValue& aCEValue) {
12585 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"
, 12585); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aGlobal" ")"
); do { MOZ_CrashSequence(__null, 12585); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12586
12587 OwningFileOrUSVStringOrFormData value;
12588 switch (aCEValue.type()) {
12589 case CustomElementFormValue::TBlobImpl: {
12590 RefPtr<File> file = File::Create(aGlobal, aCEValue.get_BlobImpl());
12591 if (NS_WARN_IF(!file)NS_warn_if_impl(!file, "!file", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12591)
) {
12592 return {};
12593 }
12594 value.SetAsFile() = file;
12595 } break;
12596
12597 case CustomElementFormValue::TnsString:
12598 value.SetAsUSVString() = aCEValue.get_nsString();
12599 break;
12600
12601 case CustomElementFormValue::TArrayOfFormDataTuple: {
12602 const auto& array = aCEValue.get_ArrayOfFormDataTuple();
12603 auto formData = MakeRefPtr<FormData>();
12604
12605 for (auto i = 0ul; i < array.Length(); ++i) {
12606 const auto& item = array.ElementAt(i);
12607 switch (item.value().type()) {
12608 case IPCFormDataValue::TnsString:
12609 formData->AddNameValuePair(item.name(),
12610 item.value().get_nsString());
12611 break;
12612
12613 case IPCFormDataValue::TBlobImpl: {
12614 auto blobImpl = item.value().get_BlobImpl();
12615 RefPtr<Blob> blob = Blob::Create(aGlobal, blobImpl);
12616 formData->AddNameBlobPair(item.name(), blob);
12617 } break;
12618
12619 default:
12620 continue;
12621 }
12622 }
12623
12624 value.SetAsFormData() = formData;
12625 } break;
12626 case CustomElementFormValue::Tvoid_t:
12627 return {};
12628 default:
12629 NS_WARNING("Invalid CustomElementContentData type!")NS_DebugBreak(NS_DEBUG_WARNING, "Invalid CustomElementContentData type!"
, nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp",
12629)
;
12630 return {};
12631 }
12632 return value;
12633}
12634
12635/* static */
12636void nsContentUtils::AppendDocumentLevelNativeAnonymousContentTo(
12637 Document* aDocument, nsTArray<nsIContent*>& aElements) {
12638 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"
, 12638); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDocument"
")"); do { MOZ_CrashSequence(__null, 12638); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12639#ifdef DEBUG1
12640 size_t oldLength = aElements.Length();
12641#endif
12642
12643 if (PresShell* presShell = aDocument->GetPresShell()) {
12644 if (ScrollContainerFrame* rootScrollContainerFrame =
12645 presShell->GetRootScrollContainerFrame()) {
12646 rootScrollContainerFrame->AppendAnonymousContentTo(aElements, 0);
12647 }
12648 if (nsCanvasFrame* canvasFrame = presShell->GetCanvasFrame()) {
12649 canvasFrame->AppendAnonymousContentTo(aElements, 0);
12650 }
12651 }
12652
12653 if (auto* el = aDocument->GetCustomContentContainer()) {
12654 aElements.AppendElement(el);
12655 }
12656
12657#ifdef DEBUG1
12658 for (size_t i = oldLength; i < aElements.Length(); i++) {
12659 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", 12661); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
") (" "Someone here has lied, or missed to flag the node" ")"
); do { MOZ_CrashSequence(__null, 12661); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
12660 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", 12661); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
") (" "Someone here has lied, or missed to flag the node" ")"
); do { MOZ_CrashSequence(__null, 12661); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
12661 "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", 12661); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aElements[i]->GetProperty(nsGkAtoms::docLevelNativeAnonymousContent)"
") (" "Someone here has lied, or missed to flag the node" ")"
); do { MOZ_CrashSequence(__null, 12661); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12662 }
12663#endif
12664}
12665
12666static void AppendNativeAnonymousChildrenFromFrame(nsIFrame* aFrame,
12667 nsTArray<nsIContent*>& aKids,
12668 uint32_t aFlags) {
12669 if (nsIAnonymousContentCreator* ac = do_QueryFrame(aFrame)) {
12670 ac->AppendAnonymousContentTo(aKids, aFlags);
12671 }
12672}
12673
12674/* static */
12675void nsContentUtils::AppendNativeAnonymousChildren(const nsIContent* aContent,
12676 nsTArray<nsIContent*>& aKids,
12677 uint32_t aFlags) {
12678 if (aContent->MayHaveAnonymousChildren()) {
12679 if (nsIFrame* primaryFrame = aContent->GetPrimaryFrame()) {
12680 // NAC created by the element's primary frame.
12681 AppendNativeAnonymousChildrenFromFrame(primaryFrame, aKids, aFlags);
12682
12683 // NAC created by any other non-primary frames for the element.
12684 AutoTArray<nsIFrame::OwnedAnonBox, 8> ownedAnonBoxes;
12685 primaryFrame->AppendOwnedAnonBoxes(ownedAnonBoxes);
12686 for (nsIFrame::OwnedAnonBox& box : ownedAnonBoxes) {
12687 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", 12687); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "box.mAnonBoxFrame->GetContent() == aContent"
")"); do { MOZ_CrashSequence(__null, 12687); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12688 AppendNativeAnonymousChildrenFromFrame(box.mAnonBoxFrame, aKids,
12689 aFlags);
12690 }
12691 }
12692
12693 // View transition pseudos.
12694 if (aContent->IsRootElement()) {
12695 if (auto* vt = aContent->OwnerDoc()->GetActiveViewTransition()) {
12696 if (auto* root = vt->GetSnapshotContainingBlock()) {
12697 aKids.AppendElement(root);
12698 }
12699 }
12700 }
12701
12702 // Get manually created NAC (editor resize handles, etc.).
12703 if (auto nac = static_cast<ManualNACArray*>(
12704 aContent->GetProperty(nsGkAtoms::manualNACProperty))) {
12705 aKids.AppendElements(*nac);
12706 }
12707 }
12708
12709 // The root scroll frame is not the primary frame of the root element.
12710 // Detect and handle this case.
12711 if (!(aFlags & nsIContent::eSkipDocumentLevelNativeAnonymousContent) &&
12712 aContent->IsRootElement()) {
12713 AppendDocumentLevelNativeAnonymousContentTo(aContent->OwnerDoc(), aKids);
12714 }
12715}
12716
12717bool nsContentUtils::IsImageAvailable(nsIContent* aLoadingNode, nsIURI* aURI,
12718 nsIPrincipal* aDefaultTriggeringPrincipal,
12719 CORSMode aCORSMode) {
12720 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
12721 QueryTriggeringPrincipal(aLoadingNode, aDefaultTriggeringPrincipal,
12722 getter_AddRefs(triggeringPrincipal));
12723 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", 12723); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "triggeringPrincipal" ")"); do { MOZ_CrashSequence
(__null, 12723); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12724
12725 Document* doc = aLoadingNode->OwnerDoc();
12726 return IsImageAvailable(aURI, triggeringPrincipal, aCORSMode, doc);
12727}
12728
12729bool nsContentUtils::IsImageAvailable(nsIURI* aURI,
12730 nsIPrincipal* aTriggeringPrincipal,
12731 CORSMode aCORSMode, Document* aDoc) {
12732 imgLoader* imgLoader = GetImgLoaderForDocument(aDoc);
12733 return imgLoader->IsImageAvailable(aURI, aTriggeringPrincipal, aCORSMode,
12734 aDoc);
12735}
12736
12737/* static */
12738bool nsContentUtils::QueryTriggeringPrincipal(
12739 nsIContent* aLoadingNode, nsIPrincipal* aDefaultPrincipal,
12740 nsIPrincipal** aTriggeringPrincipal) {
12741 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"
, 12741); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLoadingNode"
")"); do { MOZ_CrashSequence(__null, 12741); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12742 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", 12742); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aTriggeringPrincipal" ")"); do { MOZ_CrashSequence
(__null, 12742); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12743
12744 bool result = false;
12745 nsCOMPtr<nsIPrincipal> loadingPrincipal = aDefaultPrincipal;
12746 if (!loadingPrincipal) {
12747 loadingPrincipal = aLoadingNode->NodePrincipal();
12748 }
12749
12750 // If aLoadingNode is content, bail out early.
12751 if (!aLoadingNode->NodePrincipal()->IsSystemPrincipal()) {
12752 loadingPrincipal.forget(aTriggeringPrincipal);
12753 return result;
12754 }
12755
12756 nsAutoString loadingStr;
12757 if (aLoadingNode->IsElement()) {
12758 aLoadingNode->AsElement()->GetAttr(
12759 kNameSpaceID_None, nsGkAtoms::triggeringprincipal, loadingStr);
12760 }
12761
12762 // Fall back if 'triggeringprincipal' isn't specified,
12763 if (loadingStr.IsEmpty()) {
12764 loadingPrincipal.forget(aTriggeringPrincipal);
12765 return result;
12766 }
12767
12768 nsCString binary;
12769 nsCOMPtr<nsIPrincipal> serializedPrin =
12770 BasePrincipal::FromJSON(NS_ConvertUTF16toUTF8(loadingStr));
12771 if (serializedPrin) {
12772 result = true;
12773 serializedPrin.forget(aTriggeringPrincipal);
12774 }
12775
12776 if (!result) {
12777 // Fallback if the deserialization is failed.
12778 loadingPrincipal.forget(aTriggeringPrincipal);
12779 }
12780
12781 return result;
12782}
12783
12784/* static */
12785void nsContentUtils::GetContentPolicyTypeForUIImageLoading(
12786 nsIContent* aLoadingNode, nsIPrincipal** aTriggeringPrincipal,
12787 nsContentPolicyType& aContentPolicyType, uint64_t* aRequestContextID) {
12788 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", 12788); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aRequestContextID" ")"); do { MOZ_CrashSequence
(__null, 12788); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12789
12790 bool result = QueryTriggeringPrincipal(aLoadingNode, aTriggeringPrincipal);
12791 if (result) {
12792 // Set the content policy type to TYPE_INTERNAL_IMAGE_FAVICON for
12793 // indicating it's a favicon loading.
12794 aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON;
12795
12796 nsAutoString requestContextID;
12797 if (aLoadingNode->IsElement()) {
12798 aLoadingNode->AsElement()->GetAttr(
12799 kNameSpaceID_None, nsGkAtoms::requestcontextid, requestContextID);
12800 }
12801 nsresult rv;
12802 int64_t val = requestContextID.ToInteger64(&rv);
12803 *aRequestContextID = NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) ? val : 0;
12804 } else {
12805 aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE;
12806 }
12807}
12808
12809/* static */
12810nsresult nsContentUtils::CreateJSValueFromSequenceOfObject(
12811 JSContext* aCx, const Sequence<JSObject*>& aTransfer,
12812 JS::MutableHandle<JS::Value> aValue) {
12813 if (aTransfer.IsEmpty()) {
12814 return NS_OK;
12815 }
12816
12817 JS::Rooted<JSObject*> array(aCx, JS::NewArrayObject(aCx, aTransfer.Length()));
12818 if (!array) {
12819 return NS_ERROR_OUT_OF_MEMORY;
12820 }
12821
12822 for (uint32_t i = 0; i < aTransfer.Length(); ++i) {
12823 JS::Rooted<JSObject*> object(aCx, aTransfer[i]);
12824 if (!object) {
12825 continue;
12826 }
12827
12828 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", 12829)
12829 !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", 12829)
) {
12830 return NS_ERROR_OUT_OF_MEMORY;
12831 }
12832 }
12833
12834 aValue.setObject(*array);
12835 return NS_OK;
12836}
12837
12838/* static */
12839void nsContentUtils::StructuredClone(JSContext* aCx, nsIGlobalObject* aGlobal,
12840 JS::Handle<JS::Value> aValue,
12841 const StructuredSerializeOptions& aOptions,
12842 JS::MutableHandle<JS::Value> aRetval,
12843 ErrorResult& aError) {
12844 JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
12845 aError = nsContentUtils::CreateJSValueFromSequenceOfObject(
12846 aCx, aOptions.mTransfer, &transferArray);
12847 if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12847)
) {
12848 return;
12849 }
12850
12851 JS::CloneDataPolicy clonePolicy;
12852 // We are definitely staying in the same agent cluster.
12853 clonePolicy.allowIntraClusterClonableSharedObjects();
12854 if (aGlobal->IsSharedMemoryAllowed()) {
12855 clonePolicy.allowSharedMemoryObjects();
12856 }
12857
12858 // 2.7.10 Structured cloning API
12859 // Step 1: Let serialized be
12860 // ? StructuredSerializeWithTransfer(value, options["transfer"])
12861 StructuredCloneHolder holder(StructuredCloneHolder::CloningSupported,
12862 StructuredCloneHolder::TransferringSupported,
12863 JS::StructuredCloneScope::SameProcess);
12864 holder.Write(aCx, aValue, transferArray, clonePolicy, aError);
12865 if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12865)
) {
12866 return;
12867 }
12868
12869 // Step 2: Let deserializeRecord be
12870 // ? StructuredDeserializeWithTransfer(serialized, this's relevant realm).
12871 JSAutoRealm ar(aCx, aGlobal->GetGlobalJSObject());
12872 holder.Read(aCx, aRetval, clonePolicy, aError);
12873 if (NS_WARN_IF(aError.Failed())NS_warn_if_impl(aError.Failed(), "aError.Failed()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 12873)
) {
12874 return;
12875 }
12876
12877 // Step 3: Return deserializeRecord.[[Deserialized]].
12878 // (discarding deserializeRecord.[[TransferredValues]])
12879 nsTArray<RefPtr<MessagePort>> ports = holder.TakeTransferredPorts();
12880 (void)ports;
12881}
12882
12883/* static */
12884bool nsContentUtils::ShouldBlockReservedKeys(WidgetKeyboardEvent* aKeyEvent) {
12885 nsCOMPtr<nsIPrincipal> principal;
12886 RefPtr<Element> targetElement =
12887 Element::FromEventTargetOrNull(aKeyEvent->mOriginalTarget);
12888 nsCOMPtr<nsIBrowser> targetBrowser;
12889 if (targetElement) {
12890 targetBrowser = targetElement->AsBrowser();
12891 }
12892 bool isRemoteBrowser = false;
12893 if (targetBrowser) {
12894 targetBrowser->GetIsRemoteBrowser(&isRemoteBrowser);
12895 }
12896
12897 if (isRemoteBrowser) {
12898 targetBrowser->GetContentPrincipal(getter_AddRefs(principal));
12899 return principal ? nsContentUtils::IsSitePermDeny(principal, "shortcuts"_ns)
12900 : false;
12901 }
12902
12903 if (targetElement) {
12904 Document* doc = targetElement->GetUncomposedDoc();
12905 if (doc) {
12906 RefPtr<WindowContext> wc = doc->GetWindowContext();
12907 if (wc) {
12908 return wc->TopWindowContext()->GetShortcutsPermission() ==
12909 nsIPermissionManager::DENY_ACTION;
12910 }
12911 }
12912 }
12913
12914 return false;
12915}
12916
12917/**
12918 * Checks whether the given type is a supported document type for
12919 * loading within the nsObjectLoadingContent specified by aContent.
12920 *
12921 * NOTE Helper method for nsContentUtils::HtmlObjectContentTypeForMIMEType.
12922 * NOTE Does not take content policy or capabilities into account
12923 */
12924static bool HtmlObjectContentSupportsDocument(const nsCString& aMimeType) {
12925 nsCOMPtr<nsIWebNavigationInfo> info(
12926 do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID"@mozilla.org/webnavigation-info;1"));
12927 if (!info) {
12928 return false;
12929 }
12930
12931 uint32_t supported;
12932 nsresult rv = info->IsTypeSupported(aMimeType, &supported);
12933
12934 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12935 return false;
12936 }
12937
12938 if (supported != nsIWebNavigationInfo::UNSUPPORTED) {
12939 return true;
12940 }
12941
12942 // Try a stream converter
12943 // NOTE: We treat any type we can convert from as a supported type. If a
12944 // type is not actually supported, the URI loader will detect that and
12945 // return an error, and we'll fallback.
12946 nsCOMPtr<nsIStreamConverterService> convServ =
12947 do_GetService("@mozilla.org/streamConverters;1");
12948 bool canConvert = false;
12949 if (convServ) {
12950 rv = convServ->CanConvert(aMimeType.get(), "*/*", &canConvert);
12951 }
12952 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && canConvert;
12953}
12954
12955/* static */
12956uint32_t nsContentUtils::HtmlObjectContentTypeForMIMEType(
12957 const nsCString& aMIMEType, bool aIsSandboxed) {
12958 if (aMIMEType.IsEmpty()) {
12959 return nsIObjectLoadingContent::TYPE_FALLBACK;
12960 }
12961
12962 if (imgLoader::SupportImageWithMimeType(aMIMEType)) {
12963 return nsIObjectLoadingContent::TYPE_DOCUMENT;
12964 }
12965
12966 // Faking support of the PDF content as a document for EMBED tags when the
12967 // internal PDF viewer or the embedded PDF fallback is enabled.
12968 if (aMIMEType.LowerCaseEqualsLiteral(APPLICATION_PDF"application/pdf") &&
12969 (IsPDFJSEnabled() || StaticPrefs::pdfjs_embedFallback())) {
12970 // Sandboxed iframes are just never allowed to display plugins. In the
12971 // modern world, this just means "application/pdf".
12972 return aIsSandboxed ? nsIObjectLoadingContent::TYPE_FALLBACK
12973 : nsIObjectLoadingContent::TYPE_DOCUMENT;
12974 }
12975
12976 if (HtmlObjectContentSupportsDocument(aMIMEType)) {
12977 return nsIObjectLoadingContent::TYPE_DOCUMENT;
12978 }
12979
12980 return nsIObjectLoadingContent::TYPE_FALLBACK;
12981}
12982
12983/* static */
12984bool nsContentUtils::IsLocalRefURL(const nsAString& aString) {
12985 return !aString.IsEmpty() && aString[0] == '#';
12986}
12987
12988// We use only 53 bits for the ID so that it can be converted to and from a JS
12989// value without loss of precision. The upper bits of the ID hold the process
12990// ID. The lower bits identify the object itself.
12991static constexpr uint64_t kIdTotalBits = 53;
12992static constexpr uint64_t kIdProcessBits = 22;
12993static constexpr uint64_t kIdBits = kIdTotalBits - kIdProcessBits;
12994
12995/* static */
12996uint64_t nsContentUtils::GenerateProcessSpecificId(uint64_t aId) {
12997 uint64_t processId = 0;
12998 if (XRE_IsContentProcess()) {
12999 ContentChild* cc = ContentChild::GetSingleton();
13000 processId = cc->GetID();
13001 }
13002
13003 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"
, 13003); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "processId < (uint64_t(1) << kIdProcessBits)"
")"); do { MOZ_CrashSequence(__null, 13003); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13004 uint64_t processBits = processId & ((uint64_t(1) << kIdProcessBits) - 1);
13005
13006 uint64_t id = aId;
13007 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", 13007); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "id < (uint64_t(1) << kIdBits)"
")"); do { MOZ_CrashSequence(__null, 13007); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13008 uint64_t bits = id & ((uint64_t(1) << kIdBits) - 1);
13009
13010 return (processBits << kIdBits) | bits;
13011}
13012
13013/* static */
13014std::tuple<uint64_t, uint64_t> nsContentUtils::SplitProcessSpecificId(
13015 uint64_t aId) {
13016 return {aId >> kIdBits, aId & ((uint64_t(1) << kIdBits) - 1)};
13017}
13018
13019// Next process-local Tab ID.
13020static uint64_t gNextTabId = 0;
13021
13022/* static */
13023uint64_t nsContentUtils::GenerateTabId() {
13024 return GenerateProcessSpecificId(++gNextTabId);
13025}
13026
13027// Next process-local Browser ID.
13028static uint64_t gNextBrowserId = 0;
13029
13030/* static */
13031uint64_t nsContentUtils::GenerateBrowserId() {
13032 return GenerateProcessSpecificId(++gNextBrowserId);
13033}
13034
13035// Next process-local Browsing Context ID.
13036static uint64_t gNextBrowsingContextId = 0;
13037
13038/* static */
13039uint64_t nsContentUtils::GenerateBrowsingContextId() {
13040 return GenerateProcessSpecificId(++gNextBrowsingContextId);
13041}
13042
13043// Next process-local Window ID.
13044static uint64_t gNextWindowId = 0;
13045
13046/* static */
13047uint64_t nsContentUtils::GenerateWindowId() {
13048 return GenerateProcessSpecificId(++gNextWindowId);
13049}
13050
13051// Next process-local load.
13052static Atomic<uint64_t> gNextLoadIdentifier(0);
13053
13054/* static */
13055uint64_t nsContentUtils::GenerateLoadIdentifier() {
13056 return GenerateProcessSpecificId(++gNextLoadIdentifier);
13057}
13058
13059/* static */
13060bool nsContentUtils::GetUserIsInteracting() {
13061 return UserInteractionObserver::sUserActive;
13062}
13063
13064/* static */
13065bool nsContentUtils::GetSourceMapURL(nsIHttpChannel* aChannel,
13066 nsACString& aResult) {
13067 nsresult rv = aChannel->GetResponseHeader("SourceMap"_ns, aResult);
13068 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
13069 rv = aChannel->GetResponseHeader("X-SourceMap"_ns, aResult);
13070 }
13071 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)));
13072}
13073
13074/* static */
13075bool nsContentUtils::IsMessageInputEvent(const IPC::Message& aMsg) {
13076 if ((aMsg.type() & mozilla::dom::PBrowser::PBrowserStart) ==
13077 mozilla::dom::PBrowser::PBrowserStart) {
13078 switch (aMsg.type()) {
13079 case mozilla::dom::PBrowser::Msg_RealMouseMoveEvent__ID:
13080 case mozilla::dom::PBrowser::Msg_RealMouseButtonEvent__ID:
13081 case mozilla::dom::PBrowser::Msg_RealMouseEnterExitWidgetEvent__ID:
13082 case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID:
13083 case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID:
13084 case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID:
13085 case mozilla::dom::PBrowser::Msg_RealTouchMoveEvent__ID:
13086 case mozilla::dom::PBrowser::Msg_RealDragEvent__ID:
13087 case mozilla::dom::PBrowser::Msg_UpdateDimensions__ID:
13088 return true;
13089 }
13090 }
13091 return false;
13092}
13093
13094/* static */
13095bool nsContentUtils::IsMessageCriticalInputEvent(const IPC::Message& aMsg) {
13096 if ((aMsg.type() & mozilla::dom::PBrowser::PBrowserStart) ==
13097 mozilla::dom::PBrowser::PBrowserStart) {
13098 switch (aMsg.type()) {
13099 case mozilla::dom::PBrowser::Msg_RealMouseButtonEvent__ID:
13100 case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID:
13101 case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID:
13102 case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID:
13103 case mozilla::dom::PBrowser::Msg_RealDragEvent__ID:
13104 return true;
13105 }
13106 }
13107 return false;
13108}
13109
13110static const char* kUserInteractionInactive = "user-interaction-inactive";
13111static const char* kUserInteractionActive = "user-interaction-active";
13112
13113void nsContentUtils::UserInteractionObserver::Init() {
13114 // Listen for the observer messages from EventStateManager which are telling
13115 // us whether or not the user is interacting.
13116 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
13117 obs->AddObserver(this, kUserInteractionInactive, false);
13118 obs->AddObserver(this, kUserInteractionActive, false);
13119
13120 // We can't register ourselves as an annotator yet, as the
13121 // BackgroundHangMonitor hasn't started yet. It will have started by the
13122 // time we have the chance to spin the event loop.
13123 RefPtr<UserInteractionObserver> self = this;
13124 NS_DispatchToMainThread(NS_NewRunnableFunction(
13125 "nsContentUtils::UserInteractionObserver::Init",
13126 [=]() { BackgroundHangMonitor::RegisterAnnotator(*self); }));
13127}
13128
13129void nsContentUtils::UserInteractionObserver::Shutdown() {
13130 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
13131 if (obs) {
13132 obs->RemoveObserver(this, kUserInteractionInactive);
13133 obs->RemoveObserver(this, kUserInteractionActive);
13134 }
13135
13136 BackgroundHangMonitor::UnregisterAnnotator(*this);
13137}
13138
13139/**
13140 * NB: This function is always called by the BackgroundHangMonitor thread.
13141 * Plan accordingly
13142 */
13143void nsContentUtils::UserInteractionObserver::AnnotateHang(
13144 BackgroundHangAnnotations& aAnnotations) {
13145 // NOTE: Only annotate the hang report if the user is known to be interacting.
13146 if (sUserActive) {
13147 aAnnotations.AddAnnotation(u"UserInteracting"_ns, true);
13148 }
13149}
13150
13151NS_IMETHODIMPnsresult
13152nsContentUtils::UserInteractionObserver::Observe(nsISupports* aSubject,
13153 const char* aTopic,
13154 const char16_t* aData) {
13155 if (!strcmp(aTopic, kUserInteractionInactive)) {
13156 if (sUserActive && XRE_IsParentProcess()) {
13157 glean::RecordPowerMetrics();
13158 }
13159 sUserActive = false;
13160 } else if (!strcmp(aTopic, kUserInteractionActive)) {
13161 if (!sUserActive && XRE_IsParentProcess()) {
13162 glean::RecordPowerMetrics();
13163
13164 nsCOMPtr<nsIUserIdleServiceInternal> idleService =
13165 do_GetService("@mozilla.org/widget/useridleservice;1");
13166 if (idleService) {
13167 idleService->ResetIdleTimeOut(0);
13168 }
13169 }
13170
13171 sUserActive = true;
13172 } else {
13173 NS_WARNING("Unexpected observer notification")NS_DebugBreak(NS_DEBUG_WARNING, "Unexpected observer notification"
, nullptr, "/root/firefox-clang/dom/base/nsContentUtils.cpp",
13173)
;
13174 }
13175 return NS_OK;
13176}
13177
13178Atomic<bool> nsContentUtils::UserInteractionObserver::sUserActive(false);
13179NS_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"
, 13179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 13179
); __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"
, 13179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsContentUtils::UserInteractionObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 13179); __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"
, 13179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 13179
); __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"
, 13179); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsContentUtils::UserInteractionObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 13179); __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", 13179); 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; }
13180
13181/* static */
13182bool nsContentUtils::IsSpecialName(const nsAString& aName) {
13183 return aName.LowerCaseEqualsLiteral("_blank") ||
13184 aName.LowerCaseEqualsLiteral("_top") ||
13185 aName.LowerCaseEqualsLiteral("_parent") ||
13186 aName.LowerCaseEqualsLiteral("_self");
13187}
13188
13189/* static */
13190bool nsContentUtils::IsOverridingWindowName(const nsAString& aName) {
13191 return !aName.IsEmpty() && !IsSpecialName(aName);
13192}
13193
13194// Unfortunately, we can't unwrap an IDL object using only a concrete type.
13195// We need to calculate type data based on the IDL typename. Which means
13196// wrapping our templated function in a macro.
13197#define EXTRACT_EXN_VALUES(T, ...) \
13198 ExtractExceptionValuesImpl<mozilla::dom::prototypes::id::T, \
13199 T##_Binding::NativeType, T>(__VA_ARGS__) \
13200 .isOk()
13201
13202template <prototypes::ID PrototypeID, class NativeType, typename T>
13203static Result<Ok, nsresult> ExtractExceptionValuesImpl(
13204 JSContext* aCx, JS::Handle<JSObject*> aObj, nsACString& aFilename,
13205 uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) {
13206 AssertStaticUnwrapOK<PrototypeID>();
13207 RefPtr<T> exn;
13208 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(); })
;
13209
13210 if (nsCOMPtr<nsIStackFrame> location = exn->GetLocation()) {
13211 location->GetFilename(aCx, aFilename);
13212 *aLineOut = location->GetLineNumber(aCx);
13213 *aColumnOut = location->GetColumnNumber(aCx);
13214 } else {
13215 aFilename.Truncate();
13216 *aLineOut = 0;
13217 *aColumnOut = 0;
13218 }
13219
13220 exn->GetName(aMessageOut);
13221 aMessageOut.AppendLiteral(": ");
13222
13223 nsAutoString message;
13224 exn->GetMessageMoz(message);
13225 aMessageOut.Append(message);
13226 return Ok();
13227}
13228
13229/* static */
13230bool nsContentUtils::ExtractExceptionValues(
13231 JSContext* aCx, JS::Handle<JSObject*> aObj, nsACString& aFilename,
13232 uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) {
13233 return EXTRACT_EXN_VALUES(DOMException, aCx, aObj, aFilename, aLineOut,
13234 aColumnOut, aMessageOut) ||
13235 EXTRACT_EXN_VALUES(Exception, aCx, aObj, aFilename, aLineOut,
13236 aColumnOut, aMessageOut);
13237}
13238
13239/* static */
13240void nsContentUtils::ExtractErrorValues(
13241 JSContext* aCx, JS::Handle<JS::Value> aValue, nsACString& aSourceSpecOut,
13242 uint32_t* aLineOut, uint32_t* aColumnOut, nsString& aMessageOut) {
13243 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"
, 13243); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aLineOut" ")"
); do { MOZ_CrashSequence(__null, 13243); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13244 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"
, 13244); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aColumnOut"
")"); do { MOZ_CrashSequence(__null, 13244); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13245
13246 if (aValue.isObject()) {
13247 JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
13248
13249 // Try to process as an Error object. Use the file/line/column values
13250 // from the Error as they will be more specific to the root cause of
13251 // the problem.
13252 JS::BorrowedErrorReport err(aCx);
13253 if (JS_ErrorFromException(aCx, obj, err)) {
13254 // Use xpc to extract the error message only. We don't actually send
13255 // this report anywhere.
13256 RefPtr<xpc::ErrorReport> report = new xpc::ErrorReport();
13257 report->Init(err.get(),
13258 nullptr, // toString result
13259 false, // chrome
13260 0); // window ID
13261
13262 if (!report->mFileName.IsEmpty()) {
13263 aSourceSpecOut = report->mFileName;
13264 *aLineOut = report->mLineNumber;
13265 *aColumnOut = report->mColumn;
13266 }
13267 aMessageOut.Assign(report->mErrorMsg);
13268 }
13269
13270 // Next, try to unwrap the rejection value as a (DOM)Exception.
13271 else if (ExtractExceptionValues(aCx, obj, aSourceSpecOut, aLineOut,
13272 aColumnOut, aMessageOut)) {
13273 return;
13274 }
13275 }
13276
13277 // If we could not unwrap a specific error type, then perform default safe
13278 // string conversions on primitives. Objects will result in "[Object]"
13279 // unfortunately.
13280 if (aMessageOut.IsEmpty()) {
13281 nsAutoJSString jsString;
13282 if (jsString.init(aCx, aValue)) {
13283 aMessageOut = jsString;
13284 } else {
13285 JS_ClearPendingException(aCx);
13286 }
13287 }
13288}
13289
13290#undef EXTRACT_EXN_VALUES
13291
13292/* static */
13293bool nsContentUtils::ContentIsLink(nsIContent* aContent) {
13294 if (!aContent || !aContent->IsElement()) {
13295 return false;
13296 }
13297
13298 if (aContent->IsHTMLElement(nsGkAtoms::a)) {
13299 return true;
13300 }
13301
13302 return aContent->AsElement()->AttrValueIs(kNameSpaceID_XLink4, nsGkAtoms::type,
13303 nsGkAtoms::simple, eCaseMatters);
13304}
13305
13306/* static */
13307already_AddRefed<ContentFrameMessageManager>
13308nsContentUtils::TryGetBrowserChildGlobal(nsISupports* aFrom) {
13309 RefPtr<nsFrameLoaderOwner> frameLoaderOwner = do_QueryObject(aFrom);
13310 if (!frameLoaderOwner) {
13311 return nullptr;
13312 }
13313
13314 RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
13315 if (!frameLoader) {
13316 return nullptr;
13317 }
13318
13319 RefPtr<ContentFrameMessageManager> manager =
13320 frameLoader->GetBrowserChildMessageManager();
13321 return manager.forget();
13322}
13323
13324/* static */
13325Document* nsContentUtils::TryGetDocumentFromWindowGlobal(nsISupports* aFrom) {
13326 nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aFrom);
13327 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", 13327
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "window"
") (" "Expected a window global" ")"); do { MOZ_CrashSequence
(__null, 13327); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13328 if (!window) {
13329 return nullptr;
13330 }
13331 return window->GetExtantDoc();
13332}
13333
13334/* static */
13335uint32_t nsContentUtils::InnerOrOuterWindowCreated() {
13336 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", 13336); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 13336); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13337 ++sInnerOrOuterWindowCount;
13338 return ++sInnerOrOuterWindowSerialCounter;
13339}
13340
13341/* static */
13342void nsContentUtils::InnerOrOuterWindowDestroyed() {
13343 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", 13343); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 13343); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13344 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"
, 13344); AnnotateMozCrashReason("MOZ_ASSERT" "(" "sInnerOrOuterWindowCount > 0"
")"); do { MOZ_CrashSequence(__null, 13344); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13345 --sInnerOrOuterWindowCount;
13346}
13347
13348static bool JSONCreator(const char16_t* aBuf, uint32_t aLen, void* aData) {
13349 nsAString* result = static_cast<nsAString*>(aData);
13350 return result->Append(aBuf, aLen, fallible);
13351}
13352
13353/* static */
13354bool nsContentUtils::StringifyJSON(JSContext* aCx, JS::Handle<JS::Value> aValue,
13355 nsAString& aOutStr, JSONBehavior aBehavior) {
13356 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"
, 13356); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aCx" ")");
do { MOZ_CrashSequence(__null, 13356); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13357 switch (aBehavior) {
13358 case UndefinedIsNullStringLiteral: {
13359 aOutStr.Truncate();
13360 JS::Rooted<JS::Value> value(aCx, aValue);
13361 return JS_Stringify(aCx, &value, nullptr, JS::NullHandleValue,
13362 JSONCreator, &aOutStr);
13363 }
13364 case UndefinedIsVoidString: {
13365 aOutStr.SetIsVoid(true);
13366 return JS::ToJSON(aCx, aValue, nullptr, JS::NullHandleValue, JSONCreator,
13367 &aOutStr);
13368 }
13369 default:
13370 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"
, 13370); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Invalid value for aBehavior" ")"
); do { MOZ_CrashSequence(__null, 13370); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13371 return false;
13372 }
13373}
13374
13375/* static */
13376bool nsContentUtils::
13377 HighPriorityEventPendingForTopLevelDocumentBeforeContentfulPaint(
13378 Document* aDocument) {
13379 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", 13380); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "XRE_IsContentProcess()" ") (" "This function only makes sense in content processes"
")"); do { MOZ_CrashSequence(__null, 13380); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13380 "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", 13380); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "XRE_IsContentProcess()" ") (" "This function only makes sense in content processes"
")"); do { MOZ_CrashSequence(__null, 13380); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13381
13382 if (aDocument && !aDocument->IsLoadedAsData()) {
13383 if (nsPresContext* presContext = FindPresContextForDocument(aDocument)) {
13384 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", 13385
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!presContext->IsChrome()"
") (" "Should never have a chrome PresContext in a content process"
")"); do { MOZ_CrashSequence(__null, 13385); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13385 "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", 13385
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!presContext->IsChrome()"
") (" "Should never have a chrome PresContext in a content process"
")"); do { MOZ_CrashSequence(__null, 13385); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13386
13387 return !presContext->GetInProcessRootContentDocumentPresContext()
13388 ->HadFirstContentfulPaint() &&
13389 nsThreadManager::MainThreadHasPendingHighPriorityEvents();
13390 }
13391 }
13392 return false;
13393}
13394
13395static nsGlobalWindowInner* GetInnerWindowForGlobal(nsIGlobalObject* aGlobal) {
13396 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", 13396); return
nullptr; } } while (false)
;
13397
13398 if (auto* window = aGlobal->GetAsInnerWindow()) {
13399 return nsGlobalWindowInner::Cast(window);
13400 }
13401
13402 // When Extensions run content scripts inside a sandbox, it uses
13403 // sandboxPrototype to make them appear as though they're running in the
13404 // scope of the page. So when a content script invokes postMessage, it expects
13405 // the |source| of the received message to be the window set as the
13406 // sandboxPrototype. This used to work incidentally for unrelated reasons, but
13407 // now we need to do some special handling to support it.
13408 JS::Rooted<JSObject*> scope(RootingCx(), aGlobal->GetGlobalJSObject());
13409 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", 13409); return
nullptr; } } while (false)
;
13410
13411 if (xpc::IsSandbox(scope)) {
13412 AutoJSAPI jsapi;
13413 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", 13413); AnnotateMozCrashReason
("MOZ_CRASH(" "jsapi.Init(scope)" ")"); do { MOZ_CrashSequence
(__null, 13413); __attribute__((nomerge)) ::abort(); } while (
false); } while (false); } } while (false)
;
13414 JSContext* cx = jsapi.cx();
13415 // Our current Realm on aCx is the sandbox. Using that for unwrapping
13416 // makes sense: if the sandbox can unwrap the window, we can use it.
13417 return xpc::SandboxWindowOrNull(scope, cx);
13418 }
13419
13420 // The calling window must be holding a reference, so we can return a weak
13421 // pointer.
13422 return nsGlobalWindowInner::Cast(aGlobal->GetAsInnerWindow());
13423}
13424
13425/* static */
13426nsGlobalWindowInner* nsContentUtils::IncumbentInnerWindow() {
13427 return GetInnerWindowForGlobal(GetIncumbentGlobal());
13428}
13429
13430/* static */
13431nsGlobalWindowInner* nsContentUtils::EntryInnerWindow() {
13432 return GetInnerWindowForGlobal(GetEntryGlobal());
13433}
13434
13435/* static */
13436bool nsContentUtils::IsURIInPrefList(nsIURI* aURI, const char* aPrefName) {
13437 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"
, 13437); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPrefName"
")"); do { MOZ_CrashSequence(__null, 13437); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13438
13439 nsAutoCString list;
13440 Preferences::GetCString(aPrefName, list);
13441 ToLowerCase(list);
13442 return IsURIInList(aURI, list);
13443}
13444
13445/* static */
13446bool nsContentUtils::IsURIInList(nsIURI* aURI, const nsCString& aList) {
13447#ifdef DEBUG1
13448 nsAutoCString listLowerCase(aList);
13449 ToLowerCase(listLowerCase);
13450 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"
, 13451); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listLowerCase.Equals(aList)"
") (" "The aList argument should be lower-case" ")"); do { MOZ_CrashSequence
(__null, 13451); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
13451 "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"
, 13451); AnnotateMozCrashReason("MOZ_ASSERT" "(" "listLowerCase.Equals(aList)"
") (" "The aList argument should be lower-case" ")"); do { MOZ_CrashSequence
(__null, 13451); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13452#endif
13453
13454 if (!aURI) {
13455 return false;
13456 }
13457
13458 if (aList.IsEmpty()) {
13459 return false;
13460 }
13461
13462 nsAutoCString scheme;
13463 aURI->GetScheme(scheme);
13464 if (!scheme.EqualsLiteral("http") && !scheme.EqualsLiteral("https")) {
13465 return false;
13466 }
13467
13468 // The list is comma separated domain list. Each item may start with "*.".
13469 // If starts with "*.", it matches any sub-domains.
13470
13471 nsCCharSeparatedTokenizer tokenizer(aList, ',');
13472 while (tokenizer.hasMoreTokens()) {
13473 const nsCString token(tokenizer.nextToken());
13474
13475 nsAutoCString host;
13476 aURI->GetHost(host);
13477 if (host.IsEmpty()) {
13478 return false;
13479 }
13480 ToLowerCase(host);
13481
13482 for (;;) {
13483 int32_t index = token.Find(host);
13484 if (index >= 0 &&
13485 static_cast<uint32_t>(index) + host.Length() <= token.Length()) {
13486 // If we found a full match, return true.
13487 size_t indexAfterHost = index + host.Length();
13488 if (index == 0 && indexAfterHost == token.Length()) {
13489 return true;
13490 }
13491 // If next character is '/', we need to check the path too.
13492 // We assume the path in the list means "/foo" + "*".
13493 if (token[indexAfterHost] == '/') {
13494 nsDependentCSubstring pathInList(
13495 token, indexAfterHost,
13496 static_cast<nsDependentCSubstring::size_type>(-1));
13497 nsAutoCString filePath;
13498 aURI->GetFilePath(filePath);
13499 ToLowerCase(filePath);
13500 if (StringBeginsWith(filePath, pathInList) &&
13501 (filePath.Length() == pathInList.Length() ||
13502 pathInList.EqualsLiteral("/") ||
13503 filePath[pathInList.Length() - 1] == '/' ||
13504 filePath[pathInList.Length() - 1] == '?' ||
13505 filePath[pathInList.Length() - 1] == '#')) {
13506 return true;
13507 }
13508 }
13509 }
13510 int32_t startIndexOfCurrentLevel = host[0] == '*' ? 1 : 0;
13511 int32_t startIndexOfNextLevel =
13512 host.Find(".", startIndexOfCurrentLevel + 1);
13513 if (startIndexOfNextLevel <= 0) {
13514 break;
13515 }
13516 host.ReplaceLiteral(0, startIndexOfNextLevel, "*");
13517 }
13518 }
13519
13520 return false;
13521}
13522
13523/* static */
13524LayoutDeviceIntMargin nsContentUtils::GetWindowSafeAreaInsets(
13525 nsIScreen* aScreen, const LayoutDeviceIntMargin& aSafeAreaInsets,
13526 const LayoutDeviceIntRect& aWindowRect) {
13527 // This calculates safe area insets of window from screen rectangle, window
13528 // rectangle and safe area insets of screen.
13529 //
13530 // +----------------------------------------+ <-- screen
13531 // | +-------------------------------+ <------- window
13532 // | | window's safe area inset top) | |
13533 // +--+-------------------------------+--+ |
13534 // | | | |<------ safe area rectangle of
13535 // | | | | | screen
13536 // +--+-------------------------------+--+ |
13537 // | |window's safe area inset bottom| |
13538 // | +-------------------------------+ |
13539 // +----------------------------------------+
13540 //
13541 LayoutDeviceIntMargin windowSafeAreaInsets;
13542 if (windowSafeAreaInsets == aSafeAreaInsets) {
13543 // no safe area insets.
13544 return windowSafeAreaInsets;
13545 }
13546
13547 const LayoutDeviceIntRect screenRect = aScreen->GetRect();
13548 LayoutDeviceIntRect safeAreaRect = screenRect;
13549 safeAreaRect.Deflate(aSafeAreaInsets);
13550
13551 // FIXME(bug 1754323): This can trigger because the screen rect is not
13552 // orientation-aware.
13553 // MOZ_ASSERT(screenRect.Contains(windowRect),
13554 // "Screen doesn't contain window rect? Something seems off");
13555
13556 // window's rect of safe area
13557 safeAreaRect = safeAreaRect.Intersect(aWindowRect);
13558
13559 windowSafeAreaInsets.top = safeAreaRect.y - aWindowRect.y;
13560 windowSafeAreaInsets.left = safeAreaRect.x - aWindowRect.x;
13561 windowSafeAreaInsets.right =
13562 aWindowRect.x + aWindowRect.width - (safeAreaRect.x + safeAreaRect.width);
13563 windowSafeAreaInsets.bottom = aWindowRect.y + aWindowRect.height -
13564 (safeAreaRect.y + safeAreaRect.height);
13565
13566 windowSafeAreaInsets.EnsureAtLeast(LayoutDeviceIntMargin());
13567 // This shouldn't be needed, but it wallpapers orientation issues, see bug
13568 // 1754323.
13569 windowSafeAreaInsets.EnsureAtMost(aSafeAreaInsets);
13570
13571 return windowSafeAreaInsets;
13572}
13573
13574/* static */
13575nsContentUtils::SubresourceCacheValidationInfo
13576nsContentUtils::GetSubresourceCacheValidationInfo(nsIRequest* aRequest,
13577 nsIURI* aURI) {
13578 SubresourceCacheValidationInfo info;
13579 if (nsCOMPtr<nsICacheInfoChannel> cache = do_QueryInterface(aRequest)) {
13580 uint32_t value = 0;
13581 if (NS_SUCCEEDED(cache->GetCacheTokenExpirationTime(&value))((bool)(__builtin_expect(!!(!NS_FAILED_impl(cache->GetCacheTokenExpirationTime
(&value))), 1)))
) {
13582 // NOTE: If the cache doesn't expire, the value should be
13583 // nsICacheEntry::NO_EXPIRATION_TIME.
13584 info.mExpirationTime.emplace(CacheExpirationTime::ExpireAt(value));
13585 }
13586 }
13587
13588 // Determine whether the cache entry must be revalidated when we try to use
13589 // it. Currently, only HTTP specifies this information...
13590 if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest)) {
13591 (void)httpChannel->IsNoStoreResponse(&info.mMustRevalidate);
13592
13593 if (!info.mMustRevalidate) {
13594 (void)httpChannel->IsNoCacheResponse(&info.mMustRevalidate);
13595 }
13596
13597 if (!info.mMustRevalidate) {
13598 nsAutoCString vary;
13599 (void)httpChannel->GetResponseHeader("vary"_ns, vary);
13600 info.mMustRevalidate = [&] {
13601 for (const nsACString& token :
13602 nsCCharSeparatedTokenizer(vary, ',').ToRange()) {
13603 if (token.EqualsLiteral("*")) {
13604 return true;
13605 }
13606 if (token.EqualsIgnoreCase("cookie")) {
13607 return true;
13608 }
13609 }
13610 return false;
13611 }();
13612 }
13613 }
13614
13615 // data: URIs are safe to cache across documents under any circumstance, so we
13616 // special-case them here even though the channel itself doesn't have any
13617 // caching policy. Same for chrome:// uris.
13618 //
13619 // TODO(emilio): Figure out which other schemes that don't have caching
13620 // policies are safe to cache. Blobs should be...
13621 const bool knownCacheable = [&] {
13622 if (!aURI) {
13623 return false;
13624 }
13625 if (aURI->SchemeIs("data") || aURI->SchemeIs("moz-page-thumb") ||
13626 aURI->SchemeIs("moz-newtab-wallpaper") ||
13627 aURI->SchemeIs("moz-extension")) {
13628 return true;
13629 }
13630 if (aURI->SchemeIs("chrome") || aURI->SchemeIs("resource")) {
13631 return !StaticPrefs::nglayout_debug_disable_xul_cache();
13632 }
13633 return false;
13634 }();
13635
13636 if (knownCacheable) {
13637 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", 13637); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!info.mExpirationTime" ")"); do { MOZ_CrashSequence
(__null, 13637); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13638 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", 13638); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!info.mMustRevalidate" ")"); do { MOZ_CrashSequence
(__null, 13638); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13639 info.mExpirationTime = Some(CacheExpirationTime::Never());
13640 }
13641
13642 return info;
13643}
13644
13645CacheExpirationTime nsContentUtils::GetSubresourceCacheExpirationTime(
13646 nsIRequest* aRequest, nsIURI* aURI) {
13647 auto info = GetSubresourceCacheValidationInfo(aRequest, aURI);
13648
13649 // For now, we never cache entries that we have to revalidate, or whose
13650 // channel don't support caching.
13651 if (info.mMustRevalidate || !info.mExpirationTime) {
13652 return CacheExpirationTime::AlreadyExpired();
13653 }
13654 return *info.mExpirationTime;
13655}
13656
13657/* static */
13658bool nsContentUtils::ShouldBypassSubResourceCache(Document* aDoc) {
13659 RefPtr<nsILoadGroup> lg = aDoc->GetDocumentLoadGroup();
13660 if (!lg) {
13661 return false;
13662 }
13663 nsLoadFlags flags;
13664 if (NS_FAILED(lg->GetLoadFlags(&flags))((bool)(__builtin_expect(!!(NS_FAILED_impl(lg->GetLoadFlags
(&flags))), 0)))
) {
13665 return false;
13666 }
13667 return flags & (nsIRequest::LOAD_BYPASS_CACHE |
13668 nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE);
13669}
13670
13671nsCString nsContentUtils::TruncatedURLForDisplay(nsIURI* aURL, size_t aMaxLen) {
13672 nsCString spec;
13673 if (aURL) {
13674 aURL->GetSpec(spec);
13675 spec.Truncate(std::min(aMaxLen, spec.Length()));
13676 }
13677 return spec;
13678}
13679
13680/* static */
13681nsresult nsContentUtils::AnonymizeId(nsAString& aId,
13682 const nsACString& aOriginKey,
13683 OriginFormat aFormat) {
13684 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", 13684); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 13684); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13685
13686 nsresult rv;
13687 nsCString rawKey;
13688 if (aFormat == OriginFormat::Base64) {
13689 rv = Base64Decode(aOriginKey, rawKey);
13690 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"
, 13690); return rv; } } while (false)
;
13691 } else {
13692 rawKey = aOriginKey;
13693 }
13694
13695 HMAC hmac;
13696 rv = hmac.Begin(
13697 SEC_OID_SHA256,
13698 Span(reinterpret_cast<const uint8_t*>(rawKey.get()), rawKey.Length()));
13699 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"
, 13699); return rv; } } while (false)
;
13700
13701 NS_ConvertUTF16toUTF8 id(aId);
13702 rv = hmac.Update(reinterpret_cast<const uint8_t*>(id.get()), id.Length());
13703 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"
, 13703); return rv; } } while (false)
;
13704
13705 nsTArray<uint8_t> macBytes;
13706 rv = hmac.End(macBytes);
13707 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"
, 13707); return rv; } } while (false)
;
13708
13709 nsCString macBase64;
13710 rv = Base64Encode(
13711 nsDependentCSubstring(reinterpret_cast<const char*>(macBytes.Elements()),
13712 macBytes.Length()),
13713 macBase64);
13714 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"
, 13714); return rv; } } while (false)
;
13715
13716 CopyUTF8toUTF16(macBase64, aId);
13717 return NS_OK;
13718}
13719
13720void nsContentUtils::RequestGeckoTaskBurst() {
13721 nsCOMPtr<nsIAppShell> appShell = do_GetService(NS_APPSHELL_CID{0x2d96b3df, 0xc051, 0x11d1, {0xa8, 0x27, 0x00, 0x40, 0x95, 0x9a
, 0x28, 0xc9}}
);
13722 if (appShell) {
13723 appShell->GeckoTaskBurst();
13724 }
13725}
13726
13727nsIContent* nsContentUtils::GetClosestLinkInFlatTree(nsIContent* aContent) {
13728 for (nsIContent* content = aContent; content;
13729 content = content->GetFlattenedTreeParent()) {
13730 if (nsContentUtils::IsDraggableLink(content)) {
13731 return content;
13732 }
13733 }
13734 return nullptr;
13735}
13736
13737template <TreeKind aKind>
13738MOZ_ALWAYS_INLINEinline const nsINode* GetParent(const nsINode* aNode) {
13739 if constexpr (aKind == TreeKind::DOM) {
13740 return aNode->GetParentNode();
13741 } else if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
13742 return aNode->GetParentOrShadowHostNode();
13743 } else if constexpr (aKind == TreeKind::FlatForSelection) {
13744 return aNode->GetFlattenedTreeParentNodeForSelection();
13745 } else if constexpr (aKind == TreeKind::Flat) {
13746 return aNode->GetFlattenedTreeParentNode();
13747 } else {
13748 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"
, 13748); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Handle the new TreeKind value" ")"
); do { MOZ_CrashSequence(__null, 13748); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); __builtin_unreachable
(); } while (false)
;
13749 }
13750}
13751
13752template <TreeKind aKind>
13753Maybe<int32_t> nsContentUtils::GetIndexInParent(
13754 const nsINode* aParent, const nsIContent* aPossibleChild) {
13755 const Maybe<uint32_t> idx = [&]() {
13756 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
13757 return aParent->ComputeIndexOf(aPossibleChild);
13758 } else {
13759 return aParent->ComputeIndexOf<aKind>(aPossibleChild);
13760 }
13761 }();
13762 if (idx) {
13763 return idx.map([](auto i) { return AssertedCast<int32_t>(i); });
13764 }
13765
13766 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
13767 if (const auto* sr = ShadowRoot::FromNode(aPossibleChild)) {
13768 return sr->GetHost() == aParent ? Some(-1) : Nothing();
13769 }
13770 }
13771
13772 // Handle pseudo-element and anonymous node ordering:
13773 // ::backdrop -> ::marker -> ::checkmark -> ::before -> regular siblings ->
13774 // all other NAC -> ::after -> ::picker-icon
13775 // This matches the order of AllChildrenIterator.
13776 if (NS_WARN_IF(!aPossibleChild->IsRootOfNativeAnonymousSubtree())NS_warn_if_impl(!aPossibleChild->IsRootOfNativeAnonymousSubtree
(), "!aPossibleChild->IsRootOfNativeAnonymousSubtree()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13776)
) {
13777 // If aNode is mid unbind, we can reach this.
13778 return Nothing();
13779 }
13780
13781 if (NS_WARN_IF(aPossibleChild->GetParentNode() != aParent)NS_warn_if_impl(aPossibleChild->GetParentNode() != aParent
, "aPossibleChild->GetParentNode() != aParent", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13781)
) {
13782 // We can't be an anon child if not correctly parented.
13783 return Nothing();
13784 }
13785
13786 if (aPossibleChild->IsGeneratedContentContainerForBackdrop()) {
13787 return Some(-5);
13788 }
13789
13790 if (aPossibleChild->IsGeneratedContentContainerForMarker()) {
13791 return Some(-4);
13792 }
13793
13794 if (aPossibleChild->IsGeneratedContentContainerForCheckmark()) {
13795 return Some(-3);
13796 }
13797
13798 if (aPossibleChild->IsGeneratedContentContainerForBefore()) {
13799 return Some(-2);
13800 }
13801
13802 AutoTArray<nsIContent*, 8> anonKids;
13803
13804 // Regular children are indexed via ComputeIndexOf (range [0, GetChildCount))
13805 // for both DOM and ShadowIncludingDOM above; only the flat tree indexes them
13806 // via the flattened iterator. Trailing NAC must be based at the matching
13807 // count so it lands after the regular children in the same index space.
13808 const int32_t siblingCount = [&]() -> uint32_t {
13809 if constexpr (aKind == TreeKind::ShadowIncludingDOM) {
13810 return aParent->GetChildCount();
13811 } else {
13812 return aParent->GetChildCount<aKind>();
13813 }
13814 }();
13815
13816 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", 13816); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aParent->MayHaveAnonymousChildren()" ")"
); do { MOZ_CrashSequence(__null, 13816); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
13817 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", 13817); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aParent->IsContent()" ")"); do { MOZ_CrashSequence
(__null, 13817); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13818 nsContentUtils::AppendNativeAnonymousChildren(aParent->AsContent(), anonKids,
13819 nsIContent::eAllChildren);
13820
13821 if (aPossibleChild->IsGeneratedContentContainerForAfter()) {
13822 return Some(int32_t(siblingCount + anonKids.Length()));
13823 }
13824
13825 if (aPossibleChild->IsGeneratedContentContainerForPickerIcon()) {
13826 return Some(int32_t(siblingCount + anonKids.Length()) + 1);
13827 }
13828
13829 auto index = anonKids.IndexOf(aPossibleChild);
13830 if (index == decltype(anonKids)::NoIndex) {
13831 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", 13833
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
"Missing parent -> child link somehow?" "Potentially unstable ordering"
")"); do { MOZ_CrashSequence(__null, 13833); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13832 "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", 13833
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
"Missing parent -> child link somehow?" "Potentially unstable ordering"
")"); do { MOZ_CrashSequence(__null, 13833); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
13833 "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", 13833
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
"Missing parent -> child link somehow?" "Potentially unstable ordering"
")"); do { MOZ_CrashSequence(__null, 13833); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13834 return Nothing();
13835 }
13836 return Some(siblingCount + int32_t(index));
13837}
13838
13839template <TreeKind aTreeKind>
13840int32_t nsContentUtils::CompareTreePosition(const nsINode* aNode1,
13841 const nsINode* aNode2,
13842 const nsINode* aCommonAncestor,
13843 NodeIndexCache* aCache) {
13844 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", 13844
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode1" ") (" "aNode1 must not be null"
")"); do { MOZ_CrashSequence(__null, 13844); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13845 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", 13845
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aNode2" ") (" "aNode2 must not be null"
")"); do { MOZ_CrashSequence(__null, 13845); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13846
13847 if (NS_WARN_IF(aNode1 == aNode2)NS_warn_if_impl(aNode1 == aNode2, "aNode1 == aNode2", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13847)
) {
13848 return 0;
13849 }
13850
13851 // TODO: Maybe handle flat tree too or other common cases?
13852 if constexpr (aTreeKind == TreeKind::DOM ||
13853 aTreeKind == TreeKind::ShadowIncludingDOM) {
13854 if (aNode1->GetNextSibling() == aNode2) {
13855 return -1;
13856 }
13857 if (aNode1->GetPreviousSibling() == aNode2) {
13858 return 1;
13859 }
13860 }
13861
13862 AutoTArray<const nsINode*, 32> node1Ancestors;
13863 const nsINode* c1;
13864 for (c1 = aNode1; c1 && c1 != aCommonAncestor;
13865 c1 = GetParent<aTreeKind>(c1)) {
13866 node1Ancestors.AppendElement(c1);
13867 }
13868 if (!c1 && aCommonAncestor) {
13869 // So, it turns out aCommonAncestor was not an ancestor of c1. Oops.
13870 // Never mind. We can continue as if aCommonAncestor was null.
13871 aCommonAncestor = nullptr;
13872 }
13873
13874 AutoTArray<const nsINode*, 32> node2Ancestors;
13875 const nsINode* c2;
13876 for (c2 = aNode2; c2 && c2 != aCommonAncestor;
13877 c2 = GetParent<aTreeKind>(c2)) {
13878 node2Ancestors.AppendElement(c2);
13879 }
13880 if (!c2 && aCommonAncestor) {
13881 // So, it turns out aCommonAncestor was not an ancestor of c2.
13882 // We need to retry with no common ancestor hint.
13883 return CompareTreePosition<aTreeKind>(aNode1, aNode2, nullptr, aCache);
13884 }
13885
13886 // FIXME: Looks like that some of this can be rewritten with CommonAncestors.
13887 int last1 = node1Ancestors.Length() - 1;
13888 int last2 = node2Ancestors.Length() - 1;
13889 const nsINode* node1Ancestor = nullptr;
13890 const nsINode* node2Ancestor = nullptr;
13891 while (last1 >= 0 && last2 >= 0 &&
13892 ((node1Ancestor = node1Ancestors.ElementAt(last1)) ==
13893 (node2Ancestor = node2Ancestors.ElementAt(last2)))) {
13894 last1--;
13895 last2--;
13896 }
13897
13898 if (last1 < 0) {
13899 if (last2 < 0) {
13900 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"
, 13900); MOZ_PretendNoReturn(); } } while (0)
;
13901 return 0;
13902 }
13903 // aContent1 is an ancestor of aContent2
13904 return -1;
13905 }
13906
13907 if (last2 < 0) {
13908 // aContent2 is an ancestor of aContent1
13909 return 1;
13910 }
13911 // node1Ancestor != node2Ancestor, so they must be siblings with the
13912 // same parent
13913 const nsINode* parent = GetParent<aTreeKind>(node1Ancestor);
13914 if (NS_WARN_IF(!parent)NS_warn_if_impl(!parent, "!parent", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13914)
) { // different documents??
13915 return 0;
13916 }
13917 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", 13917); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "node1Ancestor" ")"); do { MOZ_CrashSequence
(__null, 13917); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13918 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", 13918); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "node2Ancestor" ")"); do { MOZ_CrashSequence
(__null, 13918); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
13919 Maybe<int32_t> index1;
13920 Maybe<int32_t> index2;
13921 // node1Ancestor and node2Ancestor must be children of parent so that they
13922 // must be content nodes if we can get the indices.
13923 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"
, 13923); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "node1Ancestor->IsContent()"
")"); do { MOZ_CrashSequence(__null, 13923); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13924 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"
, 13924); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "node2Ancestor->IsContent()"
")"); do { MOZ_CrashSequence(__null, 13924); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
13925 if (aCache) {
13926 aCache->ComputeIndicesOf<aTreeKind>(parent, node1Ancestor->AsContent(),
13927 node2Ancestor->AsContent(), index1,
13928 index2);
13929 } else {
13930 index1 = GetIndexInParent<aTreeKind>(parent, node1Ancestor->AsContent());
13931 index2 = GetIndexInParent<aTreeKind>(parent, node2Ancestor->AsContent());
13932 }
13933 if (NS_WARN_IF(index1.isNothing())NS_warn_if_impl(index1.isNothing(), "index1.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13933)
|| NS_WARN_IF(index2.isNothing())NS_warn_if_impl(index2.isNothing(), "index2.isNothing()", "/root/firefox-clang/dom/base/nsContentUtils.cpp"
, 13933)
) {
13934 // This should generally never happen, but can happen mid-unbind or in other
13935 // edge cases, deal with it somewhat reasonably.
13936 return 0;
13937 }
13938 return static_cast<int32_t>(static_cast<int64_t>(*index1) - *index2);
13939}
13940
13941nsIContent* nsContentUtils::AttachDeclarativeShadowRoot(
13942 nsIContent* aHost, ShadowRootMode aMode, bool aIsClonable,
13943 bool aIsSerializable, bool aDelegatesFocus, bool aCustomElementRegistry,
13944 SlotAssignmentMode aSlotAssignment, const nsAString& aReferenceTarget) {
13945 RefPtr<Element> host = mozilla::dom::Element::FromNodeOrNull(aHost);
13946 if (!host || host->GetShadowRoot()) {
13947 // https://html.spec.whatwg.org/#parsing-main-inhead:shadow-host
13948 return nullptr;
13949 }
13950
13951 ShadowRootInit init;
13952 init.mMode = aMode;
13953 init.mDelegatesFocus = aDelegatesFocus;
13954 init.mSlotAssignment = aSlotAssignment;
13955 init.mClonable = aIsClonable;
13956 init.mSerializable = aIsSerializable;
13957 // https://html.spec.whatwg.org/#current-template-insertion-mode
13958 // "Let registry be null if templateStartTag has a
13959 // shadowrootcustomelementregistry attribute; otherwise
13960 // declarativeShadowHostElement's node document's custom element registry."
13961 if (StaticPrefs::dom_scoped_custom_element_registries_enabled()) {
13962 if (aCustomElementRegistry) {
13963 init.mCustomElementRegistry.Construct(nullptr);
13964 } else {
13965 init.mCustomElementRegistry.Construct(
13966 host->OwnerDoc()->GetCustomElementRegistry());
13967 }
13968 }
13969
13970 RefPtr shadowRoot = host->AttachShadow(init, IgnoreErrors());
13971 if (shadowRoot) {
13972 shadowRoot->SetIsDeclarative(
13973 nsGenericHTMLFormControlElement::ShadowRootDeclarative::Yes);
13974 // https://html.spec.whatwg.org/#parsing-main-inhead
13975 // 7. If templateStartTag has a shadowrootcustomelementregistry attribute,
13976 // set shadow's keep custom element registry null to true.
13977 if (StaticPrefs::dom_scoped_custom_element_registries_enabled() &&
13978 aCustomElementRegistry) {
13979 shadowRoot->SetKeepCustomElementRegistryNull();
13980 }
13981 // https://html.spec.whatwg.org/#parsing-main-inhead:available-to-element-internals
13982 shadowRoot->SetAvailableToElementInternals();
13983 shadowRoot->SetReferenceTarget(aReferenceTarget);
13984 }
13985 return shadowRoot;
13986}
13987
13988// https://html.spec.whatwg.org/#the-navigation-must-be-a-replace
13989/* static */ bool nsContentUtils::NavigationMustBeAReplace(
13990 nsIURI& aURI, const Document& aDocument) {
13991 // The navigation must be a replace, given a URL url and a Document document,
13992 // if any of the following are true:
13993 // - url's scheme is "javascript"; or
13994 // - document's is initial about:blank is true.
13995 return aURI.SchemeIs("javascript") ||
13996 (NS_IsAboutBlank(aDocument.GetDocumentURI()) &&
13997 aDocument.IsInitialDocument());
13998}
13999
14000template int32_t nsContentUtils::CompareTreePosition<TreeKind::DOM>(
14001 const nsINode*, const nsINode*, const nsINode*, NodeIndexCache*);
14002template int32_t
14003nsContentUtils::CompareTreePosition<TreeKind::ShadowIncludingDOM>(
14004 const nsINode*, const nsINode*, const nsINode*, NodeIndexCache*);
14005template int32_t
14006nsContentUtils::CompareTreePosition<TreeKind::FlatForSelection>(
14007 const nsINode*, const nsINode*, const nsINode*, NodeIndexCache*);
14008template int32_t nsContentUtils::CompareTreePosition<TreeKind::Flat>(
14009 const nsINode*, const nsINode*, const nsINode*, NodeIndexCache*);

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

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